반응형

Spring Boot 및 일반 Spring 환경에서 외부 서비스 기반 설정 관리 방법

어플리케이션을 구동할 때 필요한 설정값들은 보통 환경변수(Environment Variables)나 파일에 저장하여 관리합니다. 하지만 최근에는 설정값을 Zookeeper, AWS Secrets Manager와 같은 외부 서비스에서 불러오거나, 보안을 강화하기 위해 메모리 내에서만 설정값을 저장하는 방식이 점점 더 선호되고 있습니다. 이러한 요구사항을 충족시키기 위해 Spring Boot와 일반 Spring 환경에서 설정값을 효과적으로 관리하는 방법을 소개합니다.

Spring Boot에서 환경 설정값 관리하기

Spring Boot는 EnvironmentPostProcessor를 활용하여 어플리케이션 시작 시점에 환경 설정값을 동적으로 변경하거나 추가할 수 있습니다. 이를 통해 외부 서비스에서 설정값을 불러와 적용하는 것이 가능합니다.

EnvironmentPostProcessor 활용 예제

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;

import java.util.Map;
import java.util.stream.Collectors;
import java.util.Arrays;
import java.util.List;

public class PriceCalculationEnvironmentPostProcessor implements EnvironmentPostProcessor {

    private static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";
    private static final List<String> names = Arrays.asList("config.key1", "config.key2"); // 예시 키 리스트

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        var system = environment.getPropertySources().get(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);

        Map<String, Object> prefixed = names.stream()
            .collect(Collectors.toMap(this::rename, system::getProperty));
        environment.getPropertySources()
            .addAfter(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, new MapPropertySource("prefixer", prefixed));
    }

    private String rename(String originalName) {
        return "prefix." + originalName; // 원하는 방식으로 키 이름 변경
    }
}

적용 방법

  1. Spring Boot의 spring.factories 파일에 등록

src/main/resources/META-INF/spring.factories 파일에 다음 내용을 추가합니다:

org.springframework.boot.env.EnvironmentPostProcessor=\
com.example.PriceCalculationEnvironmentPostProcessor
  1. 어플리케이션 실행 시 자동으로 적용

Spring Boot는 spring.factories에 등록된 EnvironmentPostProcessor를 자동으로 감지하여 적용합니다.

Spring Boot를 사용하지 않는 환경에서 설정값 관리하기

Spring Boot가 아닌 일반 Spring 환경에서도 설정값을 외부 서비스에서 불러오거나 메모리 내에서 관리할 수 있습니다. 이를 위해 ApplicationContextInitializer를 활용할 수 있습니다.

ApplicationContextInitializer 활용 예제

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.boot.context.properties.bind.Binder;

public class PropertyOverrideContextInitializer 
        implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        var environment = applicationContext.getEnvironment();
        MyConfigProps configProps = Binder.get(environment)
                                         .bind("my-config", MyConfigProps.class)
                                         .orElse(new MyConfigProps());
        System.out.println(configProps.getHomekey());
        // 추가 설정 로직 구현
    }
}

적용 방법

ApplicationContextInitializer를 적용하는 방법은 여러 가지가 있습니다. 아래에 네 가지 주요 방법을 소개합니다.

  1. web.xml 또는 Java Config에서 contextInitializerClasses 추가

web.xml을 사용하는 경우:

<context-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>com.example.PropertyOverrideContextInitializer</param-value>
</context-param>

Java Config를 사용하는 경우:

import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;

@ContextConfiguration(initializers = PropertyOverrideContextInitializer.class)
public class AppConfig {
    // Bean 정의 등
}
  1. Spring만 사용하는 경우
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainApp {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ctx.addInitializer(new PropertyOverrideContextInitializer());
        ctx.register(AppConfiguration.class);
        ctx.refresh();

        JobLauncher launcher = ctx.getBean(JobLauncher.class);
        // 어플리케이션 로직 실행
    }
}
  1. spring.factories 파일을 통한 자동 설정 (Spring Boot)

src/main/resources/META-INF/spring.factories 파일에 다음 내용을 추가합니다:

org.springframework.context.ApplicationContextInitializer=\
com.example.PropertyOverrideContextInitializer
  1. 어플리케이션 실행 시 코드로 추가 (Spring Boot)

SpringApplication을 사용하는 경우:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class YourApp {
    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(YourApp.class);
        application.addInitializers(new PropertyOverrideContextInitializer());
        application.run(args);
    }
}

SpringApplicationBuilder을 사용하는 경우:

import org.springframework.boot.builder.SpringApplicationBuilder;

public class YourApp {
    public static void main(String[] args) {
        new SpringApplicationBuilder(YourApp.class)
            .initializers(new PropertyOverrideContextInitializer())
            .run(args);
    }
}

프로퍼티 파일을 통한 설정:

application.properties 또는 application.yml 파일에 다음과 같이 설정합니다:

context.initializer.classes=com.example.PropertyOverrideContextInitializer

결론

외부 서비스에서 설정값을 불러오거나, 보안을 강화하기 위해 메모리 내에서만 설정값을 관리하고자 할 때, Spring Boot와 일반 Spring 환경에서 제공하는 EnvironmentPostProcessor와 ApplicationContextInitializer를 활용하면 효과적으로 설정값을 관리할 수 있습니다. 각 방법은 어플리케이션의 구조와 요구사항에 따라 적절히 선택하여 적용할 수 있으며, 이를 통해 보다 유연하고 안전한 설정 관리가 가능합니다.

참고 자료

  1. Baeldung - Spring Tests: Override Properties
  2. Stack Overflow - How to add custom ApplicationContextInitializer to a Spring Boot application
  3. Stack Overflow - Spring ApplicationContextInitializer and properties
  4. Stack Overflow - ApplicationContextInitializer in a non-web Spring context

이 글이 Spring 기반 어플리케이션에서 설정값을 효과적으로 관리하는 데 도움이 되길 바랍니다. 추가적인 질문이나 의견이 있으시면 댓글로 남겨주세요!

반응형

+ Recent posts