Web/환경설정 관련
Spring boot - 설정 파일 관리 (@Profile, @ConfigurationProperties,@Value,@PropertySource)
now0204
2024. 5. 10. 19:22
- 개발 프로젝트를 진행하는 방식에 따라 동일한 어플리케이션을 개발, 테스트, 스테이징, 상용 등 여러 환경에서 배포해야하는 경우가 있다.
- 이때 배포 환경에 따라 소스코드는 거의 변경되지 않고, 설정 정보만 다르게 해야 배포 작업이 편할 것이다.
- 따라서, 설정 정보를 외부화해서 관리 하는 방법 들에 대해서 알아보자
Property 관리의 여러 가지 방법
1. SpringApplication 클래스 활용
- SpringApplication 클래스를 사용하여 설정 정보를 정의할 수 있다.
- 이 클래스에는 java.util.Properties 또는 Map<String,Object>를 인자로 받는다.
- setDefaultProperties에 위 Properties나 Map으로 설정한 내용을 넣으면 된다.
- 위 방식은 소스코드로 정의하는 방식이므로, 한 번 정의하면, 나중에 바뀌지 않는 경우에 적합하다.
@SpringBootApplication
public class ManyConfigApplication {
public static void main(String[] args) {
Properties properties = new Properties();
properties.setProperty("spring.config.on-not-found", "ignore");
properties.setProperty("spring.mvc.static-path-pattern","/newstatic/**");
SpringApplication application = new SpringApplication(ManyConfigApplication.class);
application.setDefaultProperties(properties);
application.run(args);
}
}
- 그냥 key - value 형태로 properties를 작성하는 간단한 방법이다.
2. @PropertySource 사용
- PropertySource 애너테이션을 사용해서 사용할 프로퍼티 파일을 지정할 수 있다.
- 해당 값을 Environment 클래스를 통해 쉽게 값을 꺼낼 수 있다.
- 혹은 @Value 애너테이션으로 값을 꺼내서 바로 주입할 수도 있다.
- PropertySource는 YAML 파일을 지정해서 사용할 수 없고, 사용하려면 몇가지 추가 작업이 필요하다.
- PropertySouce는 여러개 사용할 수 있다.
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
@Configuration
@PropertySource("classpath:db.properties")
@Slf4j
public class DbConfig {
@Value("${spring.datasource.username}")
String userName;
@Value("${spring.datasource.driver-class-name}")
String driver;
@Autowired
private Environment env;
@Override
public String toString(){
return env.getProperty("spring.datasource.username")+env.getProperty("spring.datasource.driver-class-name");
}
@PostConstruct
public void mynameIs(){
log.info(this.toString());
}
}
3. properties와 YAML 배포시 위치 지정
- 기본적으로 application.properties나 application.yml을 다음 경로에서 찾는다.
- classpath root
- classpath /config 패키지
- 현재 디렉토리
- 현재 디렉토리 /config 디렉터리
- /config 디렉터리의 바로 하위 디렉터리
- 이때 spring.config.location 프로퍼티를 사용하면, 다른 위치에 설정 파일을 읽어올 수 있다.
- scr/main/resources/data 디렉터리에 yml 파일을 두었다고 가정
1. java -jar 배포파일명.jar --spring.config.location=data/bb.yml
2. java -jar 배포파일명.jar --spring.config.location=optional:data/bb.yml
- 기본 위치 말고 위에 설정한 위치에서도 properties 파일을 찾는다. (기본 + 추가 경로에 설정 파일이 없으면 예외 발생)
- optional을 붙이면, 설정 파일이 없더라도 애플리케이션이 일단 실행된다.
4. 운영 체제 환경 변수
- 운영 체제 환경 변수로 지정한 값을 properties 파일이나, yml에서 읽을 수 있다.
- 윈도우 set <VAR>=<value> , 리눅스 export <VAR>=<value> 등 환경변수를 지정
- ${}에 환경변수 이름을 넣으면, 환경 변수의 값을 읽어서 주입해준다.
- :를 넣어서 기본 값을 지정해 줄 수 도 있다.
app.timeout=${APP_TIMEOUT:3000}
5. 우선 순위
- 프로퍼티 지정의 우선 순위는 다음과 같다.
- 명령행 인자
- 운영체제 환경 변수
- 설정 정보 파일
- @PropertySource
- SpringApplication
6. @ConfigurationProperties 커스텀 프로퍼티 만들기
- spring의 프로퍼티는 빌트인과 커스텀으로 나눌 수 있다.
- 빌트인 프로퍼티를 Environment 인스턴스에 바인딩해서 주로 사용하는데, 몇 가지 단점이 있다.
- 프로퍼티 값 타입 안정성이 보장되지 않아, 런타임 에러 발생 가능성이 있다.(ex url, 이메일 주소 유효성 검증)
- 프로퍼티 값을 일정한 단위로 묶어서 읽을 수 없고 @Value나 Environment로 하나 하나 읽어야 한다.
- 위 단점 타입 안정성을 보장하고, 유효성을 검증할 수 있는 방법은 다음과 같다.
app.sbip.ct.name=CourseTracker
app.sbip.ct.ip=127.0.0.1
app.sbip.ct.port=9090
app.sbip.ct.security.enabled=true
app.sbip.ct.security.token=asddf998hhyqthgtYYtggghg9908jjh7ttr
app.sbip.ct.security.roles=USER,ADMIN
- 이를 읽어올 클래스를 다음과 같이 만들 수 있다.
package com.example.manyConfig.config;
import lombok.*;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.List;
@ConfigurationProperties("app.sbip.ct")
@RequiredArgsConstructor
@Getter
@ToString
public class AppProperties {
private final String name;
private final String ip;
private final int port;
private final Security security;
@ToString
public static class Security{
private final boolean enabled;
private final String token;
private final List<String> roles;
public Security(boolean enabled, String token, List<String> roles) {
this.enabled = enabled;
this.token = token;
this.roles = roles;
}
}
}
- 해당 프로퍼티를 읽어온 객체를 주입받아, 아래와 같이 사용할 수 있다.
package com.example.manyConfig;
import com.example.manyConfig.config.AppProperties;
import jakarta.annotation.PostConstruct;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service
@AllArgsConstructor
@Slf4j
public class AppService {
private final AppProperties appProperties;
public AppProperties getAppProperties(){
return appProperties;
}
@PostConstruct
private void totoString(){
log.info(appProperties.toString());
}
}
- @SpringBootApplication이 있는 시작 부분에 @EnableConfigurationProperties를 추가해주면 사용할 수 있다.
@SpringBootApplication
@EnableConfigurationProperties(AppProperties.class)
public class ManyConfigApplication {
...//
}
*스프링 3.2.1부터 위와 같이 작성했을 때 작동하지 않을 수 있다.
- 밑에 처럼 Build and run using과 Run tests using이 Gradle이어야 한다.
Profile 활용
- Profile을 설정하면, 다양한 환경에서 지정된 properties 혹은 yml파일을 개발 및 운영환경에 따라 쉽게 전환해서 사용할 수 있다.
- 먼저 application.properties파일을 기본으로
- application-[name].properties로 만들면된다.
- 여기서 name에는 다음이 사용될 수 있다. 이것 말고도 여러가지 원하는 이름을 사용해도 된다.
- local : 로컬 환경
- dev : 테스트 환경
- profile환경은 application.properties나 위에 작성된 여러 프로퍼티 주입 방식을 사용해서
- spring.profiles.active=profile명(local,dev2,dev1 ..등)을 주면 된다.
spring.profiles.active=dev1
@Profile 애너테이션
- 프로필을 통해 런타임 환경을 설정할 수 있는 기능이다.
- 테스트 환경 등에서 여러 테스트를 돌리고 난 다음 프로덕션 환경으로 전환 하는 것을 어렵지 않게 할 수 있다.
@Configuration
@Profile("dev1")
@PropertySource("classpath:application.properties")
@Slf4j
public class DbConfig {
@Value("${spring.datasource.username}")
String userName;
@Value("${spring.datasource.driver-class-name}")
String driver;
@Autowired
private Environment env;
@Override
public String toString(){
return Arrays.toString(env.getActiveProfiles())+" HI "+env.getProperty("spring.datasource.username")+env.getProperty("spring.datasource.driver-class-name");
}
@PostConstruct
public void mynameIs(){
log.info(this.toString());
}
}
- 설정 정보를 dev2로 변경하면, 빈이 생성되지 않는다.
- 이와 같이 테스트 환경에서만 사용할 Bean을 @Profile 애너테이션을 사용해서 등록하거나, 하지 않을 수 있다.
https://www.yes24.com/Product/Goods/122002340