Meta Annotation, Composed Annotation
Spring Boot는 Annotation을 적극적으로 활용하고 있다. 애플리케이션 로직을 담고 있는 클래스에 자주 사용되는 @RestController
, @Service
, @Reposeitory
와 같은 익숙한 Application logic bean annotation들은 사실 모두 Composed Annotation (합성 애노테이션)으로 Meta Annotation을 조합해서 사용한 Annotation이다. 그럼 Meta Annotation이 뭘까?
Meta Annotation
Meta Annotation이란 다른 Annotation에서 사용되는 Annotation을 말한다. (@Service
Annotation을 살펴 보면 @Component
Annotation이 사용된 것을 확인할 수 있는데 이 때 @Component
Annotation이 Meta Annotation 이다.)
Meta Annotaition을 사용하면 뭐가 좋을까? 사실 Meta Annotation인 @Component
를 사용하던 @Service
를 사용하던 모두 @ComponentScan
에 의해 Bean
으로 등록되는 것은 동일하다.
그런데 다른 이름을 부여하므로서 @Service
Annotation이 붙은 클래스는 Web MVC의 비즈니스 로직을 담당하는 서비스 클래스에 해당되는 구나, @Controller
Annotation이 붙은 클래스는 @RequestMapping
Annotation이 붙어 있는 method를 가지고 있겠구나 라는 것을 개발자들이 이해할 수 있다.
그리고 반복적인 Annotation 조합이 사용된다면 중복 되는 Annotation 코드를 줄일 수도 있다. (@ResponseBody
Annotation과 @Controller
Annotation이 반복적으로 많이 사용되어지기 때문에 @RestController
라는 Annotation이 만들어졌다고 할 수 있다.)
Composed Annotation 만드는 방법
Composed Annotation들을 살펴보면 @Retention
, @Target
과 같은 Annotation이 사용되어 지는 것을 볼 수 있다.
@Retention
@Retention
은 해당 Annotation이 붙은 클래스, 메소드, 인터페이스, ...가 실제로 적용되고 유지되는 범위를 의미한다. 기본적으로 Annotation의 default retetion은 RetentionPolicy.CLASS
이다. 즉 해당 Annotation 정보가 컴파일된 class 파일까지는 살아 있지만 런타임에 메모리로 로딩될 때는 사라진다는 뜻이다.
(RetentionPolicy
의 종류는 SOURCE
, CLASS
, RUNTIME
이 있다.)
@Target
@Target
은 Annotation이 어디에 선언될 수 있을지 결정하는 Annotation 이다. 예를 들어 @Target(ElementType.METHOD)
가 적용된 Annotation은 method에만 선언될 수 있다.
(ElementType
종류는 TYPE
, FIELD
, METHOD
, PARAMETER
, CONSTRUCTOR
, LOCAL_VARIABLE
, ANNOTATION_TYPE
, PACKAGE
, TYPE_PARAMETER
, TYPE_USE
, MODULE
이 있다. 자주 사용되는 ElementType.TYPE
은 class, interface, enum에 선언될 수 있다는 뜻이다.)
정리하면 아래의 @RestController
는 Meta Annotation인 @Controller
(@Component
)와 @ResponseBody
으로 조합된 Composed Annotation이다.
[...]
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
[...]
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
[...]