1. 개요

이 사용방법(예제)에서는 Spring의 프로필 소개에 중점을 둘 것입니다.

프로필은 프레임워크의 핵심 기능입니다. 예를 들어 dev , testprod 와 같은 다른 프로필에 bean을 매핑할 수 있습니다 .

그런 다음 서로 다른 환경에서 서로 다른 프로필을 활성화하여 필요한 빈만 부트스트랩할 수 있습니다.

2. 빈에서 @Profile 사용

간단하게 시작하여 빈을 특정 프로필에 속하게 만드는 방법을 살펴보겠습니다. 우리는 @Profile 어노테이션을 사용합니다 — 빈을 ​​해당 특정 프로필에 매핑합니다 . 어노테이션은 단순히 하나(또는 여러 개) 프로필의 이름을 사용합니다.

기본 시나리오를 고려하십시오. 개발 중에만 활성화되어야 하지만 프로덕션에 배포되지 않는 빈이 있습니다.

개발 프로필 로 해당 빈에 어노테이션을 달고  개발 중에 컨테이너에만 존재합니다. 프로덕션 환경에서는 개발자 가 활성화되지 않습니다.

@Component
@Profile("dev")
public class DevDatasourceConfig

참고로 프로필 이름 앞에 NOT 연산자(예: !dev )를 붙여 프로필에서 제외할 수도 있습니다.

예제에서 구성 요소는 개발  프로필이 활성화되지 않은 경우에만 활성화됩니다.

@Component
@Profile("!dev")
public class DevDatasourceConfig

3. XML로 프로필 선언

프로필은 XML로도 구성할 수 있습니다. <beans> 태그에는 해당 프로필의 쉼표로 구분된 값을 사용하는 프로필 속성 있습니다 .

<beans profile="dev">
    <bean id="devDatasourceConfig" 
      class="org.baeldung.profiles.DevDatasourceConfig" />
</beans>

4. 프로필 설정

다음 단계는 각 빈이 컨테이너에 등록되도록 프로필을 활성화하고 설정하는 것입니다.

이는 다양한 방법으로 수행할 수 있으며 다음 섹션에서 살펴보겠습니다.

4.1. WebApplicationInitializer 인터페이스를 통해 프로그래밍 방식으로

웹 애플리케이션에서 WebApplicationInitializer를 사용하여 프로그래밍 방식으로 ServletContext를 구성할 수 있습니다 .

프로그래밍 방식으로 활성 프로필을 설정하는 매우 편리한 위치이기도 합니다.

@Configuration
public class MyWebApplicationInitializer 
  implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
 
        servletContext.setInitParameter(
          "spring.profiles.active", "dev");
    }
}

4.2. ConfigurableEnvironment를 통해 프로그래밍 방식으로

환경에서 직접 프로필을 설정할 수도 있습니다.

@Autowired
private ConfigurableEnvironment env;
...
env.setActiveProfiles("someProfile");

4.3. web.xml 의 컨텍스트 매개변수

마찬가지로 컨텍스트 매개 변수를 사용하여 웹 애플리케이션의 web.xml 파일 에서 활성 프로필을 정의할 수 있습니다 .

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/app-config.xml</param-value>
</context-param>
<context-param>
    <param-name>spring.profiles.active</param-name>
    <param-value>dev</param-value>
</context-param>

4.4. JVM 시스템 매개변수

프로파일 이름은 JVM 시스템 매개변수를 통해 전달될 수도 있습니다. 다음 프로필은 애플리케이션 시작 시 활성화됩니다.

-Dspring.profiles.active=dev

4.5. 환경 변수

Unix 환경에서는 환경 변수를 통해 프로필을 활성화할 수도 있습니다 .

export spring_profiles_active=dev

4.6. 메이븐 프로필

Spring 프로필은 spring.profiles.active  구성 속성을 지정하여 Maven 프로필을 통해 활성화할 수도 있습니다 .

모든 Maven 프로필에서 spring.profiles.active 속성을 설정할 수 있습니다 .

<profiles>
    <profile>
        <id>dev</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <spring.profiles.active>dev</spring.profiles.active>
        </properties>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <spring.profiles.active>prod</spring.profiles.active>
        </properties>
    </profile>
</profiles>

해당 값은 application.properties  의 @ spring.profiles.active@ 자리 표시자를 대체하는 데 사용됩니다 .

spring.profiles.active=@spring.profiles.active@

이제 pom.xml 에서 리소스 필터링을 활성화해야 합니다 .

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
    ...
</build>

적용할 Maven 프로필을 전환하려면 -P 매개변수를 추가합니다 .

mvn clean package -Pprod

이 명령은 응용 프로그램을 prod 프로필 용으로 패키징합니다 .  또한 이 애플리케이션이 실행 중일 때 spring.profiles.active prod를 적용합니다  .

4.7. 테스트의 @ActiveProfile

