본문 바로가기
개발 - Coding/Java & Spring

[Spring Boot] 스프링 @Configuration 모듈화하기

by dev_jinyeong 2022. 6. 29.

스프링에서 @Configuration 모듈화하는 상황

스프링 프로젝트에서 비즈니스 로직을 구현할 때, 다형성을 적극 활용하면 좋은 경우가 있다.

예를 들어서 할인 정책을 적용할 때, 상황에 따라서 정해진 금액을 할인하는 정책과 정해진 비율을 할인하는 정책을 선택해야 하는 경우가 있다.

또는 멤버십 유형을 선택하여 유형마다 제공받을 수 있는 서비스들이 달라지는 경우에도 멤버십 객체의 역할과 구현을 분리할 수 있다.

이런 경우에는 별도의 설정 정보를 만들어서 @Configuration을 따로 관리하는 것이 좋다.

그렇다면 이 경우에 @Configuration을 여러 개 만들게 되면 이것들을 어떻게 관리하는 것이 좋을까?

반대로 하나의 @Configuration에 모든 설정 정보가 들어있는 상황에서 이것들을 어떻게 적절히 쪼개고 관리할 수 있을까?

이런 상황들은 "어떻게 Configuration들을 모듈화할 것인가?"로 요약될 수 있다.

여러 @Configuration 모듈화하기

Configuration들을 모듈화하는 상황에 대해 스프링 공식 문서에서는 구성 모듈화하기(modularizing configurations) 항목에서 다루고 있다.

https://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/modularizing-configurations.html

 

Chapter 5. Modularizing configurations

While the simplest configuration may be expressed as a single class that exposes several beans, it is often desirable to modularize configurations for reuse and clarity. 5.2. Referencing externally defined beans with @ExternalBean One configuration class

docs.spring.io

스프링 공식 문서

1. configuration을 나누고 ApplicationContext 불러 올때 다 넣기

JavaConfigApplicationContext context =
    new JavaConfigApplicationContext(AppConfigA.class, AppConfigB.class);
// both beans are still available in the resulting application context
ServiceA serviceA = context.getBean(ServiceA.class);
ServiceB serviceB = context.getBean(ServiceB.class);


ApplicationContext 생성할 때 configuration 정보를 모두 넣으면 해결할 수 있다. 그러나 이러한 해결책은 Configuration들 전체에 대한 구조를 알기 어렵고 만약 참고하는 configuration이 달라지면 코드를 직접 바꾸어주어야한다는 단점이 있다.


2. @ExternalBean 이용하기

@Configuration
public class ConfigOne {
    @Bean
    public AccountRepository accountRepository() {
// create and return anAccountRepository object
    }
}

@Configuration
public abstract class ConfigTwo {
    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl(accountRepository());
    }

    @ExternalBean
    public abstract AccountRepository accountRepository();
}

3. @Import 사용

@Configuration
public class DataSourceConfig {
    @Bean
    public DataSource dataSource() {
        return new DriverManagerDataSource(...);
    }
}

@Configuration
@Import(DataSourceConfig.class)
public class AppConfig extends ConfigurationSupport {
    @Bean
    public void TransferService transferService() {
        return new TransferServiceImpl(getBean(DataSource.class);
    }
}

4. extends ConfigurationSupport 사용

@Configuration
public class AppConfig extends ConfigurationSupport {
    @Bean
    public Service serviceA() {
        DataSource dataSource = this.getBean(DataSource.class);// provided by base class// ...
    }
}

5. @ExternalValue 사용

@ResourceBundles("classpath:/org/springframework/config/java/simple")
@Configuration
public abstract static class ConfigWithPlaceholders {
    @ExternalValue("datasource.username")
    public abstract String username();

    @Bean
    public TestBean testBean() {
        return new TestBean(username());
    }
}

6. @Configuration classes nesting

@Configuration
public class OuterConfig {
    @Bean
    public Foo outerBean() {
        // ...
    }

    @Configuration
    public static class InnerConfig {
        @Bean
        public Bar innerBean() {
            // ...
        }
    }
}

결론

@Configuration class가 여러 개 존재할 경우 관리할 수 있는 방법에는 6가지가 있었다.

이 중 자기 프로젝트에 맞는 방법을 찾아서 적용하면 된다.