빈 설정 분할
DI 컨테이너에서 관리하는 빈이 많아지면 많아질수록 설정 내용도 많아져서 관리하기가 어려워진다. 이럴 때는 빈 설정 범위를 명확히 하고 가독성도 높이기 위해 목적에 맞게 분할하는 것이 좋다.
[자바 기반 설정의 분할]
자바 기반 설정 방식에서 설정된 내용(Configuration Class)을 분할할 때는 @Import 애너테이션(org.springframework.context.annotation.Import)을 사용한다. 다음은 AppConfig 클래스의 빈 정의 내용을 DomainConfig 클래스와 InfrastructureConfig 클래스에 나눠서 분할한 예다.
- 분할한 설정 클래스를 임포트하는 대표 설정 클래스(AppConfig.java)
@Configuration
@Import({DomainConfig.class, InfrastructureConfig.class})
public class AppConfig {
/* DomainConfig.class와 InfrastructureConfig.class에 정의한 빈을 주입할 수 있다. */
}
- 분할된 설정 클래스(DomainConfig.java)
@Configuration
public class DomainConfig {
@Bean
UserService userService() {
// 생략
}
}
- 분할된 설정 클래스(InfrastructureConfig.java)
@Configuration
public class InfrastructureConfig {
@Bean
DataSource dataSource() {
// 생략
}
}
[XML 기반 설정의 분할]
XML 기반 설정 방식에서 XML 설정 파일을 분할할 때는 <import> 요소를 사용한다. 다음 예제에서는 app-config.xml의 빈 정의 내용을 domain-config.xml 파일과 infra-config.xml 파일에 나눠서 분할한다.
- 분할한 XML 파일을 임포트하는 대표 XML 파일(app-config.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:conf/domain-config.xml" />
<import resource="classpath:conf/infra-config.xml" />
<!--
domain-config.xml과 infra-config.xml에 정의된 빈을 참조할 수 있다.
-->
</beans>
- 분할된 XML 파일(domain-config.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="..." />
</beans>
- 분할된 XML 파일(infra-config.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="..." />
</beans>
프로파일별 설정 구성
스프링 프레임워크에서는 설정 파일을 특정 환경이나 목적에 맞게 선택적으로 사용할 수 있도록 그룹화할 수 있으며, 이 기능을 프로파일(profile)이라고 한다. 예를 들어, 애플리케이션이 실행될 환경마다 서로 다른 프로파일을 만든다면 개발 환경을 위한 development 프로파일, 검증 환경을 위한 staging 프로파일, 실제 운영 환경을 위한 production 프로파일 등을 만들 수 있을 것이다.
[프로파일 정의]
자바 기반 설정 방식
자바 기반 설정 방식에서 프로파일을 지정할 때는 @Profile 애너테이션(org.springframework.context.annotation.Profile)을 사용한다.
- 자바 기반 설정 방식에서의 프로파일 정의
@Configuration
@Profile("development")
public class DevelopmentConfig {
// 생략
}
@Configuration
@Profile("staging")
public class StagingConfig {
// 생략
}
@Configuration
@Profile("production")
public class ProductionConfig {
// 생략
}
한편, 클래스 레벨이 아니라 메서드 레벨로 적용 범위를 좁힐 수도 있다.
- 자바 기반 설정 방식에서 메서드 레벨로 프로파일 정의
@Configuration
public class AppConfig {
@Bean(name = "dataSource")
@Profile("development")
DataSource dataSourceForDevelopment() {
// 생략
}
@Bean(name = "dataSource")
@Profile("staging")
DataSource dataSourceForStaging() {
// 생략
}
@Bean(name = "dataSource")
@Profile("production")
DataSource dataSourceForProduction() {
// 생략
}
}
@Profile 애너테이션에서는 @Profile({"development", "staging"})처럼 여러 개의 프로파일을 지정하거나 production 프로파일만 제외한다는 의미로 @Profile("!production")과 같이 부정형으로 표현할 수도 있다. 이렇게 프로파일을 개발 환경별로 구분하는 방식은 개발이 어느 정도 진행된 다음에 다른 개발 환경으로 쉽게 옮겨갈 수 있게 해주는 유용한 기법이다.
XML 기반 설정 방식
한편 XML 기반 설정 방식에서는 <beans> 요소의 profile 속성을 활용한다. 다음 예는 프로파일별로 하나의 XML 설정 파일을 사용한 예다.
- XML 기반 설정 방식에서의 프로파일 정의(XML 파일 하나에 하나의 프로파일)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
profile="development">
<!-- 이 안에서 정의한 내용은 지정한 프로파일 내에서만 유효하다. -->
</beans>
만약 하나의 XML 안에 다른 프로파일도 함께 정의하고 싶다면 다음과 같이 <beans> 요소를 중첩해서 profile 속성을 지정하면 된다.
- XML 기반 설정 방식에서의 프로파일 정의(XML 파일 하나에 여러 개의 프로파일)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<beans profile="development">
<!-- 이 안에서 정의한 내용은 development 프로파일 내에서만 유효하다. -->
<bean id="dataSource" class="...">
<!-- 생략 -->
</bean>
</beans>
<beans profile="staging">
<!-- 이 안에서 정의한 내용은 staging 프로파일 내에서만 유효하다. -->
<bean id="dataSource" class="...">
<!-- 생략 -->
</bean>
</beans>
<beans profile="production">
<!-- 이 안에서 정의한 내용은 production 프로파일 내에서만 유효하다. -->
<bean id="dataSource" class="...">
<!-- 생략 -->
</bean>
</beans>
</beans>
여러 프로파일을 동시에 지정하고 싶다면 profile="프로파일1, 프로파일2"와 같이 쉼표로 구분해서 나열할 수 있다.
애너테이션 기반 설정 방식
한편, 애너테이션 기반 설정 방식에서는 다음과 같이 @Profile 애너테이션에 프로파일을 지정할 수 있다.
- 애너테이션 기반 설정 방식에서의 프로파일 정의
@Component
@Profile("staging")
public class DummyUserRepository implements UserRepository {
// 생략
}
만약 프로파일이 별도로 지정되지 않은 빈 설정이 있다면 이것들은 모든 프로파일에서 사용 가능하다고 보면 된다.
[프로파일 선택]
앞서 프로파일별로 설정을 정리했다면 이제는 실행 시 어떤 프로파일을 선택해야 할지 알려줄 차례다. 이 정보는 자바의 시스템 프로퍼티를 통해 전달할 수 있는데, 자바 애플리케이션을 실행할 때 명령행 옵션으로 spring.profiles.active라는 프로퍼티 값과 사용할 프로파일 이름을 지정하면 된다.
- 자바 명령행 옵션으로 프로파일을 지정하는 방법
-Dspring.profiles.active=production
만약 프로파일을 여러 개 선택하고 싶으면 쉼표로 구분해서 나열할 수 있다. 자바 명령행 옵션으로 전달하는 방법 외에도 환경 변수를 이용할 수도 있는데 환경 변수명 SPRING_PROFILES_ACTIVE에 사용할 프로파일 이름을 지정하면 된다.
- 환경 변수로 프로파일을 지정하는 방법
export SPRING_PROFILES_ACTIVE=production
웹 애플리케이션에서는 웹 애플리케이션 설정 파일(Web Application Deployment Descriptor)인 web.xml에 다음과 같이 지정한다.
- web.xml에 프로파일을 지정하는 방법
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>production</param-value>
</context-param>
spring.profiles.active를 따로 지정하지 않았다면 기본값으로 spring.profiles.default에서 지정된 프로파일을 사용한다. 웹 애플리케이션이라면 위와 같이 web.xml에 spring.profiles.default를 설정해서 기본 프로파일을 지정한 다음 프로파일을 바꾸고 싶을 때만 자바 명령행 옵션으로 spring.profiles.active를 지정해 기본 프로파일을 덮어쓰면 된다.
댓글