본문 바로가기
혼자 공부하는 것들/Spring

@Component는 어떻게 동작하는 걸까?

by applepick 2023. 1. 24.
반응형

실무에서 @Component로 Bean을 편리하게 만들어줘서 사용하고 있지만, 동작 원리부터 어떤 식으로 작용하는지 궁금했습니다.

일단 @Component를 쓰기 위해서는 @ComponentScan과 @Configuration을 알아야 합니다.

@Configuration는 간단하게 이야기하자면 해당 클래스는 설정파일이라고 인식시켜 주는 것입니다. Bean Object 생성 이상으로 전체 애플리케이션을 구성하는 가장 중요한 기능들을 넣을 수 있습니다.

@ComponentScan는 @ComponentScan를 적용한 해당 클래스 아래에 있는 @Component가 붙은 모든 클래스들을 Bean으로 등록할 수 있게 도와줍니다. 필요하다면 의존 Object를 찾아서 생성자를 찾아 파라미터로 넘겨주기도 합니다.

@Component를 직접 해당 클래스에 붙여서 Bean으로 등록해도 되지만, 메타에노테이션으로 만들어서 붙여서 사용할 수 있습니다. 메타에노테이션은 해당 에노테이션 위에 붙어있는 에노테이션을 뜻합니다.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Component
public @interface WebComponent {
    // bean 오브젝트가 어떤 의미인지 커스텀, 명시해줄 때 사용 Ex) 웹 계층인지, controller, service 등등...
    // 메타어노테이션
}

@WebComponent를 하나 정의해봤습니다. 해당 어노테이션의 생명주기를 설정하는 @Retention은 RUNTIME 시점으로 해주고, @Target은 지정된 타깃 위치만 해당할 수 있도록 설정해 줍니다. ElementType.TYPE 설정을 통해 Class나 interface 같은 타입에만 적용해 줄 수 있도록 해줍니다. 마지막으로 @Component로 컴포넌트로 인식할 수 있도록 작성해 주면 메타어노테이션을 생성할 수 있습니다. 해당 어노테이션을 사용하는 곳에서는

@WebComponent
public class WebController {

일반적인 어노테이션처럼 사용해주면 됩니다. 이러한 원리로 우리가 흔히 사용하고 있는 @Controller, @RestController, @Service도 이러한 원리로 동작하고 있습니다.

각 각의 구현체를 확인해보겠습니다.

@Controller를 확인해 보면 Bean의 생명주기 설정, 타입설정, 문서설정을 해주고 @Component를 통해 Bean으로 등록할 수 있게 됩니다.

@Service도 마찬가지로 동일하게 설정해 주는 것을 볼 수 있습니다.

여기서 저는 사실 @Service든 @Controller든 Bean을 등록해 주는 똑같은 코드를 왜 분리했을까? 생각했습니다. 고민한 결과
@Component로 Bean 생성을 해줄 수 있지만, 각 각의 Layer를 구분하여 더 좋은 아키텍처를 구성할 수 있다고 생각했습니다. 하지만 사용하지 않아도 @Component를 구성하는 올바른 구조, 설계만 있다면 사용하지 않아도 충분히 좋은 아키텍처를 만들 수 있다고 생각합니다.

@RestController를 살펴보면, @Controller 메타어노테이션을 가지고 있습니다. 메타어노테이션은 메타어노테이션 안에 메타어노테이션... 쭉 계층형으로 가져갈 수 있습니다. 결국 그 안에는 @Component가 붙어있을 것입니다.

그러면 굳이 @RestController를 왜 만들었을까?

위에 사진을 살펴보면, @ResponseBody 어노테이션 하나가 더 붙은 것을 볼 수 있습니다. 그 이유는 API 역할의 Controller 메서드를 만들 경우 ResponseBody가 Controller에 붙어있는 것으로 DispatcherServlet이 인식하게 됩니다. Controller를 조금 더 확장한 RestController를 사용할 수 있게 되는 것입니다. 장점으로는 @RestController를 사용하게 된다면 Class 레벨의 @RequestMapping을 작성을 안 해줘도 DispatcherServlet이 해당 클래스 안에 Mapping 정보가 있다고 가정하여 찾아줍니다. Method 레벨에 Mapping을 작성해줘도 됩니다.

반응형

댓글