본문 바로가기
Java 웹 프로그래밍

그래서 @Retention이 뭔데 이 개발자야

by irerin07 2023. 11. 26.
728x90

왜 @Retention이 궁금해졌는가

  • 자바 Annotation을 뒤적거리다가 @Retention을 보게 되었는데 각각 Class, Source, Runtime 세가지 종류로 나뉘어 있는걸 보았다. 그리고 이게 도대체 뭔데.. 싶어서 찾아보기 시작했다.

그래서 우선 Annotation이 뭔가요?

  • 어노테이션은 클래스, 메서드 혹은 필드에 선언할 수 있는 일종의 주석같은 것 이라고 설명할 수 있을 것 같다.

그러면 Annotation의 역할은 뭔가요?

  • Annotation은 JVM이나 컴파일러에 추가적인 정보, metadata를 전달하는 역할을 담당합니다.
  • 컴파일 시점, 런타임 시점, 혹은 빌드시에 참고할 정보를 가지고 있습니다.

그럼 본론으로 돌아와서 @Retention이 뭔가요?

RetentionPolicy

  • RetentionPolicy에는 총 3가지가 있다.
  1. Source
  2. Class
  3. Runtime

RetentionPolicy.SOURCE

  • 소스코드에서만 유지되고 컴파일시에 사라진다.
  • 제일 처음 떠오르는 예제로는 @Getter Annotation이 있다.

@Getter
@Getter가 있었는데요

 

위 엔티티 클래스는 @Getter를 사용해 만든 엔티티 클래스이다. 

우리는 @Getter 메소드를 사용하면 getCity() 같은 메서드가 생성된다는 것을 알고 있다.

하지만 위에서 설명했듯이 @Getter의 RetentionPolicy(유지정책)은 Source이다. 

그렇다는 것은 Source코드를 컴파일한 클래스 파일에는 @Getter 어노테이션이 유지되지 않는다는 뜻이다.

확인해보자.

없었습니다.

진짜로 사라졌다.

그리고 대신 getCity(), getDistrict()와 같은 메서드들이 생성되어있는 것이 보인다.

 

@Getter와 같이 유지정책이 Source인 Annotation들은 Source코드단계에서만 보여지고 그 이후 단계에서는 보이지 않게 된다.

RetentionPolicy.CLASS

- 클래스 단계까지만 유지 된다.

- 롬복의 @NonNull을 예시로 들수 있다.

lombok에서 제공하는 NonNull

위에서 RetentionPolicy.SOURCE를 설명했으니 이젠 이 유지정책도 대충 감이 올것이다.

클래스 단계까지만 유지시키는 유지정책인데 문든 궁금한것이 생겼다.

 

"이걸 그래서 왜 씀? Source쓰면 되는거 아님?"

https://stackoverflow.com/questions/38975073/retention-of-java-type-checker-annotations

https://jeong-pro.tistory.com/234

한참을 구글링 하면서 찾을 굉장히 도움 된 포스트들이다.

 

그 안의 내용을 정리하자면, 

when type-checking a class, the compiler needs to read the annotations on libraries that it uses, and separately-compiled libraries are available to the compiler only as class files.

클래스를 type-check할 때, 컴파일러는 자신이 사용하는 라이브러리의 Annotation을 읽어야 하는데, 별도로 컴파일 된 라이브러리들은 오직 클래스 파일 형태로만 컴파일러에게 제공되기 때문이다.

 

즉, Maven이나 Gradle을 통해 받은 라이브러리와 같은 jar 파일들은 소스코드를 포함하고 있지 않은 대신, 클래스 파일만 포함되어 있기 때문이다.

 

RetentionPolicy.RUNTIME

- 런타임, 즉 메모리에 올라가서도 유지된다.

-  @Service를 예시로 들 수 있다.

 

해당 유지정책이 적용되면 메모리에 올라가서도 어노테이션이 살아남아있다.

이는 스프링을 생각해보면 조금 더 이해가 쉽다.

스프링은 Reflection API를 사용하여 @Service, @Controller등의 어노테이션이 붙은 클래스를 가져오는데, 이 때문에 스프링이 올라오는 시점에 컴포넌트 스캔이 가능해야 하므로 RUNTIME 유지 정책이 필요한것이다.

728x90