스프링 핵심 기술-05.Environment 프로파일/프로퍼티
in Back-end on Spring, Applicationcontext, Environment, Profile, Properties
IoC 컨테이너 6부 : Environment 1부.프로파일
ApplicationContext는 빈팩토리의 기능만 하는 것은 아닙니다.
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
..
}
많은 클래스들을 상속받고 있는 걸 볼 수 있는데, 가진 기능들을 좀 더 구체적으로 정리할 예정입니다.
가장 먼저 Environment 부터 살펴보자.
- EnvironmentCapable 이 제공하는 기능은 크게 2가지
- 프로파일 기능
- 프로퍼티
- 프로파일과 프로퍼티를 다루는 인터페이스.
- ApplicationContext extends EnvironmentCapable
- getEnvironment()
- 프로파일
- 빈들의 그룹
- Environment의 역할은 활성화할 프로파일 확인 및 설정
- 프로파일 유즈케이스
- 테스트 환경에서는 A라는 빈을 사용하고, 배포 환경에서는 B라는 빈을 쓰고 싶다.
- 이 빈은 모니터링 용도니까 테스트할 때는 필요가 없고 배포할 때만 등록이 되면 좋겠다.
프로파일은..
우리가 많이 사용해 보았던 메이븐에도 프로파일 기능이 있고, 스프링 프로파일도 마찬가지이다.
@Environment
환경이란,
테스트 환경에서는 이런 빈들을 쓰고
배포 환경에서는 이런 빈들을 쓰겠다. 라고 설정하는 것이다.
특정한 환경에서는 이런 빈들을 등록해야 하는 경우 이런 요구사항들..(개발계, 운영계, 테스트계 등..)
ApplicationContext - EnvironmentCapable 인터페이스를 통해 사용이 가능하다.
프로파일(Profiles) 확인
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
ApplicationContext ctx;
@Override
public void run(ApplicationArguments args) throws Exception {
Environment environment = ctx.getEnvironment(); // EnvironmentCapable
System.out.println(Arrays.toString(environment.getActiveProfiles())); // 추가 설정 프로파일
System.out.println(Arrays.toString(environment.getDefaultProfiles())); // 기본 디폴트 프로파일
}
}
실행결과
[]
[default]
프로파일 정의하기
- 클래스에 정의
- @Configuration @Profile(“test”)
- @Component @Profile(“test”)
- 메소드에 정의
- @Bean @Profile(“test”)
1.클래스에 정의
@Configuration 설정 클래스를 만들어서 설정
@Configuration
@Profile("test")
public class TestConfiguration {
@Bean
public TestRepository testRepository(){
return new TestRepository();
}
}
이렇게 설정 클래스 파일을 생성했는데.. 실행 결과는 에러가 발생한다.
Field testRepository in com.example.ioccontainer5.demo.AppRunner required a bean of type 'com.example.ioccontainer5.demo.TestRepository' that could not be found.
해당 프로파일이 없으면 찾을 수 없다고 에러가 발생한다.
이유가 뭐냐면, 아직 프로파일을 적용해 주지 않았기 때문이다.
test 프로파일을 적용해 주기 전까지는 TestRepository 빈을 찾을 수 없다.
인텔리제이 액티브 프로파일 설정에서 적용 프로파일을 지정해 줄 수 있다.
test 프로파일을 적용해 준 뒤에는 정상적으로 실행되는 걸 확인 가능하다.
@Component 개별 클래스에도 설정해 사용도 가능하다.
@Repository
@Profile("develope")
public class DevelopeRepository {
추가로 이런 설정도 가능하다
@Repository @Profile(“!test”) public class DevelopeRepository { }
프로파일에 test가 없을 때에만 적용을 한다던가..
! : not
& : and
| : or
저렇게 실행하면 지금은 test, develope 프로파일이 둘 다 설정이 되어 있는 상태이니까, DevelopeRepository 은 사용하지 못한다.
이런 방식으로도 사용이 가능하고 클래스 뿐만 아니라 메서드에도 @Profile(“!develope”)를 붙여 활용 가능하다.
해당 메서드는 개발에서는 절대 돌면 안되는 메서드라던가..
프로파일을 설정하는 방법은 인텔리J를 활용해서 간단히 적용했지만,
yaml파일을 이용한다던가..
spring:
profiles: test
application.properties를 파일을 이용해 설정도 가능하다.
application-{profile}.properties 형식
application-test.properties
application-develope.properties
application-prod.properties
IoC 컨테이너 6부 : Environment 2부.프로퍼티
EnvironmentCapable가 제공하는 두번째 기능이다.
Properties
- 애플리케이션에 등록되는 프로퍼티(Key, value 쌍)에 접근할 수 있는 기능
- 계층형으로 접근을 한다.
계층형이란? 우선순위가 있다는 말이다.
프로퍼티는(Key, value 쌍으로) 여러가지 소스, 여러가지 형태로 제공이 될 수 있는데..
- OS에 있는 환경변수,
- 자바 애플리케이션 실행할 때 넘겨주는 -d 옵션으로 넘겨주는 프로퍼티들
- 서블릿 컨텍스트
- 서블릿 컨피그 등 (서블릿 애플리케이션이라면 ) 등이 있다.
프로퍼티 사용법
그럼 프로퍼티를 어떻게 접근하고 사용하느냐?
내가 넘겨준 -d app.name 값
해당 코드로 확인되는 걸 볼 수 있다.
이런 방법 말고도 난 체계적으로 값을 전달하려고 한다면..
프로퍼티 파일을 만들고(resources)
app.about=jaeuk
값을 넣어놓은 다음
@SpringBootApplication
@PropertySource("classpath:/app.properties")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@PropertySource로 프로퍼티 파일을 읽고,
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
ApplicationContext ctx;
@Override
public void run(ApplicationArguments args) throws Exception {
Environment environment = ctx.getEnvironment(); // EnvironmentCapable
System.out.println(environment.getProperty("app.name")); // 프로퍼티 확인
System.out.println(environment.getProperty("app.about")); // 직접 생성한 프로퍼티 파일 참조
}
}
똑같이 사용이 가능하다.
추가적으로 스프링 부트에서는
@Value("${app.name}")
String appName;
이런 방식으로 더 간편하게 사용이 가능하다.
(사실 앞서 설명한 내용들을 기반으로 스프링 부트가 구현된 것)
그럼 프로퍼티를 가져오는 우선 순위는 어떻게 될까?
둘 다 똑같은 app.name이라는 key를 있다면 된다면?
두개 중에서는
vm 옵션으로 준 게 더 우선순위를 가진다.
= 내가 프로퍼티에 적어놓은 것이 아닌, vm옵션의 value를 가져온다.
- StandardServletEnvironment의 우선순위
- ServletConfig 매개변수
- ServletContext 매개변수
- JNDI (java:comp/env/)
- JVM 시스템 프로퍼티 (-Dkey=”value”)
- JVM 시스템 환경 변수 (운영 체제 환경 변수)
이 외에도 다양한 기능들은 추후 스프링부트 내용에서 더 자세히 정리 예정이다.