hotamul의 개발 이야기

Meta Annotation, Composed Annotation 본문

Dev./Spring-Boot

Meta Annotation, Composed Annotation

hotamul 2023. 9. 5. 23:29

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 {
[...]
Comments