헬로우월드 2024. 11. 14. 20:08

@Value는 Spring에서 외부화된 속성 값을 주입하는 데 유용한 애노테이션입니다. @Value를 통해 application.properties 또는 application.yml 파일의 값을 주입하거나, 스프링 표현 언어(SpEL)를 사용해 런타임 시 계산된 값을 주입할 수 있습니다. 다음은 @Value의 다양한 활용 방법과 설정 방법에 대한 설명입니다.

1. 기본 사용법: 외부 속성 값 주입

@Value 애노테이션은 외부 속성을 주입하는 데 사용됩니다. 예를 들어, application.properties 파일에서 catalog.name 속성을 정의하고 이를 클래스에 주입할 수 있습니다.

# application.properties 파일
catalog.name=MovieCatalog

 

@Component
public class MovieRecommender {

    private final String catalog;

    // @Value를 사용해 catalog.name 속성 값을 주입
    public MovieRecommender(@Value("${catalog.name}") String catalog) {
        this.catalog = catalog;
    }
}

위 코드에서 catalog 필드는 MovieCatalog 값으로 설정됩니다.

Java 기반 구성 메타데이터

외부 파일을 읽어올 수 있도록 @PropertySource@Configuration 클래스에 추가해야 합니다.

@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig { }

이렇게 하면 Spring이 application.properties 파일을 로드하고 @Value에 정의된 속성 값을 주입할 수 있습니다.

2. 디폴트 값 설정

속성이 존재하지 않을 때 사용할 디폴트 값을 설정할 수도 있습니다.

@Component
public class MovieRecommender {

    private final String catalog;

    // catalog.name이 설정되지 않은 경우 defaultCatalog를 사용
    public MovieRecommender(@Value("${catalog.name:defaultCatalog}") String catalog) {
        this.catalog = catalog;
    }
}

위 예제에서 catalog.name 속성이 정의되지 않았을 경우 catalog 필드는 defaultCatalog 값으로 설정됩니다.

3. 강력한 속성 해석을 위한 설정

Spring은 기본적으로 너그러운 속성 해석을 지원하여 속성 값을 찾지 못하면 ${catalog.name}과 같은 원래의 속성 이름을 그대로 주입합니다. 그러나 존재하지 않는 값을 엄격하게 관리하려면 PropertySourcesPlaceholderConfigurer 빈을 설정하여 강력한 해석을 활성화할 수 있습니다.

@Configuration
public class AppConfig {

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

PropertySourcesPlaceholderConfigurer를 설정하면, 속성 파일에서 ${} 플레이스홀더가 해석되지 않으면 Spring 초기화가 실패하게 됩니다. JavaConfig에서 PropertySourcesPlaceholderConfigurer를 사용할 때는 @Bean 메서드를 static으로 선언해야 합니다.

4. SpEL(Spring Expression Language) 사용

@Value는 스프링 표현 언어(SpEL)를 사용하여 런타임 시 동적으로 값을 계산할 수도 있습니다. 예를 들어 시스템 속성을 기반으로 값을 생성할 수 있습니다.

@Component
public class MovieRecommender {

    private final String catalog;

    // SpEL 표현식 사용
    public MovieRecommender(@Value("#{systemProperties['user.catalog'] + 'Catalog' }") String catalog) {
        this.catalog = catalog;
    }
}

위 예제에서 user.catalog라는 시스템 속성의 값을 기반으로 catalog 필드에 값을 할당합니다.

5. 복잡한 데이터 구조 지원

SpEL을 사용하여 더 복잡한 데이터 구조도 주입할 수 있습니다. 예를 들어, Map이나 List와 같은 컬렉션을 생성하여 주입할 수 있습니다.

@Component
public class MovieRecommender {

    private final Map<String, Integer> countOfMoviesPerCatalog;

    // SpEL을 사용하여 Map 구조 주입
    public MovieRecommender(
            @Value("#{{'Thriller': 100, 'Comedy': 300}}") Map<String, Integer> countOfMoviesPerCatalog) {
        this.countOfMoviesPerCatalog = countOfMoviesPerCatalog;
    }
}

위 예제에서 countOfMoviesPerCatalog 필드는 {'Thriller': 100, 'Comedy': 300}이라는 초기 값으로 설정됩니다.

6. ConversionService를 통한 타입 변환

Spring은 @Value를 통해 주입된 값을 디폴트 타입 변환을 지원하여 Integerint로 자동 변환할 수 있습니다. 여러 개의 쉼표로 구분된 값은 자동으로 String 배열로 변환됩니다.

또한, 사용자 정의 타입 변환을 추가하고 싶다면 ConversionService 빈을 설정할 수 있습니다. 다음 예제에서는 사용자 정의 컨버터를 추가합니다.

@Configuration
public class AppConfig {

    @Bean
    public ConversionService conversionService() {
        DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
        conversionService.addConverter(new MyCustomConverter()); // 사용자 정의 변환기 추가
        return conversionService;
    }
}

@Value는 내부적으로 ConversionService를 사용하여 문자열 값을 타겟 타입으로 변환합니다. MyCustomConverterConversionService에서 사용할 사용자 정의 컨버터로, 필요한 경우 직접 작성할 수 있습니다.

7. Spring Boot의 디폴트 설정

Spring Boot는 디폴트로 PropertySourcesPlaceholderConfigurer 빈을 자동 구성하여 application.propertiesapplication.yml 파일의 속성을 로드합니다. 별도로 PropertySourcesPlaceholderConfigurer를 정의하지 않아도 Spring Boot는 이러한 속성 파일의 값을 자동으로 처리합니다.

요약

  • @Value를 사용해 외부 속성이나 동적으로 계산된 값을 주입할 수 있습니다.
  • 디폴트 값을 제공하거나 존재하지 않는 값을 엄격하게 관리할 수 있습니다.
  • SpEL을 사용하여 동적 표현식이나 복잡한 데이터 구조를 주입할 수 있습니다.
  • Spring의 디폴트 ConversionService를 통해 타입 변환을 지원하며, 사용자 정의 컨버터를 추가할 수 있습니다.
  • Spring Boot에서는 application.propertiesapplication.yml의 속성을 자동으로 처리하므로 추가 설정이 필요하지 않습니다.

이러한 @Value의 기능을 통해 Spring 애플리케이션에서 외부화된 설정과 동적 값 주입이 보다 유연하게 가능합니다.