[Spring Boot] 외부 설정과 프로필 2
@Value, @ConfigurationProperties 등 외부 설정을 객체에 주입하는 방법을 알아보자.
※ 코드는 강의에서 사용된 것과 다릅니다.
<a href = https://github.com/jaewon-ju/Learning_Spring>jaewon-ju Github Address</a>
✏️ 외부 설정과 스프링 빈
이전 포스트에서 배운 Environment 클래스로 외부 설정을 조회할 수 있다.
외부 설정 자체를 하나의 스프링 빈으로 등록하면 더 편하게 사용할 수 있을 것이다!
외부 설정 자체를 하나의 클래스로 만들어서 사용하는 방법을 알아보자.
일단, 외부 설정을 주입받을 클래스 MySetting 클래스를 정의한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Slf4j
@Getter
public class MySetting {
private String appKey;
private String appSecretKey;
private int maxConnection;
private Duration timeout;
public MySetting(String appKey, String appSecretKey, int maxConnection, Duration timeout) {
this.appKey = appKey;
this.appSecretKey = appSecretKey;
this.maxConnection = maxConnection;
this.timeout = timeout;
}
}
외부 설정은 application.properties 파일에 존재한다.
1
2
3
4
my.app-key=thisIsAppkey
my.app-secret-key=thisIsAppSecretKey
my.etc.max-connection=1
my.etc.timeout=3000ms
이제 MySetting 클래스에 외부 설정을 주입하는 방법에 대해서 알아보자.
✏️ Environment
Environment 클래스를 사용해서 외부설정을 MySetting 클래스에 주입할 수 있다.
Environment클래스를 스프링 빈으로 등록한다.Environment클래스를 사용해서 외부 설정을 읽어온다.- 읽어온 데이터를
MySetting클래스에 직접 주입한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Slf4j
@Configuration
public class MyConfig {
private final Environment env;
public MyConfig(Environment env){
this.env = env;
}
@Bean
public MySetting mySetting(){
String appKey = env.getProperty("my.app-key");
String appSecretKey = env.getProperty("my.app-secret-key");
int maxConnection = env.getProperty("my.max-connection", Integer.class);
Duration timeout = env.getProperty("my.timeout",Duration.class);
return new MySetting(appKey,appSecretKey,maxConnection,timeout);
}
}
추가로, Application에 @Import 어노테이션을 작성해야 한다.
1
2
3
4
5
6
7
@Import(MyConfig.class)
@SpringBootApplication
public class MyApp{
public static void main(String args[]){
SppringApplication.run(MyApp.class, args)
}
}
■ 단점
Environment로 주입받고,env.getProperty()로 꺼내는 작업을 반복해야 한다.env.getProperty()로 받은 데이터를 각 타입에 맞게 파싱해야 하는 번거로움이 있다.
✏️ @Value
【 주식 분석 어플리케이션 】 프로젝트를 진행할 때, @Value 어노테이션을 사용했었다.
@Value 어노테이션을 사용해서 외부 설정 값인 app_key, app_secret_key 등을 주입받은 경험이 있다.
@Value도 내부에서는Environment클래스를 사용한다.@Value("${key}")로 외부 설정을 주입받을 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Slf4j
@Configuration
public class MyConfig {
@Value("${my.app-key}")
private String appKey;
@Value("${my.app-secret-key}")
String appSecretKey;
@Value("${my.etc.max-connection}")
int maxConnection;
@Value("${my.etc.timeout}")
Duration timeout;
@Bean
public MySetting mySetting(){
return new MySetting(appKey, appSecretKey, maxConnection, timeout);
}
}
- 파라미터에서 직접 주입받을 수도 있다.
- 주입받을 외부 설정이 없는 경우, Default 값을 설정할 수 있다.
@Value("${my.app-key:defaultAppKey}"): app-key 설정 값이 없는 경우, defaultAppKey를 주입한다.
■ 단점
@Value를 하나하나 입력하는 부분이 번거롭다.
∴ 설정 데이터를 하나의 묶음으로 가져오는 방법을 고안해야 한다.
✏️ @ConfigurationProperties
■ Type-safe Configuration Properties
외부 설정의 묶음을 객체로 변환하는 기능이다.
- 잘못된 타입이 입력되는 문제를 방지할 수 있다.
- 객체를 다양하게 활용할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 외부 설정으로부터 정보를 묶음으로 가져오는 MyProperties 클래스
// @ConfigurationProperties 어노테이션으로 묶음의 시작점을 표기해야 한다.
@Data
@ConfigurationProperties("my")
public class MyProperties {
private String appKey;
private String appSecretKey;
private Etc etc = new Etc();
@Data
public static class Etc {
private int maxConnection;
private Duration timeout;
}
}
- 기본 주입 방식은 자바빈 프로퍼티 방식이므로, Getter, Setter가 필요하다!
MyProperties 클래스로 설정 정보를 묶음으로 가져온 다음, MySetting 클래스에 주입한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Slf4j
@EnableConfigurationProperties(MyProperties.class)
public class MyConfig {
private final MyProperties properties;
public MyConfig(MyProperties properties){
this.properties = properties;
}
@Bean
public MySetting mySetting(){
return new MySetting(
properties.getAppKey(),
properties.getAppSecretKey(),
properties.getEtc().getMaxConnection(),
properties.getEtc().getTimeout()
);
}
}
@EnableConfigurationProperties어노테이션을 지정해야 한다.
■ 장점
- 타입을 잘못 입력하면 오류를 발생시켜준다.
- ex)
my-connection=hello를 입력하면 오류 발생
- ex)
- 외부 설정을 하나의 객체로 땡겨온다.
■ 주의할 점
MyProperties 클래스는 Setter를 가지고 있다.
➜ 누군가 값을 변경할 수 있다.
- 외부 설정 값은 어플리케이션 내부에서 변경되어선 안된다!
- 따라서, Setter를 제거하고 생성자를 사용하는 방법이 존재한다.
✏️ YAML
스프링은 설정 데이터를 사용할 때,
application.properties뿐만 아니라application.yml이라는 형식도 지원한다.
- YAML(YAML Ain’t Markup Language)
- 사람이 읽기 좋은 데이터 구조
Application.properties 예시
1 2 3 4 5 spring.application.name=springmvc my.app-key=thisIsAppkey my.app-secret-key=thisIsAppSecretKey my.etc.max-connection=1 my.etc.timeout=3000ms
위의 텍스트를 yml 파일로 바꾸면, 다음과 같이 읽기 좋은 데이터 구조로 만들 수 있다.
Application.yml 예시
1 2 3 4 5 6 7 8 9 spring: application: name: springmvc my: app-key: thisIsAppkey app-secret-key: thisIsAppSecretKey etc: max-connection: 1 timeout: 3000ms
- YAML은 공백으로 계층 구조를 만든다.
- 보통 2칸을 사용한다.
- 구분 기호로 : 를 사용한다.
✏️ @Profile
외부설정을 사용하면, 각 환경마다 설정 값을 다르게 적용시킬 수 있다.
만약, 환경마다 각각 다른 빈을 등록해야 한다면 어떻게 해야할까?
이럴 때는, @Profile 어노테이션을 사용하면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Slf4j
@Configuration
public class MyConfig {
@Bean
@Profile("default")
public LocalDB localDB(){
return new LocalDB();
}
@Bean
@Profile("prod")
public ProdDB prodDB(){
return new ProdDB();
}
}
실행 시점에 --spring.profile.active=prod 를 적용하면, prod 프로필이 활성화되고, prodDB 빈만 등록된다.
아무 프로필도 활성화하지 않으면, default 프로필이 활성화된다.