테스트를 통해 @ActiveProfile 어노테이션을 사용하여 특정 프로필을 활성화하는 프로필을 매우 쉽게 지정할 수 있습니다 .

@ActiveProfiles("dev")

지금까지 프로필을 활성화하는 여러 가지 방법을 살펴보았습니다. 이제 어느 것이 다른 것보다 우선 순위가 높은지, 우선 순위가 높은 것부터 낮은 것까지 둘 이상을 사용하면 어떤 일이 발생하는지 살펴보겠습니다.

  1. web.xml 의 컨텍스트 매개변수
  2. WebApplicationInitializer
  3. JVM 시스템 매개변수
  4. 환경 변수
  5. 메이븐 프로필

5. 기본 프로필

프로필을 지정하지 않은 모든 빈은 기본  프로필에 속합니다.

Spring은 또한 다른 프로필이 활성 상태가 아닐 때 spring.profiles.default 속성 을 사용하여 기본 프로필을 설정하는 방법을 제공합니다  .

6. 활성 프로필 가져오기

Spring의 활성 프로필은 Bean 활성화/비활성화를 위한 @Profile 어노테이션 의 동작을 구동합니다 . 그러나 프로그래밍 방식으로 활성 프로필 List에 액세스할 수도 있습니다.

Environment 또는 spring.profiles.active 를 사용 하는 두 가지 방법이 있습니다 .

6.1. 환경 사용

Environment 개체를 주입하여 활성 프로필에 액세스할 수 있습니다 .

public class ProfileManager {
    @Autowired
    private Environment environment;

    public void getActiveProfiles() {
        for (String profileName : environment.getActiveProfiles()) {
            System.out.println("Currently active profile - " + profileName);
        }  
    }
}

6.2. spring.profiles.active 사용

또는 spring.profiles.active 속성을 주입하여 프로필에 액세스할 수 있습니다  .

@Value("${spring.profiles.active}")
private String activeProfile;

여기에서 activeProfile  변수에는 현재 활성화된 프로필의 이름이 포함되며 여러 개가 있는 경우 쉼표로 구분된 이름이 포함됩니다.

그러나 활성 프로필이 전혀 없는 경우 어떤 일이 발생할지 고려해야 합니다. 위의 코드에서 활성 프로필이 없으면 응용 프로그램 컨텍스트가 생성되지 않습니다. 이로 인해 변수에 주입하기 위한 누락된 자리 표시자로 인해 IllegalArgumentException 이 발생합니다 .

이를 방지하기 위해 기본값을 정의 할 수 있습니다 .

@Value("${spring.profiles.active:}")
private String activeProfile;

이제 활성화된 프로필이 없으면 activeProfile 에 빈 문자열만 포함됩니다.

이전 예제와 같이 List에 액세스하려면 activeProfile 변수를 분할하여 수행 있습니다 .

public class ProfileManager {
    @Value("${spring.profiles.active:}")
    private String activeProfiles;

    public String getActiveProfiles() {
        for (String profileName : activeProfiles.split(",")) {
            System.out.println("Currently active profile - " + profileName);
        }
    }
}

7. 예: 프로필을 사용하여 데이터 소스 구성 분리

이제 기본 사항은 끝났으니 실제 예를 살펴보겠습니다.

개발 및 프로덕션 환경 모두에 대해 데이터 소스 구성을 유지해야 하는 시나리오를 고려하십시오 .

두 데이터 소스 구현에서 구현해야 하는 공통 인터페이스 DatasourceConfig를 생성해 보겠습니다 .

public interface DatasourceConfig {
    public void setup();
}

다음은 개발 환경의 구성입니다.

@Component
@Profile("dev")
public class DevDatasourceConfig implements DatasourceConfig {
    @Override
    public void setup() {
        System.out.println("Setting up datasource for DEV environment. ");
    }
}

프로덕션 환경을 위한 구성:

@Component
@Profile("production")
public class ProductionDatasourceConfig implements DatasourceConfig {
    @Override
    public void setup() {
       System.out.println("Setting up datasource for PRODUCTION environment. ");
    }
}

이제 테스트를 만들고 DatasourceConfig 인터페이스를 삽입해 보겠습니다. 활성 프로필에 따라 Spring은 DevDatasourceConfig 또는 ProductionDatasourceConfig 빈을 주입합니다.

public class SpringProfilesWithMavenPropertiesIntegrationTest {
    @Autowired
    DatasourceConfig datasourceConfig;

    public void setupDatasource() {
        datasourceConfig.setup();
    }
}

dev  프로필이 활성화 되면 Spring은 DevDatasourceConfig 객체를 주입하고 setup() 메서드를 호출하면 다음과 같은 결과가 출력됩니다.

Setting up datasource for DEV environment.

8. Spring Boot의 프로필

Spring Boot는 몇 가지 추가 기능과 함께 지금까지 설명한 모든 프로필 구성을 지원합니다.

