1. Spring @Annotation
1.1. @RestController
@RestController 동작에 앞서, 먼저 알아보아야할것이 @Controller와의 차이점입니다.
@Controller 내부
1 | /* |
@Controller Annotation의 내부를 살펴보면 다음과 같은 구조를 볼 수 있습니다. 자세히 살펴보시면 @Component
어노테이션을 살펴보실 수 있습니다. 과연 이것의 어노테이션의 역할은 무엇일까요?
즉, 기존의 Spring에서는 @Bean
을 붙여 빈을 등록하던 것처럼 빈 클래스에 @Component
애노테이션을 붙여 빈을 등록할 수 있습니다. 따라서 @Controller
어노테이션 내부에는 해당 컨트롤러를 @Bean
으로 등록하는 역할도 하고 있다는 뜻입니다.
@Component를 붙여 빈을 등록하면 클래스 이름의 첫 문자를 소문자로 바꾼 것이 빈의 이름(id)이 됩니다. 그리고 빈 객체가 생성되는 시점은 ApplicationContext 객체가 생성되는 시점이며 기본적으로 singleton scope 입니다.
해당 경로로 요청을 진행한다고 할때 localhost:8080/mvc
의 요청경로에 맞는 컨트롤러를 @Bean 컴포넌트 스캔을 통하여 해당 경로를 가지고 있는 컨트롤러를 찾아주게 됩니다. 만약 @ResponseBody
가 붙여져 있지 않다면 해당 모델에 값을 넘겨줄 수도 있고, String을 반환하게 되면 데이터를 넘겨주는것이 아니라 해당 View의 Path값에 맞게 모델값과 함께 반환시켜주게 됩니다. 요약하면 API와 view를 동시에 사용하는 경우에 사용한다고 생각하시면 됩니다.
이제 @Controller 다음으로 @RestController 의미에 대해 알아보겠습니다. 간단히 @RestController는 @Controller가 포함되어있고 @ReponseBody형식을 함께 사용할때 사용합니다.
@RestController 내부
1 | /* |
내부 스펙을 확인해보면 @ResponseBody Annotation, @Controller Annotation이 함께 선언되어 있습니다.
@ResponseBody를 붙여주면 무슨일이 발생할까요?
@ResponseBody
의 역할은 HTTP BODY
문자내용을 반환하는 api
라고 할 수 있습니다. 즉, 기존에 @ResponseBody
가 없는 경우에 viewResolver
대신에 httpMessageConverter
가 동작하여 문자일 경우에는 StringHttpMessageConverter
객체일 경우에는 MappingJackson2HttpMessageConverter
로 이루어져있습니다. 클라이언트의 HTTP Accept헤더와 서버 컨트롤러의 반환 타입 정보 둘을 조합해서 HttpMessageConverter가 동작되게 됩니다. 기본으로 동작되는 데이터반환형식은 Default JSON형식으로 동작되게 됩니다.
1.2. @RequestMapping
@RequestMapping Annotation은 Spring에서 제공하는 HandlerMapping Class가 가지고 있습니다.
두 가지의 경우로 나눌 수 있는데, 이것은 스프링 HTTP 내부 Note:를 참고하면 아래와 같은 사항을 확인할 수 있습니다.
1 | /** |
위의 내용을 요약 하면
@RequestMapping Annotation은 클래스 및 메서드 수준에서 모두 사용할 수 있습니다. 대부분의 경우 방법 수준에서 응용 프로그램은 HTTP 메서드별 변형된 @GetMapping, @PostMapping, @PutMapping, @DeleteMapping 또는 @PatchMapping 중 하나를 사용하는 것을 권장합니다.
참고: 컨트롤러 인터페이스(예: AOP 프록시)를 사용할 때 구현 클래스가 아닌 컨트롤러 인터페이스에 @RequestMapping 및 @SessionAttributes와 같은 모든 매핑 Annotation을 일관되게 배치해야 합니다.
즉, 클래스 및 메서드 수준을 모두 사용할 수 있으며, 최근에는 HTTP 메서드별 변형된 @GetMapping, @PostMapping, @PutMapping, @DeleteMapping 또는 @PatchMapping 중 하나를 사용하는 것을 권장한다고 합니다.
- Class Level Mapping
Class Level Mapping은 모든 메서드에 적용하는 경우 사용합니다.
1 |
|
HTTP Request 요청경로가 “/” 일 경우 해당 클래스에서 처리를 진행합니다.
- Handler Level Mapping
1 |
|
요청 URL에 대하여 해당 메서드를 처리해야하는 경우 사용합니다. 특정 메서드에서 HTTP요청을 처리한다고 생각하면 됩니다.
RequestMapping 옵션
- value는 해당 URL 경로를 지정합니다.
- HTTP Request Method를 지정하여 HTTP 형식에 맞추어 수행됩니다.
1.3. @GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping
@RequestMapping에서 조금더 세분화된 Method path를 지정하여 명시적이고 효율적인 사용을 위하여 Annotation이 Spring 4.3.xx 버전 이후로 추가되었습니다.
현재 @RequestMapping보다는 4.3버전이후로 나온 Annotation을 권장하고 있습니다.
종류
@GetMapping, @PostMapping, DeleteMapping, @PutMapping, @PatchMapping
Annotation 사용법
1 |
|
기존에 RequestMapping을 통하여 가독성이 떨어지는 코드를 작성하였는데 스프링4.3버전이후로 부터 세부적인 HTTP Method를 지정할 수 있게 되어 명시적이고 효율성이 올라갔다고 생각합니다.
1.4. @Compoment
스프링빈을 등록하는 방법은 2가지가 존재합니다.
- 컴포넌트 스캔과 자동의존관계 설정
- 코드로 직접 스프링빈을 등록하는 방식
따라서, 컴포넌트스캔원리를 이용 할때 @Component Annotation을 사용하게 됩니다. @Component의 의미는 해당 Annotation이 있으면 Spring bean으로 자동으로 등록이 됩니다.
즉, component-scan을 통하여 특정 패키지 안의 클래스들을 스캔하고 @Component Annotation이 있는 클래스에 대하여 bean인스턴스를 생성시킵니다. bean인스턴스로 생성되면 스프링 컨테이너에서 관리를 진행하게 되고 DI를 주입받을 수 있습니다.
DI주입은 필드주입, setter주입, 생성자 주입 총 3가지 방법
이 있습니다. 의존관계가 실행중 동적으로 변하는 경우는 거의 없기때문에 생성자 주입을 통한 DI주입을 권장합니다.
DI주입시 주의사항은
@Autowired를 통한 DI는 Controller, Service등과 같이 스프링이 관리하는 객체에서만 동작하게 됩니다. 스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작되지 않습니다. 생성자에 @Autowired를 사용하면 객체 생성 시점에 스프링 컨테이너에서 해당 스프링 빈을 찾아서 주입해줍니다. 생성자가 1개만 있으면 @Autowired는 생략이 가능합니다.
1.5. @Controller, @Service, @Repository
1.5.1. @Controller
@Controller가 스프링빈으로 자동등록되는 이유는 @Controller내부에 보면 @Component Annotation에 의해서 컴포넌트스캔이 진행되기 때문입니다.
@Controller 내부
1 |
|
1.5.2. @Service
@Service Annotation또한 스프링빈으로 자동등록되는 이유는 @Service내부에 보면 @Component Annotation에 의해서 컴포넌트스캔이 진행되기 떄문입니다.
요약하면 @Component 어노테이션에 의해서 @Controller, @Service, @Repository와 같은 어노테이션을 구체화하여 스프링 컨테이너에 @Service bean으로 등록을 하게 됩니다.
@Service 내부
1 | /** |
1.5.3. @Repository
@Repository Annotation또한 스프링빈으로 자동등록되는 이유는 @Repository내부에 보면 @Component Annotation에 의해서 컴포넌트스캔이 진행되기 떄문입니다. 즉, @Component 어노테이션에 의해서 @Controller, @Service, @Repository와 같은 어노테이션을 구체화하여 스프링 컨테이너에 @Service bean으로 등록을 하게 됩니다.
@Repository 내부
1 | /** |
1.6. @ComponentScan
@ComponentScan이란 컴포넌트 검색기능을 가진 어노테이션입니다.
스프링은 기본적으로 객체를 자동으로 생성하여 관리하기 때문에 @Component 어노테이션이 있는 클래스들을 스프링 컨테이너가 생성해줍니다.
따라서, @ComponentScan는 특별히 basePackage를 지정하지 않아도 main class가 위치한 패키지를 Root package로 하여 그 이하의 모든 컴포넌트 클래스들을 검색하여 빈으로 등록할 수 있습니다.
1.7. @Configuration
- 클래스에 이 어노테이션이 붙어 있으면 스프링은 해당 클래스를 Java config로 간주합니다.
- 1개 이상의 @Bean을 제공하는 클래스의 경우 반드시 @Configuration을 명시해 주어야 합니다.
1.8. @Bean
- 개발자가 직접 제어가 불가능한 외부 라이브러리 또는 설정을 위한 클래스를 Bean으로 등록할 때 @Bean 어노테이션을 활용합니다.
1.9. @SpringBootApplication
@SpringBootApplication 어노테이션은 스프링 부트의 가장 기본적인 설정을 선언이 되어있습니다. 내부로직을 살펴보도록 하겠습니다.
@SpringBootApplication
1 | /** |
여기 스펙부분을 자세히보시면 중요하게 생각해야할 부분이 두가지 있습니다.
- @ComponentScan
- @EnableAutoConfiguration
이 두가지가 왜 중요할까요?
@ComponentScan
@ComponentScan은
@component 어노테이션 및 @Service, @Repository, @Controller 등의 어노테이션을 스캔하여 Bean으로 등록해주는 어노테이션입니다.
즉, 어플리케이션 실행시에 @Service, @Repository, @Repositroy, @Controller에 컴포넌트스캔을 통하여 스프링 컨테이너에 Bean으로 등록합니다.
@EnableAutoConfiguration
@EnableAutoConfiguration은
사전에 정의한 라이브러리들을 Bean으로 등록해 주는 어노테이션입니다. 사전에 정의한 라이브러리들 모두가 등록되는 것은 아니고 특정조건이 만족될 경우에 Bean으로 등록됩니다.
저장위치
사전 정의 파일 위치: Dependencies > spring-boot-autoconfigure > META-INF > spring.factories
References
https://projectlombok.org/features/
https://docs.spring.io/spring-framework/docs/3.0.0.M3/reference/html/ch04s11.html
https://velog.io/@gillog/Spring-Annotation-정리
https://gmlwjd9405.github.io/2018/12/02/spring-annotation-types.html
https://bamdule.tistory.com/31
https://imucoding.tistory.com/217
https://toma0912.tistory.com/86
https://tomining.tistory.com/180