이전 포스트에서 배운 Environment
클래스로 외부 설정을 조회할 수 있다.
외부 설정 자체를 하나의 스프링 빈으로 등록하면 더 편하게 사용할 수 있을 것이다!
외부 설정 자체를 하나의 클래스로 만들어서 사용하는 방법을 알아보자.
일단, 외부 설정을 주입받을 클래스 MySetting
클래스를 정의한다.
@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
파일에 존재한다.
my.app-key=thisIsAppkey
my.app-secret-key=thisIsAppSecretKey
my.etc.max-connection=1
my.etc.timeout=3000ms
이제 MySetting
클래스에 외부 설정을 주입하는 방법에 대해서 알아보자.
Environment
클래스를 사용해서 외부설정을 MySetting
클래스에 주입할 수 있다.
Environment
클래스를 스프링 빈으로 등록한다.Environment
클래스를 사용해서 외부 설정을 읽어온다.MySetting
클래스에 직접 주입한다.@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
어노테이션을 작성해야 한다.
@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
어노테이션을 사용해서 외부 설정 값인 app_key, app_secret_key 등을 주입받은 경험이 있다.
@Value
도 내부에서는 Environment
클래스를 사용한다.@Value("${key}")
로 외부 설정을 주입받을 수 있다.@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);
}
}
@Value("${my.app-key:defaultAppKey}")
: app-key 설정 값이 없는 경우, defaultAppKey를 주입한다.@Value
를 하나하나 입력하는 부분이 번거롭다.∴ 설정 데이터를 하나의 묶음으로 가져오는 방법을 고안해야 한다.
외부 설정의 묶음을 객체로 변환하는 기능이다.
// 외부 설정으로부터 정보를 묶음으로 가져오는 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;
}
}
MyProperties
클래스로 설정 정보를 묶음으로 가져온 다음, MySetting
클래스에 주입한다.
@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
어노테이션을 지정해야 한다.my-connection=hello
를 입력하면 오류 발생MyProperties
클래스는 Setter를 가지고 있다.
➜ 누군가 값을 변경할 수 있다.
스프링은 설정 데이터를 사용할 때,
application.properties
뿐만 아니라application.yml
이라는 형식도 지원한다.
YAML(YAML Ain't Markup Language)
: 사람이 읽기 좋은 데이터 구조
Application.properties 예시
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 예시
spring: application: name: springmvc my: app-key: thisIsAppkey app-secret-key: thisIsAppSecretKey etc: max-connection: 1 timeout: 3000ms
외부설정을 사용하면, 각 환경마다 설정 값을 다르게 적용시킬 수 있다.
만약, 환경마다 각각 다른 빈을 등록해야 한다면 어떻게 해야할까?
이럴 때는, @Profile
어노테이션을 사용하면 된다.
@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 프로필이 활성화된다.