외부 설정이란?
하나의 애플리케이션을 여러 다른 환경에서 사용해야 할 때가 있다. 대표적으로 개발이 잘 진행되고 있는지 내부에서 확인하는 용도의 개발 환경, 그리고 실제 고객에게 서비스하는 운영 환경이 있다.
- 개발 환경: 개발 서버, 개발 DB 사용
- 운영 환경: 운영 서버, 운영 DB 사용

배포 환경과 무관하게 하나의 빌드 결과물을 만든다. 이 그림에서는 app.jar를 빌드한다.
설정 값은 실행 시점 각 환경에 따라 외부에서 주입한다.
- 개발 서버: app.jar를 실행할 때 dev.db.com값을 외부 설정으로 주입한다.
- 운영 서버: app.jar를 실행할 때 prod.db.com값을 외부 설정으로 주입한다.
cf. 유지보수하기 좋은 애플리케이션 개발의 가장 기본 원칙은 변하는 것과 변하지 않는 것을 분리하는 것이다.
외부 설정 - 스프링 통합
외부 설정 방법에는 1. 커맨드 라인 옵션 인수 2. 자바 시스템 속성 3. OS 환경변수 모두 외부 설정을 key=value 형식을 사용할 수 있는 방법이다. 하지만 이러한 설정들은 어디에 있는 외부 설정 값을 읽어야 하는지에 따라 각각 읽는 방법이 다르다는 단점이 있다.
외부 설정 값이 어디에 위치하든 상관없이 일관성 있고 편리하게 key=value 형식의 외부 설정 값을 읽을 수 있기 위해 스프링은 Environment와 PropertySource라는 추상화를 이용한다.

설정 데이터(파일)인 application.properties, application.yml도 PropertySource에 추가되고, Environment를 통해 접근할 수 있다.
EnvironmentCheck
package hello;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class EnvironmentCheck {
private final Environment env;
public EnvironmentCheck(Environment env) {
this.env = env;
}
@PostConstruct
public void init() {
String url = env.getProperty("url");
String username = env.getProperty("username");
String password = env.getProperty("password");
log.info("env url={}", url);
log.info("env username={}", username);
log.info("env password={}", password);
}
}
우선 순위
- 더 유연한 것이 우선권을 가진다. (변경하기 어려운 파일보다 실행 시 원하는 값을 줄 수 있는 자바 시스템 속성이 더 우선권을 가진다.)
- 범위가 넓은 것보다 좁은 것이 우선권을 가진다. (자바 시스템 속성은 해당 JVM 안에서 모두 접근할 수 있다. 반면 커맨드 라인 옵션 인수는 main의 arg를 통해서 들어오기 때문에 접근 범위가 더 좁다.)
설정 데이터1 - 외부 파일
OS 환경 변수, 자바 시스템 속성, 커맨드 라인 옵션 인수는 사용해야 하는 값이 늘어날 수록 사용하기가 불편해진다.
이를 해결하기 위한 방법이 설정 값을 파일에 넣어서 관리하는 방법이다.
.properties라는 파일은 key=value 형식을 사용해 설정 값을 관리하기 아주 적합하다.

application.properties 개발 서버에 있는 외부 파일
url=dev.db.com
username=dev_user
password=dev_pw
application.properties 운영 서버에 있는 외부 파일
url=prod.db.com
username=prod_user
password=prod_pw
설정 데이터2 - 내부 파일 분리
설정 파일을 외부에 관리하는 것은 번거로운 일이다. 이를 해결하기 위한 방법으로 설정 파일을 프로젝트 내부에 포함해 관리하는 것이다.
또한 빌드 시점에 함께 빌드되게 한다. 이렇게 한다면 애플리케이션을 배포할 때 설정 파일의 변경 사항도 함께 배포할 수 있다.

