[Spring / TIL] Spring profiles를 통해 application.yaml 하나로 개발환경 관리하기(부제. @Value 환경변수 사용법)

resilient

·

2023. 1. 17. 00:41

728x90
반응형

프로젝트를 개발하다 보면 하나의 서버 애플리케이션을 prod,dev,local 환경에서 각각 실행해야 할 일이 생깁니다. 

 

예를 들면 Cloud SQL을 사용할 경우, private IP도 다를 것이고, 다양한 secret key 값도 환경에 따라서 모두 달라야 합니다. 이런 경우는 굉장히 흔한데 어떻게 효율적으로 관리할까요?

 

이번 시간에는 일반적인 스프링 부트 애플리케이션을 운영할 때, 하나의 application.yaml(application.properties) 파일 설정으로 Profiles를 관리하고, prod, dev, local 환경을 구성하고, 각 환경변수들을 어떻게 사용하는지에 대한 방법을 설명하려고 합니다.

 

0. @Value로 환경변수 사용하기

 

먼저 yaml파일의 프로퍼티 값을 전달받아서 애플리케이션 내부에서 환경변수로 사용하는 경우를 알아보겠습니다. 이후 프로퍼티 값을 각 환경에 어떻게 적용시키는지를 알아보도록 하겠습니다.

 

아래 예시 코드를 보겠습니다. 

user.name은 스프링에서 기본으로 제공해주는 프로퍼티가 아닌 제가 임의로 만든 프로퍼티입니다. 

@RestController
@RequestMapping("/api")
class HealthCheckController(
) {

    @Value("\${user.name}")
    private val userName:String = ""


    @GetMapping("/health-check")
    fun hello(): ResponseEntity<HealthCheckResponse> {
        println("userName = $userName")
        return ResponseEntity.ok(HealthCheckResponse("ok"))
    }

}

 

Kotlin에서 @Value (Value annotation)을 사용하는 방법은 위와 같습니다.

Spring에서는 @Value를 통해서 다양한 종류의 소스에서 값을 읽어 올 수 있는데요. 여기서 주의해야 할 점은 Kotlin언어에서는 \를 ${} 앞에 붙여줘야 에러가 나지 않습니다.

 

\를 붙이지 않았을 경우 나타나는 에러

 

Kotlin에서는 $뒤에 호출하고 싶은 변수의 이름을 적었을 경우, 변수의 값을 가져올 수 있기 때문에 문자열 처리를 할 수가 없습니다. @Value 안에는 문자열이 와야 하는데 말이죠. 이럴 경우, 앞에 백슬래시(\)를 이용해서 이스케이프 무자로 사용해서 문자열 처리를 할 수 있습니다. 따라서 \를 붙여줘야 user.name값을 제대로 가져올 수 있게 되죠.

 

1. application.yaml에 프로퍼티 추가하기

 

이제 @Value로 Spring 애플리케이션에서 어떻게 값을 가져오는지 알아봤습니다. 이제 user.name을 어디서 어떻게 가져오는지 알아보도록 하겠습니다.

 

1-1. 먼저 Spring boot 2.4 이전과 이후에 프로파일 처리방식이 바뀌었습니다.

 

Spring boot 2.4 이전에는 아래와 같이 사용했습니다.

spring.profiles:prod
---
spring.profiles:dev
---
spring.profiles:local

 

하지만 2.4 이후로 spring.profiles는 deprecated 대상이 되었습니다. 이후에는 spring.config.activate.on-profile을 사용해야 합니다.

대체 키를 사용하라고 친절하게 설명까지 해줍니다.

1-2. spring.config.activate.on-profile을 사용한 프로파일 처리 방식

 

spring:
  profiles:
    group:
      dev: dev
      prod: prod
      local: local

---
# 모든 프로파일에서 사용하는 common data.
common: common-data

---
# 실행되는 프로파일이 dev인 경우, 아래에 있는 프로퍼티들을 사용
spring.config.activate.on-profile: dev
user.name: dev-user

---
# 실행되는 프로파일이 prod인 경우, 아래에 있는 프로퍼티들을 사용
spring.config.activate.on-profile: prod
user.name: prod-user

---
# 실행되는 프로파일이 local인 경우, 아래에 있는 프로퍼티들을 사용
spring.config.activate.on-profile: local
user.name: local-user

 

spring.profiles 옵션이 deprecated 되었고 spring.profiles.group 옵션이 추가 되었습니다.

