Spring의 @Profile에 대해서 알아보자

David Lee·2023년 10월 30일
0
post-thumbnail

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에 대해 직, 간접적으로 사용
  • 사용자 정의 주석을 작성하기 위한 meta-annotation으로 사용
  • @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.propertiesapplication.yaml에 속성을 전달함으로써 프로파일을 실행시킬 수 있다.

# applicaton.yaml
spring:
  profiles:
    include:
      - "common"
      - "local"

위와 같이 여러개의 프로파일을 같이 실행시킬 수 있다. 자주 함께 사용하는 프로파일들의 경우 Group으로 묶어서 실행할 수 있다.

spring:
  profiles:
    group:
      production:
      - "proddb"
      - "prodmq"

위의 코드는 production이라는 프로파일 명으로 proddb프로파일과 prodmq프로파일을 그룹화 한 것으로 production 프로파일을 application.propertiesapplication.yaml에 포함시키거나 jar 실행 변수로--spring.profiles.active=production를 추가함으로써 그룹화된 프로파일도 실행할 수 있다.

결론

간단하게 프로파일만 구분해서 활용하면 될 것이라고 생각한 @Profile 어노테이션이 다양한 사용법과 활용 방안을 갖고 있다는것을 공부할 수 있는 좋은 계기였다.
특히 오버로딩된 Bean에 대한 프로파일 구분에 대해서 좋은 해답을 얻을 수 있었다.

출처

profile
쌓아가기

0개의 댓글

관련 채용 정보