@ConditionalOnProperty와 @Profile, @Value

양성준·2025년 3월 19일

스프링

목록 보기
15/49

Spring Boot에서는 설정값을 동적으로 변경하고, 환경(프로필)에 따라 다르게 Bean을 등록하는 방법이 여러가지 있다.
application.yml 설정 파일, @ConditionalOnProperty, @Profile, @Value 이 네 가지를 활용하여 환경별로 설정을 관리하는 방법을 알아보자!

application.yml 기본 설정

  • Spring Boot의 application.yml은 환경별 설정을 쉽게 관리할 수 있는 강력한 기능을 제공한다.
  • 예를 들어, 파일 기반 저장소와 메모리 기반 저장소를 선택하는 설정을 정의할 수 있다.
discodeit:
  repository:
    type: file  # 사용할 Repository 유형 (file | jcf)
    file-directory: "${user.dir}/discodeit/data"  # 파일이 저장될 경로
    # user.dir을 해줘야 루트 디렉토리에 절대경로처럼 들어가서 안전함
  • discodeit.repository.type: 어떤 저장소를 사용할지 선택 (file 또는 jcf)
  • discodeit.repository.file-directory: 파일 저장 경로 지정 (discodeit/data)
    (이름은 아무렇게나 해도 됨, 대신 @ConditionalOnProperty로 가져올 때 name 명시!)
  • 해당 설정값을 적용하는 방법은 @ConditionalOnProperty와 @Value

@ConditionalOnProperty - 특정 설정 값에 따라 Bean 등록 제어

  • Spring Boot에서는 설정값(application.yml)에 따라 특정 Bean을 자동으로 등록하거나 제외할 수 있다.
  • 이를 위해 @ConditionalOnProperty를 사용!
@Repository
@ConditionalOnProperty(name = "discodeit.repository.type", havingValue = "file")
public class FileBinaryContentRepository implements BinaryContentRepository {
    // 파일 기반 Repository 구현
}

@Repository
@ConditionalOnProperty(name = "discodeit.repository.type", havingValue = "jcf", matchIfMissing = true)
public class JCFBinaryContentRepository implements BinaryContentRepository {
    // JCF 기반 Repository 구현
}
  • 설정 값이 file이면 FileBinaryContentRepository가 Bean으로 등록
  • 설정 값이 jcf 또는 없으면 JCFBinaryContentRepository가 기본적으로 등록 (matchIfMissing = true)
  • @ConditionalOnProperty를 사용하면 application.yml만 변경해도 Bean을 제어할 수 있음!

@Profile - 실행 환경(프로필)에 따라 다른 Bean을 등록

  • 환경별로 다른 설정을 적용하고 싶다면 @Profile을 사용할 수 있다. (ex 개발환경, 로컬환경, 배포환경)
  • @ConditionalOnProperty는 설정 값 기반으로 Bean을 등록하지만,
    @Profile은 Spring Boot의 spring.profiles.active 값에 따라 다른 Bean을 등록함!
  • 배포나 실행할 때 spring.profiles.active=dev 또는 spring.profiles.active=prod와 같이 설정하면,
    해당 프로필과 일치하는 @Profile("dev") 또는 @Profile("prod")이 붙은 Bean만 등록된다.
@Repository
@Profile("file")  //"file" 프로필이 활성화된 경우만 등록됨
public class FileBinaryContentRepository implements BinaryContentRepository {
    // 파일 기반 Repository 구현
}

@Repository
@Profile("jcf")  //"jcf" 프로필이 활성화된 경우만 등록됨
public class JCFBinaryContentRepository implements BinaryContentRepository {
    // JCF 기반 Repository 구현
}

spring:
  profiles:
    active: file  
  • 현재 프로필이 file이므로, FileBinaryContentRepository가 활성화

application.yml을 멀티파트로 나눠서 @Profile과 함께 사용

  • Spring Boot에서는 환경별 설정을 yml 파일에서 멀티파트로 나눠서 관리할 수도 있다. (가장 많이 사용)
  • 개별 파일로 분리하는 것보다 이걸 더 많이 사용한다.
# [공통 설정]
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      maximum-pool-size: 10

---
# [개발 환경 설정 - JCF 사용]
spring:
  profiles: dev
  datasource:
    url: jdbc:mysql://dev-db.local:3306/devdb
    username: devuser
    password: devpass

discodeit:
  repository:
    type: jcf  # 개발 환경에서는 JCF 사용

---
# [운영 환경 설정 - File 사용]
spring:
  profiles: prod
  datasource:
    url: jdbc:mysql://prod-db.local:3306/proddb
    username: produser
    password: prodpass

discodeit:
  repository:
    type: file  # 운영 환경에서는 File 사용
    file-directory: /var/app/files
  • spring.profiles.active=dev (개발 환경)
    • discodeit.repository.type = jcf → JCFBinaryContentRepository가 활성화됨.
  • spring.profiles.active=prod (운영 환경)
    • discodeit.repository.type = file → FileBinaryContentRepository가 활성화됨.
    • 파일 저장 경로는 /var/app/files

@Value - application.yml 값 주입

  • Spring Boot에서 설정값을 직접 Java 클래스에서 사용하고 싶을 때 @Value를 사용할 수 있다.
public class FileBinaryContentRepository {

    private final Path directory;

    public FileBinaryContentRepository(@Value("${discodeit.repository.file-directory}") String fileDir) {
        this.directory = Paths.get(System.getProperty("user.dir"), fileDir, "binarycontents");
    }
}
  • application.yml의 discodeit.repository.file-directory 값을 읽어서 fileDir에 주입
  • System.getProperty("user.dir")와 결합하여 실행 경로 기준으로 저장 경로 설정
  • 설정 값을 쉽게 변경할 수 있어 하드코딩을 피할 수 있음
    • yml 파일이 없다면, 경로가 변경되었을 때 모든 파일을 다 변경해야한다.
profile
백엔드 개발자를 꿈꿉니다.

0개의 댓글