SpringBoot에 @Profile
에 대해서 살펴보자
데브코스에서 과제를 진행하면서 콘솔 입출력 방식에서 Web API로 전환시키는 과정이 필요했다. 당연히 콘솔 입출력으로 구현된 기능들을 리팩토링해서 Web API로 바꿀 계획을 갖고 있었는데 멘토님이 '@Profile
을 사용해서 기존 기능을 그대로 두고 새로 Web API 기능을 추가해서 Profile별로 실행하게 하면 좋을 것 같다' 라는 아이디어를 주셨다. 이를 활용하는 과정에서 @Profile
에 대해서 좀 더 자세히 공부하고 사용하자!라는 생각에 포스트를 작성하게 되었다.
@Profile
@Profile
에 대한 Spring Framework Document의 설명은 다음과 같다.
The
@Profile
annotation lets you indicate that a component is eligible for registration when one or more specified profiles are active.
@Profile
어노테이션은 하나 이상의 지정된 프로필이 활성화되면 구성 요소가 등록될 수 있음을 나타낸다.
@Profile
은 구성 요소를 구분함으로써 활성화된 Profile에 따라서 구성 요소가 다르게 등록되도록 하는 기능을 갖고 있다.
@Profile
사용하기@Profile
을 사용하여 등록하는 경우는 크게 3가지로 나뉜다.
@Configuration
을 포함해서, @Component
Annotation이 사용된 Class에 대해 직, 간접적으로 사용@Bean
클래스 내부의 메소드에 대해 사용@Profile
을 활용할 방법으로 동일한 이름으로 오버로딩한 빈을 여러개 두고 상황에 맞게 프로파일로 활용하면 되는거 아닌가? 라는 생각이 들었는데 이에 대해서 Spring은 이미 Note를 적어놓았다..
With
@Profile
on@Bean
methods, a special scenario may apply: In the case of overloaded @Bean methods of the same Java method name (analogous to constructor overloading), a@Profile
condition needs to be consistently declared on all overloaded methods. If the conditions are inconsistent, only the condition on the first declaration among the overloaded methods matters.
동일한 Java 메소드 이름의 @Bean
메소드가 오버로드 된 경우 @Profile
은 모두 일관되게 선언해야하며, 그렇지 않으면 첫번째 선언의 조건만을 인식한다는 것이다... 이는 Spring의 Bean 생성자 결정 알고리즘에 의한 것이라고 하는데 그렇다면 이를 어떻게 해결할 수 있을까?
If you want to define alternative beans with different profile conditions, use distinct Java method names that point to the same bean name by using the @Bean name attribute, as shown in the preceding example. If the argument signatures are all the same (for example, all of the variants have no-arg factory methods), this is the only way to represent such an arrangement in a valid Java class in the first place (since there can only be one method of a particular name and argument signature).
해결 방법도 친절하게 안내해주었다. Java 메소드 이름을 오버로딩하지 말고 @Bean
어노테이션의 name 속성을 활용하여 구분하는 방법을 사용하면 해결할 수 있다.
@Profile
을 활용할때 특별한 이름 규칙을 사용할 수 있다.
!
: 작성한 프로파일 이름에 대해 NOT
을 적용한다. &
: 작성한 프로파일 이름들에 대해서 AND
를 적용한다.|
: 작성한 프로파일 이름들에 대해서 OR
을 적용한다.→ 예를 들어 @Profile("dev & test")
로 선언된 구성요소는 dev와 test프로파일이 모두 활성화 되어야지만 사용 가능하다.
Q. 그렇다면
|
와&
를 혼용해서 사용할 수 있을까요?@Profile("prod | dev & test")
이런 식으로요
A. 하나 이상의 이름 규칙을 적용할 때는()
를 사용해서 우선 순위를 정해주어야 합니다!
@Profile("prod | dev & test")
→@Profile("prod | (dev & test)")
열심히 나눠둔 프로파일을 어떻게 활성화 할 수 있을까?
ConfigurableEnvironment.setActiveProfiles()
을 통한 프로그래밍 방식의 활성화@SpringBootApplication
public class SpringbootBasicApplication {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(SpringbootBasicApplication.class, args);
ctx.getEnvironment().setActiveProfiles("something");
ctx.refresh();
}
// ...
}
위의 코드와 같은 방식으로 프로그램 작성 단계에서 프로파일을 지정하여 실행시킬 수 있다.
spring.profiles.active
속성 전달을 통한 활성화application.properties
나 application.yaml
에 속성을 전달함으로써 프로파일을 실행시킬 수 있다.
# applicaton.yaml
spring:
profiles:
include:
- "common"
- "local"
위와 같이 여러개의 프로파일을 같이 실행시킬 수 있다. 자주 함께 사용하는 프로파일들의 경우 Group으로 묶어서 실행할 수 있다.
spring:
profiles:
group:
production:
- "proddb"
- "prodmq"
위의 코드는 production
이라는 프로파일 명으로 proddb
프로파일과 prodmq
프로파일을 그룹화 한 것으로 production
프로파일을 application.properties
나 application.yaml
에 포함시키거나 jar 실행 변수로--spring.profiles.active=production
를 추가함으로써 그룹화된 프로파일도 실행할 수 있다.
간단하게 프로파일만 구분해서 활용하면 될 것이라고 생각한 @Profile
어노테이션이 다양한 사용법과 활용 방안을 갖고 있다는것을 공부할 수 있는 좋은 계기였다.
특히 오버로딩된 Bean에 대한 프로파일 구분에 대해서 좋은 해답을 얻을 수 있었다.
@Profile
@Profile
Annotation Java doc