inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

토비의 스프링 부트 - 이해와 원리

@Configuration 과 @ComponentScan

해결된 질문

2216

cjh

작성한 질문수 24

3

@Configuration
@ComponentScan
public class HelloApplication {

    public static void main(String[] args) {
        AnnotationConfigServletWebApplicationContext applicationContext = new AnnotationConfigServletWebApplicationContext(){
            @Override
            protected void onRefresh() {
                super.onRefresh();
                ServletWebServerFactory webServerFactory = new TomcatServletWebServerFactory();
                WebServer webServer = webServerFactory.getWebServer(
                        servletContext -> {
                            servletContext.addServlet("dispatcherServlet",
                                    new DispatcherServlet(this)
                            ).addMapping("/*");
                        }
                );
                webServer.start();
            }
        };
//        applicationContext.register(HelloController.class);
//        applicationContext.register(SimpleHelloService.class);
        applicationContext.register(HelloApplication.class);
        applicationContext.refresh();
    }
}

강사님 안녕하세요,

강의를 복습하다보니 @ComponentScan을 사용할 때 @Configuration이 필요한지 의문이 들더라구요

처음에 @Configuration javaDoc를 보면 @ConponentScan 부분에

@Configuration 클래스는 구성 요소 스캐닝(component scanning)을 통해 부트스트랩될 뿐만 아니라, @ComponentScan 주석을 사용하여 스스로 구성 요소 스캐닝을 설정할 수도 있습니다.

라고 작성이 되었더라구요

@ComponentScan
public class HelloApplication {}

이 상태로 register에 등록을 해도 컴포넌트 스캔이 동작합니다.

Creating shared instance of singleton bean 'helloApplication'
Creating shared instance of singleton bean 'helloController'
Creating shared instance of singleton bean 'simpleHelloService'

@Configuration이 없어도 직접 register에 등록하면 애노테이션을 읽어서 컴포넌트 스캔이 동작합니다.

그러면 register에 @Configuration을 붙이지 않고 직접 등록한다면 @ComponentScan만 있어도 되는데

붙이는 이유가 궁금합니다.

 

 

spring spring-boot spring-jdbc

답변 1

9

토비

날카로운 질문을 해주셨네요.

자바의 애노테이션은 한국어로 하면 "주석"입니다. 책의 본문이나 문서의 텍스트에 부가적인 설명 등을 달아놓는 것을 말합니다. 자바의 애노테이션도 기본적으로 주석이라서 그 자체로 어떤 기능이 동작하지 않습니다. 동작하는 코드에 노트처럼 추가한 것이라고 볼 수 있습니다. @Override 같은 것이 그런 용도이지요. @Override를 붙이지 않는다고 오버라이드를 못하는 건 아닙니다. 이건 코드를 읽는 사람을 위해서 상위 타입에서 정의된 메소드를 오버라이드하는 메소드라는 일종의 코멘트를 붙인 겁니다.

그런데 @Configuration, @ComponentScan과 같은 스프링 기술에서 쓰는 애노테이션은 단순 각주 이상으로 런타임에 코드의 동작에 관여합니다. 주로 프레임워크가 하는 일에 참고하는 정보입니다. 그 자체로 명령은 아니지만, 메타데이터로 프레임워크가 사용해서 어떤 기능이 수행되게 만드는 것입니다. 이러게 런타임까지 유지되는 애노테이션은 그런 용도로도 활용됩니다.

@Configuration은 우선 @Component를 메타 애노테이션으로 가지고 있으므로 자신이 스프링의 빈으로 등록될 대상임을 각주로 표시합니다. 그러면서 @ComponentScan 대상이 됩니다.

스프링부트의 관례를 따르면 HelloApplication은 그 자체로 스프링의 빈으로 등록되야 합니다. 그래서 최소한 @Component를 붙여야 하는데, 그 안에 @Bean과 같은 팩토리 메소드를 넣기도 하니까 그중에서 @Configuration을 붙이는 것이 관례입니다. 이건 @SpringBootApplication이라는 부트가 만든 합성 애노테이션을 보면 알 수 있습니다. 그 메타 애노테이션으로 @Configuration이 있거든요. 위 코드가 나온 강의 부분은 아직 부트의 애노테이션을 직접 사용하는 단계가 아니라서 우선 @Configuration을 붙였습니다.

그 자체로 애플레케이션의 로직/기능을 제공하는 것이 아니라, 구성정보를 정의하는 것이 목적인 @Configuration이 붙은 클래스에 @ComponentScan도 같이 들어가는 것이 자연스럽습니다. 그래서 둘은 보통 같이 등장하고, @SpringBootApplication 애노테이션의 메타 애노테이션에도 이 두가지가 다 나옵니다.