사용방법은 위에 spring.profiles.group을 설정한 후, jar을 실행할 때 profile을 선택해서 실행하면 됩니다. 

 

2. 주의할 점

 

주의할 점이 있습니다.

 

application.yaml 파일 마지막 프로파일을 설정할 때, spring.config.activate.on-profile 선언하는 것을 빼먹는 경우가 종종 있는데 이럴 경우에는 프로파일 선언이 되지 않고, 마지막 속성값으로 덮어 씌워집니다.

 

...

---
# 실행되는 프로파일이 prod인 경우, 아래에 있는 프로퍼티들을 사용
spring.config.activate.on-profile: prod
user.name: prod-user

---
# 실행되는 프로파일이 local인 경우, 아래에 있는 프로퍼티들을 사용

# 이 경우, local 프로파일이 생성되지 않고, user.name에 local-user가 아닌 prod-user로 세팅
user.name: local-user

 

 

3. application.yaml 파일 내에서 외부로부터 환경변수 받아서 사용하기

 

위의 user.name값을 외부로부터 숨겨야 하는 상황이라고 가정해 보겠습니다.

 

1차원적으로는 위의 application.yaml 파일처럼 모든 secert key나 user.name 등을 입력해 놓고. gitignore에 추가해서 깃의 관리 대상에서 완전히 누락시키는 방안을 생각할 수 있습니다. 하지만 이 방법은 굉장히 비효율적이고 위험합니다.

 

가장 어리석게는 gitignore에 빼먹고 커밋을 남긴다던가 (제 얘기입니다.)

개발자마다 로컬 머신에 yaml 파일들을 다 가지고 있어야 하기 때문에 수작업으로 모든 yaml파일들을 관리해야 한다는 번거로움이 있죠.

 

이런 경우 yaml파일 내에서 환경변수를 설정해서 사용할 수 있습니다. 

 

굉장히 간단한데요. user.name: prod-user가 아닌 user.name: ${secret-user}로 추가해 주고, secret-user에 prod-user를 담아서 사용하면 됩니다.

user.name: prod-user 가 아닌 
user.name: ${secret-user} 로 추가 나중에 env에서 secret-user=prod-user로 추가

 

저희 프로젝트 같은 경우에는 Google App Engine을 사용하기 때문에 app.yaml 파일에 아래와 같이 작성해서 env 설정을 해주곤 합니다.

 

env_variables:
  spring_profiles_active: prod
  secret-user: prod-user

 

4. IntelliJ IDEA에서 환경변수 설정하기

 

버전은 2021.3.3 (Ultimate Edition)이니 참고해 주세요. (예시는 prod 환경 세팅으로 진행하겠습니다.)

 

우측 상단 Edit Configurations(구성 편집) 선택

 

 

 

활성화된 프로파일에 prod를 넣어주고 옵션수정을 눌러서 환경 변수를 추가해 줍니다. 위에서 넣었던 것처럼 secret-user에 prod-user를 담아주도록 하겠습니다.

 

이렇게 IntelliJ에서 쉽게 환경변수를 설정해서 각 프로젝트에 한정된 시스템 환경을 구축할 수 있습니다. 개발을 할 때 로컬 컴퓨터에서 환경을 설정하는 일이 꽤나 까다로운 일이지만 이 방법은 IDE를 사용한 굉장히 효율적인 최선의 방법 중 하나라고 생각합니다.

 

그럼 테스트를 해보겠습니다. (예시는 prod 환경 세팅으로 진행하겠습니다.)

 

The following 1 profile is active:"prod"

Springboot를 실행시키면 빨간색 밑줄처럼 profile은 prod로 설정이 되는 것을 볼 수 있습니다.

 

5. 정리

 

이번 시간에는 스프링 개발자라면 기본적으로 알아야 할 환경세팅을 하는 방법을 알아봤습니다. 물론 위에서 설명한 내용들이 최선은 아니지만 현재 제가 가지고 있는 스프링 능력치와 효율성을 고려해봤을 때는 최선이라고 판단. 위와 같이 세팅해서 현재 개발 중에 있습니다.

 

앞으로도 환경 세팅을 하는 여러 가지 방법이나 지식들을 습득하고 실습을 통해서 실무에서 적용할 수 있도록 연습을 많이 해봐야겠다고 생각했습니다.

 

긴 글 읽어주셔서 감사합니다.

 

반응형