본문 바로가기
Spring/인프런 토비의 Spring Boot

섹션 4-9 [독립 실행형 스프링 애플리케이션] @Conponent 스캔

by include_hoany 2024. 6. 1.


@Component스캔

지난 시간까지 사용했던 스프링 컨테이너에 빈을 등록하는 방법은 클래스 정보를 레지스터 빈 메소드에 넘겨주거나 아니면 팩토리 메소드를 만들어서 직접 빈 인스턴스를 생성하는 방법을 사용했습니다. 그러나 그것보다 좀 더 간결하게 빈을 등록할 수 있는 방법이 있습니다. 그 방법은 @Component, @ComponentScan 애노테이션을 사용하여 Spring Container에게 Bean구성정보를 전달하는 방식입니다.

애노테이션 방식으로 Bean을 등록하면 좋은점은 새로운 Bean을 만들어서 추가할때 매번 구성정보를 다시 등록해줄 필요가 없고 간단하게 Component애노테이션을 사용하면 됩니다. 다만 이러한 편리성 이면에는 Bean으로 등록되는 클래스가 굉장히 많아지게 되면 내가 이 애플리케이션을 실행했을 때 정확하게 어던 것들이 등록되는가 이거를 찾아보려면 굉장히 번거로울 수 있습니다. 클래스들을 확인해서 Component 애노테이션이 부은 클래스들이 어떤게 있는지 체크해야하기 때문입니다.그래도 애노테이션 방식으로 Bean을 등록하는 방법에 이점이 더 크기때문에 표준처럼 사용이 되어집니다.

컴포넌트라는 애노테이션은 재미있는 특징을 가지고 있는데 그게 뭐냐하면 애노테이션을 직접 빈 클래스로 사용할 클래스에다가 붙여도 되지만 이 애노테이션을 메타 애노테이션으로 가지고 있는 애노테이션을 붙여도 컴포넌트라는 애노테이션이 붙은 것과 동일한 효과를 내줍니다.

 

메타 애노테이션이란?

애노테이션 위에 붙은 애노테이션이라는 뜻 입니다. 애노테이션도 결국 Java코드로 만들어진 부분이다보니 애노테이션 코드 위에 애노테이션으 또 붙일 수 있습니다.

 

MyComponent.annotation

package com.tobyspring.tobyspringboot;  
  
import java.lang.annotation.ElementType;  
import java.lang.annotation.Retention;  
import java.lang.annotation.RetentionPolicy;  
import java.lang.annotation.Target;  
  
import org.springframework.stereotype.Component;  
  
// Retention 이 어노테이션으 언제까지 유지될것인가 하는 정책을 결정하는 어노테이션  
@Retention(RetentionPolicy.RUNTIME)  
// Target 애노테이션을 적용할 대상을 지정해 줄 수 있습니다. 지정된 Target 위치에만 적용할 수 있도록 합니다.  
@Target(ElementType.TYPE)  
// 메타 애노테이션 @Component  
@Component  
public @interface MyComponent {  }

 

@Component으로 등록하는 코드로 변경

HelloController.class

package com.tobyspring.tobyspringboot;  
  
import java.util.Objects;  
  
import org.springframework.web.bind.annotation.GetMapping;  
import org.springframework.web.bind.annotation.RequestMapping;  
import org.springframework.web.bind.annotation.RestController;  
  
/*  
    DispatchServlet이 맵핑정보를 만들때 클랙스 레벨에 있는 정보를 먼저 참고한다.
    그리고난 후 메소드 레벨에 붙어있는 정보를 추가합니다.
*/  
/*  
    Component라는 어노테이션으로 스프링컨테이너에 들어가는 컴포넌트야 라고 선언을 한다.
*/  

// @RestController애노테이션은 @Component애노테이션을 메타 애니토에션으로 포함하고 있기때문에
// @Component애노테이션 생략을해도 Bean으로 등록이 가능합니다.  
@RestController  
@RequestMapping("/hello")  
public class HelloController {  
  
    private final HelloService helloService;  
  
    public HelloController(HelloService helloService) {  
       this.helloService = helloService;  
    }  
  
    // GET 메소드를 사용하고 /hello 경로로 접근하는 요청을 매핑하겠다.  
    @GetMapping  
    /*  
         일반적으로 String으로 리턴을 했다면 String으로 전달된 값의 View가 존재하는지 확인합니다.     다만 현재 String으로 전달된 값의 View를 찾을 수 없으면 404 Not Found 오류가 발생하게 됩니다.  
         String값을 그대로 Web 응답에 Body에 넣어서 전달하게 하는 텍스트 플레인으로
         전달하게 하는 방식을 사용하려면 ResponseBody를 사용하면 됩니다.  
         @ResponseBody애노테이션은 @RestController에 메타 애노테이션으로 포함하고 있기 때문에
         생략이 가능하다
 	*/  
    // @ResponseBody
    // RequestMapping을 사용해도 되지만 간결하게 사용하기위해 @GetMapping로 합쳐진 애노테이션이 만들어졌다. 
    // @RequestMapping(method = RequestMethod.GET, value = "/hello")
    public String hello(String name) {  
       return helloService.sayHello(Objects.requireNonNull(name));  
    }  
  
}

 

package com.tobyspring.tobyspringboot;  
  
import org.springframework.stereotype.Service;  
  
// @Service어노테이션은 메타 애노테이션으로 ComponentScan을 포함하고 있으므로 생략이 가능합니다.  
@Service  
public class SimpleHelloService implements HelloService {  
  
    @Override  
    public String sayHello(String name) {  
       return "Hello " + name;  
    }  
  
}