8.1. 프로필 활성화 또는 설정

섹션 4에서 소개한 초기화 매개변수 spring.profiles.active 는 현재 활성 프로필을 정의하기 위해 Spring Boot의 속성으로 설정할 수도 있습니다. 이것은 Spring Boot가 자동으로 선택하는 표준 속성입니다.

spring.profiles.active=dev

그러나 Spring Boot 2.4부터는 이 속성을 spring.config.activate.on-profile 과 함께 사용할 수 없습니다 . 이는 ConfigDataException : InvalidConfigDataPropertyException 또는  InactiveConfigDataAccessException ) 을 발생시킬 수 있기 때문입니다.

프로그래밍 방식으로 프로필을 설정하기 위해 SpringApplication 클래스를 사용할 수도 있습니다 .

SpringApplication.setAdditionalProfiles("dev");

Spring Boot에서 Maven을 사용하여 프로필 을 설정하려면 pom.xmlspring-boot-maven-plugin 에서 프로필 이름을 지정할 수 있습니다  .

<plugins>
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <profiles>
                <profile>dev</profile>
            </profiles>
        </configuration>
    </plugin>
    ...
</plugins>

Spring Boot 관련 Maven 목표를 실행합니다.

mvn spring-boot:run

8.2. 프로필별 속성 파일

그러나 Spring Boot가 제공하는 가장 중요한 프로필 관련 기능은 프로필별 속성 파일입니다. 이들은 application-{profile}.properties 형식으로 이름을 지정해야 합니다 .

Spring Boot는 모든 프로필에 대한 application.properties 파일 의 속성을 자동으로 로드 하고 지정된 프로필에 대해서만 프로필별 .properties 파일 의 속성을 로드합니다.

예를 들어 application-dev.propertiesapplication-production.properties 라는 두 개의 파일을 사용하여 dev프로덕션 프로필에 대해 서로 다른 데이터 소스를 구성할 수 있습니다 .

application-production.properties 파일 에서 MySql 데이터 소스를 설정할 수 있습니다 .

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=root
spring.datasource.password=root

그런 다음 메모리 내 H2 데이터베이스를 사용하도록 application-dev.properties 파일 의 dev 프로필 에 대해 동일한 속성을 구성할 수 있습니다 .

spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa

이러한 방식으로 서로 다른 환경에 대해 서로 다른 구성을 쉽게 제공할 수 있습니다.

Spring Boot 2.4 이전에는 프로필 관련 문서에서 프로필을 활성화할 수 있었습니다. 그러나 그것은 더 이상 사실이 아닙니다.  이후 버전에서는 이러한 상황에서 프레임워크가 다시 InvalidConfigDataPropertyException 또는  InactiveConfigDataAccessException을 throw합니다.

8.3. 다중 문서 파일

별도의 환경에 대한 속성 정의를 더욱 단순화하기 위해 동일한 파일의 모든 속성을 포함하고 구분 기호를 사용하여 프로필을 나타낼 수도 있습니다.

버전 2.4부터 Spring Boot는 이전에 지원된 YAML 외에도 속성 파일에 대한 다중 문서 파일에 대한 지원을 확장했습니다 . 이제 동일한 application.properties 에서 devproduction 속성을 지정할 수 있습니다 .

my.prop=used-always-in-all-profiles
#---
spring.config.activate.on-profile=dev
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=root
spring.datasource.password=root
#---
spring.config.activate.on-profile=production
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa

이 파일은 Spring Boot에서 위에서 아래로 읽습니다. 즉, my.prop 와 같은 일부 속성이 위의 예에서 마지막에 한 번 더 발생하면 가장 끝의 값이 고려됩니다.

8.4. 프로필 그룹

Boot 2.4에 추가된 또 다른 기능은 프로필 그룹입니다. 이름에서 알 수 있듯이 유사한 프로필을 함께 그룹화할 수 있습니다 .

프로덕션 환경에 대한 여러 구성 프로필이 있는 사용 사례를 고려해 보겠습니다. 프로덕션 환경에서 데이터베이스용 proddb 및 스케줄러용 prodquartz를 예로 들어 보겠습니다 .

application.properties 파일 을 통해 이러한 프로필을 한 번에 활성화하려면 다음을 지정할 수 있습니다.

spring.profiles.group.production=proddb,prodquartz

따라서 프로덕션 프로필을 활성화하면 proddbprodquartz활성화됩니다 .

9. 결론

이 기사에서 우리는 bean에서 프로파일을 정의하는 방법 과 애플리케이션에서 올바른 프로파일을 활성화하는 방법에 대해 논의했습니다.

마지막으로 간단하지만 실제 사례를 통해 프로파일에 대한 이해를 검증했습니다.

이 사용방법(예제)의 구현은 GitHub 프로젝트 에서 찾을 수 있습니다 .

Generic footer banner