결론부터 말하자면 애너테이션에 기능은 전달될 수 없다. 기능을 전달하는 것처럼 보일 뿐.
@에 어떻게 기능이 전달되는 걸까?
최근에 스프링에 입문을 하며 코드를 작성을 하는데, 애너테이션을 많이 사용하며 구현을 해야했었다. Javascript, C, Python 만 사용하다가 넘어온 사람으로서 타 언어에 없는 '@ 문법'은 정말 이질감이 들었다.
이보다 더 당황스러웠던 건 상속도, 구현도, 외부함수를 끌어다 사용하는것도 아닌데 기능이 어떻게 들어갈 수 있는지는 정말 의문이다.
(학부생활 때 배웠던 @Override는 단순히 주석정도의 기능밖에 하지 않는다고 배웠는데...)
그래서 오늘 그 @에 대해서 이해해보려고 한다.
간편해서 많이 사용하는 @Getter, @Setter으로 알아보려고 한다.
@Getter
해당 클래스의 객체를 생성할 때, 자동으로 필드를 get할 수 있는 메서드를 생성해준다.
아래는 @Getter 의 내부 구조이다.
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface Getter {
AccessLevel value() default AccessLevel.PUBLIC;
AnyAnnotation[] onMethod() default {};
boolean lazy() default false;
}
유의해서 볼 것들은 다음 것들이 되겠다. (내가 모르는 것들)
우선 위에 것들부터 차근차근 알아가보자.
커스텀 애너테이션 생성
애너테이션을 만들 때 사용하는 문법이다.
public @interface MyAnnotation {
String value() default "default";
}
사용법은 클래스나 특정 대상 위에 애너테이션을 추가하면 된다.
@MyAnnotation(value = "Hello World")
public class ExampleClass {}
애너테이션을 붙일 대상을 지정한다.
@Target(ElementType.TYPE)
public @interface MyAnnotation {}
ElementType에는 여러 종류가 있다.
애너테이션이 유지되는 시간을 결정한다.
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {}
Retention
애너테이션에 저장할 메타데이터
public @interface MyAnno {
String value();
}
MyAnno라는 애너테이션에 저장할 메타데이터를 정의한다. String 타입의 value라는 명칭의 데이터를 저장하겠다는 의미이다.
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface Getter {
AccessLevel value() default AccessLevel.PUBLIC;
AnyAnnotation[] onMethod() default {};
boolean lazy() default false;
}
@Getter => 클래스, 필드를 대상으로
@Retention => 컴파일 시기에 유지되는
@interface => 커스텀 애너테이션
필드를 보면
AccessLevel (접근제어자) : 생성되는 대상의 접근 제어자를 PUBLIC으로 설정
AnyAnnotation[] onMethod() default {};
생성되는 getter 메서드에 추가적인 애너테이션을 붙일 수 있는 기능.boolean lazy() : 필드 초기화를 지연(lazy) 여부
해당 get 기능을 생성해주는 코드가 어디에도 없다.
어떻게 어디에서 getter 함수가 자동으로 달리는 건지 궁금했다.
애너테이션은 단순한 표지판일 뿐
애너테이션은 기능을 구현해주지 않는다. 단순히 '@Getter에 메서드를 만들어 줘' 라는 표시일 뿐이다. 그래서 field도 단순 정보를 넣을 뿐인 것 같다.
@MyAnno(maker = "애너테이션을 만든 사람은 Jeong이야", time="2025.02.21")
해당 get 기능은 Lombok에서 해당 애너테이션을 보고 구현해주는 것이다. 이때 사용되는 것이 애너테이션 프로세서이다.
애너테이션을 읽고 기능을 구현해주는 역할을 수행
다음과 같은 방식으로 get 메서드가 구현된다.
1. 컴파일
2. Lombok실행
3. Lombok의 애너테이션 프로세서가 @Getter을 확인
4. 해당 클래스의 필드에 대한 getter 메서드 생성
뭔가 예상은 어느정도 했지만, 허무하다.
프로그래밍 언어별로 크게 차이가 없는 듯 해서 아쉽다가도, 또 새로운 문법을 공부하지 않아도 된다는 안도감이 동시에 든다.