인프라 빈 구성 정보의 분리

Sol's·2023년 5월 28일
0

토비의 스프링 부트

목록 보기
17/31

이전 글에서 살펴보았듯이, 빈 구성정보를 분리하여 관리해 보겠습니다.
우선 사용자 구성정보 Bean들은 ComponentScan을 통해 등록이 되고 있습니다.

하지만, 자동 구성정보까지 ComponentScan이 Bean으로 등록하고 있습니다.
이제 자동구성정보ComponentScan이 아닌 애플리케이션 실행 시 자동으로 등록이 되게 설정하겠습니다.

ComponentScan의 적용 범위

우선 ComponentScan의 적용범위를 알아야 합니다.
적용 범위는 ComponentScan의 패키지부터 아래의 모든 정보를 스캔합니다.
따라서, ConfigComponentScan의 패키지 밖으로 빼내야 합니다.

Config 폴더를 만들어 클래스를 분리하였습니다.
이제 ComponentScan의 관리대상 밖입니다.
애플리케이션을 실행해 보겠습니다.

ServletWebServerFactory bean defined in the context.

서블릿팩토리를 찾을 수 없다고 에러가 발생합니다.
Bean으로 등록되지 못해서 그렇습니다.

그럼 이제 Config클래스에있는 Bean들을 ComponentScan이 아닌 자동으로 Bean으로 등록되게 해보겠습니다.

@import(클래스 구성정보)

@import를통해 Bean으로 애플리케이션 실행 시 주입할 수 있습니다.
Component와 관련된 애노테이션이 있는 클래스에 @import를 사용하면 Bean 구성정보를 직접 추가할 수 있습니다.

@Retention(RetentionPolicy.RUNTIME) // 런타임까지 애노테이션 정보가 유지되게 합니다.
@Target(ElementType.TYPE) // 클래스, 인터페이스, Enum에 부여합니다.
@Configuration
@ComponentScan
@Import({DispatcherServlet.class, TomcatWebServerConfig.class})
public @interface MySpringBootApplication {
}
@Configuration
public class DispatcherServletConfig {
    @Bean
    public DispatcherServlet dispatcherServlet(){
        // DispatcherServlet이 이용할 컨트롤러를 찾아야 하기때문에 ApplicationContext를 생성자로 주어야합니다.
        // 스프링이 알아서 ApplicationContext를 주입해 줍니다!!
        return new DispatcherServlet();
    }
}
@Configuration
public class TomcatWebServerConfig {
    @Bean
    public ServletWebServerFactory servletWebServerFactory(){
        return new TomcatServletWebServerFactory();
    }
}

문제점

이렇게 한다면 자동구성정보를 추가할때마다 MySpringBootApplication@import에 찾아가 클래스 구정정보를 넣어주어야 합니다.
최상위 레벨에 정보가 계속 추가되는것을 좋지 않습니다.

문제 해결을 위해 EnableMyAutoConfiguration 메타 어노테이션을 생성하겠습니다.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import({DispatcherServletConfig.class, TomcatWebServerConfig.class})
public @interface EnableMyAutoConfiguration {
}

Enable은 ~기능을 사용하게 해줘 라는 뜻입니다.

그리고 이제 Main어노테이션인 MySpringBootApplication메타 어노테이션에는 EnableMyAutoConfiguration 메타 어노테이션을 추가하면 됩니다.

@Retention(RetentionPolicy.RUNTIME) // 런타임까지 애노테이션 정보가 유지되게 합니다.
@Target(ElementType.TYPE) // 클래스, 인터페이스, Enum에 부여합니다.
@Configuration
@ComponentScan
@EnableMyAutoConfiguration
public @interface MySpringBootApplication {
}

이제 MySpringBootApplication을 Config 폴더로 옮겨줄 것입니다.
그 이유는 비지니스 로직과 Config 정보를 폴더 단위로 관리하여 가독성과 유지보수에 쉽게하기 위해서 입니다.

정리


처음 리펙토링을 했을때의 구성정보입니다.
@import를 통해 자동구성정보들을 MySpringBootApplication에 구성정보를 주입하였습니다.

한단계 더 리펙토링을 진행했을떄의 구성정보입니다.

한단계 더 추상화 되었습니다.
위에 설명하였듯이, 최상위 어노테이션인 MySpringBootApplication에 변경이 자주 일어나면 안되기 때문에,
EnableMyAutoConfiguration어노테이션을 생성하여 자동구성정보들을 관리하게 하였고
MySpringBootApplication에서는 EnableMyAutoConfiguration애노테이션을 사용하였습니다.

따라서 MySpringBootApplication자동구성정보에대해 직접적으로 알지 못하고, EnableMyAutoConfiguration만을 바라보기때문에 느슨한 연결이 되었습니다!

느슨한 연결이 되었다면 유연성과 코드의 재사용성에 용의하기때문에 유리합니다!

profile
배우고, 생각하고, 행동해라

0개의 댓글