본문 바로가기

Spring

설정 파일을 통한 환경별 Property 관리

개요 : 설정 파일을 통한 환경별 Property 관리 필요성

  • 이번에 알림톡, 푸시 알림 기능을 프로젝트에 추가하였다. 
  • 개발 환경에서 테스트를 할 때 실제 사용자들에게 알림톡, 푸시 알림이 가는 것을 방지해야 한다.
  • 물론 일반적으로는 개발 환경에서는 개발용 DB를 따로 사용할 것이다.
  • 그런데 현재 개발용 DB로 운영 DB를 덤프 떠서 사용 중이다.
  • 따라서 개발 환경에서 알림톡, 푸시 알림 관련 로직을 실행할 때 목적지를 개발자의 핸드폰으로 바꿔주는 절차가 필요했다.

 

환경별로 다른 설정 파일 로드하기

Spring Boot에서는 프로파일을 사용하여 환경별로 다른 설정 파일을 로드하고 애플리케이션을 실행할 수 있다.

  1. 프로파일별 yml 파일 작성
    각 프로파일에 맞는 application-{profile}.yml 파일을 작성한다. 예를 들어, application-local.yml, application-qa.yml, application-prod.yml 파일을 만든다.
  2. application.yml 설정 
    application.yml 파일에서 기본 설정을 정의할 수 있다. 이 파일은 모든 프로파일에 공통으로 적용된다.
  3. 프로파일 활성화
    Spring Boot 애플리케이션을 실행할 때 spring.profiles.active 속성을 사용하여 활성화할 프로파일을 지정한다. 이를 통해 해당 프로파일에 맞는 yml 파일이 로드된다.
  4. 프로파일별로 다른 설정 로드
    설정 파일의 이름은 application-{profile}.yml 형식을 따른다. 예를 들어, application-local.yml 파일은 local 프로파일이 활성화될 때 로드된다.

 

그룹으로 설정 파일 로드하기

Spring Boot에서 spring.profiles.group를 사용하면 특정 프로파일 그룹을 정의할 수 있다. 이를 통해 하나의 활성화된 프로파일이 여러 하위 프로파일을 포함하도록 설정할 수 있다.

spring.profiles.group로 지정한 경우, 해당 그룹에 포함된 모든 프로파일이 활성화된다. 예를 들어, local 프로파일을 활성화하면 spring.profiles.group.local에 정의된 모든 프로파일이 함께 활성화된다.

 

예제

application.yml 파일 예시

spring:
  profiles:
    active: local
    group:
      local:
        - db-local
        - logging-local
        - security-local
      qa: 
        - db-qa
        - logging-qa
        - security-qa
      production:
        - db-production
        - logging-production
        - security-production

위 설정에서 spring.profiles.active=local이 설정되면, local 프로파일과 함께 spring.profiles.group.local에 나열된 모든 프로파일이 활성화된다.

 


프로젝트에 적용하기

위의 설명한 내용을 이용해서, 개발 환경 - 로컬 환경(활성화된 profile에 local로 끝나는 것이 있을 때)에서는 알림톡, 푸시의 목적지를 개발자의 핸드폰으로 바꿔주는 절차를 만들 것이다.

yml 파일 생성 및 작성

먼저 알림톡과 푸시를 사용하는 모듈의 resources에 다음과 같은 yml 파일을 만든다.

 

application-notification-local.yml

spring:
  config:
    active:
      on-profile: notification-local

alimtalkTest:
  developerPhoneNumber: ${env.alimtalkTest.developerPhoneNumber}

pushTest:
  developerPushToken: ${env.pushTest.developerPushToken.caregiver}

 

env는 별도의 파일로 분리한다. 분리는 이런식으로 하면 된다.

application-notification-env.yml

spring:
  config:
    active:
      on-profile: notification-env

env:
  alimtalkTest:
    developerPhoneNumber: # 개발자 핸드폰 번호 기입

  pushTest:
    developerPushToken: # 개발자 push token 기입

이 env.yml 파일은 gitignore에 등록해놓고 팀원들끼리 공유한다.

그리고 각자 env.yml 내부를 수정해서 본인의 핸드폰으로 테스트를 할 수 있다.

 

application.yml 파일 수정

spring:
  profiles:
    active: local
    group:
      local:
        - db-local
        - logging-local
        - security-local
        - notification-local
        - notification-env
      qa: 
        - db-qa
        - logging-qa
        - security-qa
      production:
        - db-production
        - logging-production
        - security-production

설정을 추가할 yml파일들을 local 그룹에 추가한다.

qa, production 환경에서는 번호와 토큰을 바꿀 필요가 없으니, local 그룹에만 추가한다. 이렇게 하면 설정이 다 끝난다.

 

 

property 세팅하는 로직 작성

실제로 push 알림을 보내거나, 알림톡을 보내는 클래스에 다음 생성자를 추가한다.

 

private val environment: Environment,

 

Spring에서 Environment 객체는 애플리케이션의 환경 속성에 대한 액세스를 제공하는 인터페이스이다.

이는 다양한 소스(예: application.properties, application.yml, 시스템 환경 변수, JVM 속성 등)에서 속성을 가져올 수 있다. Environment 객체를 사용하면 이 속성들을 코드에서 쉽게 접근하고 사용할 수 있다.

 

 

그리고 실제로 push 알림을 보내거나, 알림톡을 보내는 함수 내에서 변수를 세팅할 때 다음과 같은 방식으로 작성하면 된다.

 phone = getDevOrActualPhoneNumber(model.phone), // local 환경에서는 개발자 핸드폰 번호로 바뀜

 

getDevOrActualPhoneNumber는 private 함수로 다음과 같이 작성하였다. 파라미터로는 실제 핸드폰 번호를 받는다.

    private fun getDevOrActualPhoneNumber(actualPhoneNumber: String): String {
        val isLocalProfile = environment.activeProfiles.any { it.endsWith("local") }
        return if (isLocalProfile) {
            environment.getProperty("alimtalkTest.developerPhoneNumber")
                ?: throw IllegalArgumentException("테스트 핸드폰 번호가 없습니다.")
        } else {
            actualPhoneNumber
        }
    }
  • environment.activeProfiles는 현재 활성화된 Spring 프로필의 배열을 반환한다.
  • .any { it.endsWith("local") }는 활성 프로필 중 하나라도 local로 끝나는지 확인한다.
  • isLocalProfile 변수는 활성 프로필 중 하나가 local로 끝나면 true를, 그렇지 않으면 false를 갖는다.
  • if (isLocalProfile)
    • true인 경우
      • environment.getProperty("alimtalkTest.developerPhoneNumber")를 호출하여 alimtalkTest.developerPhoneNumber 속성의 값을 가져온다.
      • 해당 속성이 없으면 IllegalArgumentException 예외를 발생시킨다.
    • false인 경우
      • 입력 파라미터로 받은 actualPhoneNumber를 반환한다.

토큰 쪽도 비슷한 방식으로 작성하면 된다.