@Configuration 과 @ComponentScan
@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만 있어도 되는데
붙이는 이유가 궁금합니다.
답변 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
강사님이 제 머리 속까지 읽으신줄 알았습니다.
제가 작성한 질문외에 궁금했지만 질문에 남지기 않았던 부분까지
상세하게 설명해주실 줄 몰랐습니다.
토비님 강의는 복습할때 마다 새로운걸 얻게 되네요
항상 건강하세요 ! 그리고 감사합니다
앞으로 준비하시는 강의도 결제대기하고 있습니다!
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





