• 스프링 XML 구성으로 속성 값을 설정하던 지난 10년간은 명시적으로 빈을 구성하지 않고는 속성을 설정하는 마땅한 방법이 없었다.
  • 스프링 부트는 구성 속성(configuration property)을 사용하는 방법을 제공한다.
  • 스프링 애플리케이션 컨텍스트에서 구성 속성은 빈의 속성이다.

자동-구성 세부 조정하기

  • 두 가지 형태의 서로 다르면서도 관련이 있는 구성
    • 빈 연결: 스프링 애플리케이션 컨텍스트에서 빈으로 생성되는 애플리케이션 컴포넌트 및 상호 간에 주입되는 방법을 선언하는 구성
    • 속성 주입: 스프링 애플리케이션 컨텍스트에서 빈의 속성 값을 설정하는 구성

스프링 환경 추상화 이해하기

  • 스프링 환경 추상화(environment abstraction)는 구성 가능한 모든 속성을 한 곳에서 관리하는 개념이다.
  • 스프링 환경에서 속성의 근원
    • JVM 시스템 속성
    • 운영체제의 환경 변수
    • 명령행 인자
    • 애플리케이션의 구성 파일
  • properties 파일에서 실행 포트 변경하기
server.port = 9090
  • 애플리케이션 실행시 명령행 인자로 실행 포트 변경
java -jar tacocloud-0.0.5-SNAPSHOT.jar -jar --server.port=9090
  • 운영체제 환경 변수로 실행 포트 변경
    • 환경 변수로 속성을 설정할 떄는 속성 이름의 형태가 운영체제 규칙에 맞춰서 약간 달라진다.
export SERVER_PORT=9090

데이터 소스 구성하기

  • 스프링 부트 사용 시, 구성 속성을 통해서 DataSource 빈을 명시적으로 구성할 필요없다.
    • DataSource 빈을 자동-구성할 때 스프링 부트가 아래의 속성 설정을 연결 데이터로 사용한다.
    • 톰캣의 JDBC 커넥션 풀을 classpath에서 자동으로 찾을 수 있다면 DataSource 빈이 그것을 사용한다.
    • 그렇지 않다면 스프링 부터는 다음 중 하나의 다른 커넥션 풀을 claspath에서 찾아서 사용한다.
      • HikariCP
      • Commons DBCP 2
spring:  
  datasource:  
    url: jdbc:mysql://localhost:3306/test  
    username: root  
    password: password  
    driver-class-name: com.mysql.cj.jdbc.Driver
  • spring.datasource.schemaspring.datasource.data 속성을 사용하면 애플리케이션이 시작될 때 데이터베이스를 초기화하는 SQL 스크립트의 실행을 할 수 있다.

내장 서버 구성하기

  • server.port = 0으로 지정하면, 사용 가능한 포트를 무작위로 선택하여 시작된다.
    • 동시적으로 실행되는 어떤 테스트도 같은 포트 번호로 인한 충돌이 생기지 않는다.
    • 마이크로서비스와 같이 애플리케이션이 시작되는 포트가 중요하지 않을 때도 유용하다.
  • HTTPS 요청 처리를 위한 컨테이너 설정

로깅 구성하기

  • logging.level: 각 logger 별 로깅 레벨 설정
  • logging.file.name: 생성될 로그 파일 경로와 이름
logging:  
  level:  
    root: WARN  
    org.springframework.security: DEBUG  
  file:  
    name: /var/logs/TacoCloud.log

다른 속성의 값 가져오기

  • 다른 구성 속성으로부터 값을 가져올 수도 있다.
greeting:  
  welcome: Your are using ${spring.application.name}.

우리의 구성 속성 생성하기

  • @ConfigurationProperties를 통해 구성 속성을 가져오는 방법 2가지
    • @ConfigurationProperties를 클래스에 선언하고, @Configuration 클래스의 메서드로 @Bean 등록
    • @EnableConfigurationProperties/@ConfigurationPropertiesScan 을 통해서 자동으로 빈으로 등록
    • 코틀린에서 생성자를 통해서 구성 속성을 바인딩하려면 두번째 방법을 사용해야 된다.