그런데 질문하신 내용은 뭐냐면, HelloApplication은 초기화 코드에서 직접 register를 해주니까 기본적으로 빈으로 등록이 되고, 그렇게 등록된 빈에 @ComponentScan이 붙으면 나머지 빈들도 알아서 찾아주는데 왜 또 @Configuration을 붙여냐는 질문이신 거죠.

사실 애플리케이션의 부트스트래핑을 해주는 클래스를 register로 직접 등록하는 것은 아주 특별한 경우입니다. 부트의 xxxApplication으로 끝나는 클래스 정도 뿐이죠. 기능적으로만 보자면 HelloApplication에 @Configuration을 붙이지 않아도 됩니다. 그렇다면 스프링부트가 기본적으로 붙여주는 @SpringBootApplication 애노테이션이 붙은 클래스도 register로 등록이 되는데 거기에는 왜 또 @Configuration이 들어가있을까요?

두가지를 생각해볼 수 있습니다.

첫째는 애노테이션을 기능이 아니라 주석으로 생각한다면 이 클래스는 스프링의 빈이고 그 중에서도 구성정보를 자바 코드로 다루는 것임을 나타내기 위해서입니다. 애플리케이션 구조 전반에 적용되는 @ComponentScan을 일반 컨트롤러 클래스 같은데 붙이지 않죠. 자연스럽게 @Configuration 빈으로 정의된 클래스에 나오게 됩니다. 그래서 스프링부트의 애노테이션도 부트스트래핑으로 직접 등록되는 빈 클래스라고 하더라도 @Configuration을 붙이게 됩니다.

두 번째는 이게 멀티 모듈로 나눠지는 경우 해당 모듈의 루트가 되는 클래스이고 하위 패키지에서 빈 클래스를 찾아서 등록시키기 위해 @ComponentScan가 붙어있더라도 부트의 부트스트래핑 클래스가 아니게 될 수 있습니다. 물론 이때도 @Import나 자동구성에 의해서 등록될 수도 있긴하지만 register로 등록되는 건 아니겠죠. 설명을 적고 보니, 결국 질문하신 내용에 포함이 될 수도 있겠네요.

어쨌든 저는 다른 방식으로 빈으로 등록된다고 하더라도, 자바 애노테이션을 이용한 빈 구성 전략을 선택했다면 명시적으로 빈이 되는 클래스에는 @Componet류의 애노테이션을 붙이는 것을 권장합니다. 다른 분들이 코드를 읽을 때도 도움이 되겠죠.

0

cjh

강사님이 제 머리 속까지 읽으신줄 알았습니다.

제가 작성한 질문외에 궁금했지만 질문에 남지기 않았던 부분까지

상세하게 설명해주실 줄 몰랐습니다.

토비님 강의는 복습할때 마다 새로운걸 얻게 되네요

항상 건강하세요 ! 그리고 감사합니다

앞으로 준비하시는 강의도 결제대기하고 있습니다!

11강에서 cmd에서 spring shell에 $ init 하면 Fail 메세지

0

73

2

TestRestTemplate 을 통해 테스트 실행시 웹 요청 정보가 콘솔에 표시되지 않습니다.

0

83

1

섹션7. 자동구성 정보파일분리 강의 질문(@MyAutoConfiguration 붙힌 이유)

0

200

2

WebApplicationContext를 DispatcherServlet에 this로 넘기는 것

0

278

2

인프라 빈 구성 정보의 분리에서 EnableMyAutoConfiguration 질문드립니다.

0

209

2

질문드립니다.

0

232

2

spring boot 3.3.7로 학습중입니다.

0

369

2

Serverproperties 객체 생성 후 @Impor 어노테이션 사용 이유 용도

0

162

2

spring start io 에서 이제더이상 2.x버전은 지원하지 않는 것 같습니다.

1

294

2

Springboot 3.2 이상에서 파라미터 추론관련

0

913

4

binding error

0

220

3

Arrays.copyOf 메서드의 타입 세이프

1

155

2

MyOnClassCondition에 있는 matches method의 Invoke 횟수

1

231

3

인용구의 출처가 궁금합니다.

0

259

1

프로퍼티 빈의 후처리기 도입 AnnotationUtils의 사용

0

235

2

SimpleCacheConfiguration과 빈 등록

0

168

2

MyAutoConfigImportSelector 에서 생성자로 ClassLoader를 주입받을 수 있는 점

0

241

1

IntelliJ project jenerator spring initailizr

0

150

1

강의 자료 레퍼지토리에 업로드

0

215

1

강의자료

0

385

1

Hikari 라이브러리가 없으면 오류가 나는거 아닌가요

0

311

2

Tomcat 포트 프로퍼티 미설정시 랜덤 포트 설정 문의

0

467

5

@Import 로 Bean을 등록해야하는 기준이 뭔지 궁금합니다.

0

333

2

application.properties파일내 프로퍼티 이름

0

207

1