Codeit/스프린트 과제

[sprint3] 심화 1 - application.yaml로 Repository 구현체 선택하기 (File/JCF)

leejunkim 2025. 6. 27. 10:35

업무: Repository 구현체 중에 어떤 구현체를 Bean으로 등록할지 Java 코드의 변경 없이 application.yaml 설정 값을 통해 제어해보세요.

  • discodeit.repository.type 설정값에 따라 Repository 구현체가 정해집니다.
  • 값이 jcf 이거나 없으면 JCF*Repository 구현체가 Bean으로 등록되어야 합니다.
  • 값이 file 이면 File*Repository 구현체가 Bean으로 등록되어야 합니다.

application.yml - 설정 파일

spring:
  application:
    name: discodeit


discodeit:
  repository:
    # jcf | file
    type: file
    file-directory: .discodeit
    extension: .ser

먼저 yml에 구현체 선택 설정정보를 추가해줬다.

이 파일에서 type을 쉽게 jcf나 file로 변경을 해주면 자동으로 그에 맞는 repository 구현체를 쓰게 하는 것이 목표다.

RepositorySettings.java - @ConfigurationProperties 클래스

@ConfigurationProperties("discodeit.repository")
// need getters and setters for spring to inject values
@Getter
@Setter
public class RepositorySettings {
    // default values unless stated otherwise
    private String type = "jcf";
    private String fileDirectory = ".discodeit";
    private String extension = ".ser";
}

먼저 @ConfigurationProperties를 통해 설정 프러퍼티 클래스를 하나 만들어줬다.

  • @ConfigurationProperties
    • application.yml 파일의 discodeit.repository 하위 프로퍼티 값들을 RepositorySettings 클래스의 필드(type, fileDirectory, extension) 에 자동으로 바인딩(연결)해주는 역할을 한다.
    • @ConfigurationProperties에 대한건 나중에 블로그 포스팅으로 더 자세히 따로 정리할 생각이다.
  • Getter와 Setter
    • Setter
      • 주입(Injection) - 스프링이 application.yml 파일의 값을 RepositorySettings 객체의 필드에 자동으로 넣어주기 위해 필요하다
      • @EnableConfigurationProperties(RepositorySettings.class) 때문에 스프링 부트가 시작되면 RepositorySettings 클래스의 비어있는 객체를 만들고, setter들을 이용해서 application.yml에 있는 값들을 파라미터로 넘겨주고 필드에 저장한다.
    • Getter
      • 다른 곳에서 그 값을 읽어가기 위해 필요하다. 예를 들면 심화 2에 나오는데, 위에 보이는 나머지 두개의 값 (fileDirectory, extension)은 File*Repository 구현체에서 읽혀서 사용된다. File*Repository 구현체로 넘어갈 때 생성자에는 RepositorySettings를 넣어준다. 

DiscodeitApplication.java (메인 파일)

@SpringBootApplication
@EnableConfigurationProperties(RepositorySettings.class)
public class DiscodeitApplication {

	public static void main(String[] args) {
  • @EnableConfigurationProperties
    • 아까 본 RepositorySettings 클래스에 @Component를 안붙혀줘도 이 어노테이션을 넣으면, 스프링 부트에게 RepositorySettings 클래스를 프로퍼티 바인딩 기능으로 활성화하고 다른 빈에서 주입하여 사용할 수 있도록 만들어달라고 요청하는 것이다.
    • 그러면 RepositorySettings 클래스는 빈은 아니지만 스프링 컨테이너가 관리하는 특별한 객체가 된다 -> @Component 계열의 어노테이션이 없어 일반적인 빈(Bean)은 아니지만, @EnableConfigurationProperties를 통해 빈처럼 스프링 컨테이너에 등록되고 다른 곳에 주입될 수 있는 자격을 얻게 된다.
@SpringBootApplication
@ConfigurationPropertiesScan
public class DiscodeitApplication {

	public static void main(String[] args) {

참고로 @EnableConfigurationProperties대신 @ConfigurationPropertiesScan을 사용할 수 있다.

@Configuration 클래스 생성 - FileRepositoryConfig, JCFRepositoryConfig

@Configuration이 들어간 클래스 생성을 했다.

  • @ConfigurationProperties를 사용한 프로퍼티 클래스 (위에 만든RepositorySettings 클래스)를 통해 빈을 주입한다
@Configuration
@ConditionalOnProperty(
        prefix = "discodeit.repository",
        name="type",
        havingValue = "jcf",
        matchIfMissing = true // 디폴트값 설정
)
public class JCFRepositoryConfig {

    @Bean
    public BinaryContentRepository binaryContentRepository() {
        return new JCFBinaryContentRepository();
    }
    ...
@Configuration
@ConditionalOnProperty(
        prefix = "discodeit.repository",
        name="type",
        havingValue = "file"
)
public class FileRepositoryConfig {

    @Bean
    public BinaryContentRepository binaryContentRepository(RepositorySettings settings) {
        return new FileBinaryContentRepository(settings);
    }
    
    ...

 

 

@ConditionalOnProperty

  • application.yml에서 두가지 버젼을 (jcf/file)을 고를 수 있는게 목표였기 때문에, @ConditionalOnProperty를 이용해서 두가지 클래스를 만들었다.
  • ConditionalOnProperty 어노테이션은 두 클래스 중 하나만 조건에 따라 빈으로 등록된다.
    • 어노테이션 설명
      • prefix - 경로 (discodeit.repository)
      • name - 키 값 (type)
      • havingValue - discodeit.repository.type 프로퍼티의 값이 jcf/file이어야 함
      • JCFRepositoryConfig
        • matchIfMissing = true: 만약 discodeit.repository.type 프로퍼티가 application.yml에 아예 존재하지 않으면, 이 조건을 true로 간주하여 디폴트로 JCFRepositoryConfig를 빈으로 등록한다
    • 주어진 조건이 충족되면, 해당 @Configuration 클래스가 활성화되고, 그 안에 있는 @Bean 어노테이션이 붙은 메소드들이 실행된다.
      • 스프링이 @Bean을 등록할 때, 파라미터로 필요한 객체(여기서는 RepositorySettings)가 이미 컨테이너에 의해 관리되고 있다면 자동으로 주입(DI)해준다.

결과

 

간단하게 getBean을 사용해서 결과를 프린트해보면 잘 나오고, 테스트 케이스도 모두 통과한다.