1. 프로젝트 안에 소스 코드 뿐 아니라 각 환경에 필요한 설정 데이터도 함께 포함해 관리한다.
- 개발용 설정 파일: application-dev.properties
- 운영용 설정 파일: application-prod.properties
2. 빌드 시점에 개발, 운영 설정 파일을 모두 포함해서 빌드한다.
3. 실행할 때 어떤 설정 데이터를 읽어야 할지 최소한의 구분은 필요하다.
- 개발 환경: application-dev.properties
- 운영 환경: application-prod.properties
application-dev.properties 개발 프로필에서 사용
url=dev.db.com
username=dev_user
password=dev_pw
application-prod.properties 운영 프로필에서 사용
url=prod.db.com
username=prod_user
password=prod_pw
설정 데이터3 - 내부 파일 합체
설정 파일을 각각 분리해서 관리하면 한 눈에 전체가 들어오지 않는 단점이 있다.
이를 해결하기 위해, 스프링은 하나의 파일 안에서 논리적으로 영역을 구분하는 방법을 제공한다.

스프링은 하나의 application.properties 파일 안에서 논리적으로 영역을 구분하는 방법을 제공한다
- application.properties 구분 방법: #---, !---
- application.yml 구분 방법: ---
application.properties
spring.config.activate.on-profile=dev
url=dev.db.com
username=dev_user
password=dev_pw
#---
spring.config.activate.on-profile=prod
url=prod.db.com
username=prod_user
password=prod_pw
기본 값
내 PC에서 개발하는 것을 보통 로컬(local) 개발 환경이라고 한다. 이때 설정 데이터에는 기본 값을 지정할 수 있는데, 프로필 지정과 무관하게 이 값은 항상 사용된다.
application.properties
url=local.db.com
username=local_user
password=local_pw
#---
spring.config.activate.on-profile=dev
url=dev.db.com
username=dev_user
password=dev_pw
#---
spring.config.activate.on-profile=prod
url=prod.db.com
username=prod_user
password=prod_pw
YAML
스프링은 설정 데이터를 사용할 때 application.properties 뿐만 아니라 application.yml 이라는 형식도 지원한다.
YAML은 사람이 읽기 좋은 데이터 구조를 목표로 한다. 확장자는 yaml, yml 이고, 주로 yml을 사용한다.
application.yml
environment:
dev:
url: "https://dev.example.com"
name: "Developer Setup"
prod:
url: "https://another.example.com"
name: "My Cool App"
- YAML의 가장 큰 특징은 사람이 읽기 좋게 계층 구조를 이룬다는 점이다.
- YAML은 space(공백)로 계층 구조를 만든다. space는 1칸을 사용해도 되는데, 보통 2칸을 사용한다.
- 구분 기호로 :를 사용한다. 만약 값이 있다면 key: value : 이후에 공백을 하나 넣고 값을 넣어준다.
@Profile
PayConfig
package hello.pay;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Slf4j
@Configuration
public class PayConfig {
@Bean
@Profile("default")
public LocalPayClient localPayClient() {
log.info("LocalPayClient 빈 등록");
return new LocalPayClient();
}
@Bean
@Profile("prod")
public ProdPayClient prodPayClient() {
log.info("ProdPayClient 빈 등록");
return new ProdPayClient();
}
}
- @Profile 애노테이션을 사용하면 해당 프로필이 활성화된 경우에만 빈을 등록한다.
- default 프로필(기본값)이 활성화 되어 있으면 LocalPayClient를 빈으로 등록한다.
- prod 프로필이 활성화 되어 있으면 ProdPayClient를 빈으로 등록한다.
우선 순위
1. 설정 데이터 (application.properties)
2. OS 환경변수
3. 자바 시스템 속성
4. 커맨드 라인 옵션 인수
5. @TestPropertySource (테스트에서 사용)
우선 순위 이해 방법
1. 더 유연한 것이 우선권을 가진다. (변경하기 어려운 파일 보다 실행 시 원하는 값을 줄 수 있는 자바 시스템 속성이 더 우선권을 가진다.)
2. 범위가 넒은 것 보다 좁은 것이 우선권을 가진다.
- OS 환경변수 보다 자바 시스템 속성이 우선권이 있다.
- 자바 시스템 속성 보다 커맨드 라인 옵션 인수가 우선권이 있다
'Spring Study > SpringBoot' 카테고리의 다른 글
[SpringBoot] Actuator (0) | 2023.12.06 |
---|---|
[SpringBoot] 스프링 부트 스타터와 라이브러리 관리 (0) | 2023.11.23 |
[SpringBoot] 웹 서버와 서블릿 컨테이너 (2) | 2023.11.21 |
댓글