@ConfigurationPropertiesScan("junroot.study.tacos")  
@SpringBootApplication  
class StudyApplication {
	// ... 
}
@ConfigurationProperties(prefix = "taco.orders")  
@ConstructorBinding  
data class OrderProps(  
   val pageSize: Int  
)
taco:  
  orders:  
    pageSize: 10

프로파일 사용해서 구성하기

  • 애플리케이션이 서로 다른 런타임 환경에 배포, 설치될 때는 대개 구성 명세가 달라진다.
  • 각 운영체제의 환경 변수를 사용해서 구성하는 것도 방법이지만, 환경 변수의 변경을 추적 관리하거나 오류가 있을 경우에 변경 전으로 바로 되돌릴 수 있는 방법이 마땅치 않다.
  • 각 환경에 적합한 속성들을 설정하는 프로파일을 정의할 수 있다.
  • 참고 자료

프로파일 특정 속성 정의하기

  • 하나의 application.properties 파일에 모든 프로파일 속성 정의하는 방법
    • ---를 기준으로 프로필을 분리할 수 있다.
    • spring.config.activate.on-profile을 명시하지 않으면 프로파일에 특정되지 않고 공통으로 적용되는 기본 속성과 함께 프로파일 특정 속성을 지정할 수 있다.
spring:
    config:
        activate:
            on-profile: test
name: test-YAML
environment: testing
enabled: false
servers: 
    - www.abc.test.com
    - www.xyz.test.com
---
spring:
    config:
        activate:
            on-profile: prod
name: prod-YAML
environment: production
enabled: true
servers: 
    - www.abc.com
    - www.xyz.com
  • application-{프로파일 이름}.properties로 분리하는 방법

프로파일 활성화 하기

  • WebApplicationInitializer 인터페이스를 통해 프로그래밍 방식으로 설정하기
@Configuration
public class MyWebApplicationInitializer 
  implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
 
        servletContext.setInitParameter(
          "spring.profiles.active", "dev");
    }
}
  • ConfigurableEnvironment를 통해 프로그래밍 방식으로 설정하기
@Autowired
private ConfigurableEnvironment env;
...
env.setActiveProfiles("someProfile");
  • 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>
  • JVM 시스템 파라미터
-Dspring.profiles.active=dev
  • 환경 변수
export spring_profiles_active=dev
  • 메이븐 프로파일
<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>
  • 테스트 코드애서 @ActiveProfile
@ActiveProfiles("dev")
  • 동시에 여러 개를 설정해뒀을 때는 위에 있을수록 높은 우선순위를 가지게 된다.
    1. web.xml을 통한 컨텍스트 파라미터
    2. WebApplicationContext
    3. JVM 시스템 파라미터
    4. 환경 변수
    5. Maven 프로파일

프로파일을 사용해서 조건별로 빈 생성하기

  • @Profile 애노테이션은 다음 방식으로 사용할 수 있다.

    • @Component또는 @Configuration 클래스의 타입-레벨 애노테이션
    • 커스텀 스테레오타입 애노테이션에 결합되는 메타 애노테이션 용도
    • @Bean 메소드의 메소드 레벨 애노테이션
  • 기본적으로 @Profile 애노테이션 안에 지정된 프로파일 중 하나 이상이 활성화 되어 있으면 빈으로 생성된다.

    • @Profile({"dev", "qa"})
  • 프로파일 이름의 나열은 or 연산으로 포함된다. 좀 더 복잡한 로직을 위해서는 p1 & p2 같은 프로필 표현식을 사용할 수 있다.

  • 어떤 프로파일이 활성화 되지 않았을 때 빈으로 생성하고 싶다면 !를 붙이면된다.

    • 아래의 예는 p1이 활성화 되었거나 p2가 활성하되지 않으면 빈으로 생성한다.
    • @Profile({"p1", "!p2"})