본문 바로가기

Java

[JAVA]어노테이션(Annotation)

어노테이션은 메타데이터(metadata)라고 할 수 있다. 메타데이터는 애플리케이션이 처리해야 할 데이터가 아닌, 컴파일 과정과 실행 과정에서 코드를 어떻게 컴파일하고 처리할 것인지 알려주는 데이터이다. 예를 들어 바나나를 판매하는데 특정 바나나에는 @할인가능이라는 명찰(어노테이션)을 붙이고 후에 @할인가능이라고 적혀있는 바나나를 따로 다른 통에 담아두라"는 업무를 수행한다고 하자. 이 때 @할인 가능이라는 어노테이션을 사용해 바나나 분류 업무를 수행했다고 할 수 있다. 어노테이션은 다음과 같이 작성한다.

@AnnotationName

어노테이션의 용도

  • 컴파일러에게 코드 문법 에러를 체크하도록 정보를 제공한다.
    • 대표적인 예로 @Override 어노테이션이 있다.
      • 이 어노테이션은 메소드 선언 시 사용한다.
      • 메소드가 오버라이드 된 것임을 컴파일러에게 알려준다.
      • 이를 통해 컴파일러는 오버라이드 검사를 한다.
      • 만약 정확히 오버라이드 되지 않았다면 컴파일러가 에러를 발생시킨다.
  • 소프트웨어 개발 툴이 빌드나 배치 시 코드를 자동 생성할 수 있도록 정보를 제공한다.
  • 실행 시 특정 기능을 실행하도록 정보를 제공한다.

어노테이션 타입 정의와 적용

어노테이션 타입 정의는 다음과 같이 한다.

public @interface AnnotationName { }

이렇게 정의를 하고 사용할 때는 @AnnotationName과 같이 사용하면 된다.

어노테이션은 요소(element)를 가질 수 있다. 문자열 하나를 요소로 받고 디폴트 값이 null이라는 문자열인 어노테이션은 다음과 같이 정의한다.

public @interface AnnotationName {
  String elementName() default "null";
  //타입 요소이름() [defult "디폴트 값"]
}

name이라는 요소에 Annotation이라는 문자열 값을 가지고 있는 어노테이션은 다음과 같이 코드에서 사용한다.

@Annotation(name = "Annotation")

요소는 여러 개가 될 수 있으며 요소가 하나일 경우 @Annotation("NO")와 같이 줄여 쓸 수 있다.

어노테이션 적용 대상과 위치(@Target)

어노테이션 적용 가능 대상은 java.lang.annotation.ElementType 열거 상수에 정의되어 있다. 이 열거 상수를 살펴보면 클래스, 인터페이스, 메소드, 메소드 파라미터, 필드, 지역변수, 패키지 등이 있다.

어노테이션의 적용 대상을 설정할 때에는 @Target 어노테이션을 사용한다. 만약 클래스와 필드에 적용할 수 있는 어노테이션을 정의할 경우 ElementType.적용대상과 같이 표현해 @Target안에 넣어주면 되는데 다음과 같이 표현하면 된다.

@Target({ElementType.TYPE, ElementType.FILD})
public @interface Annotation{ }

위의 코드에서 TYPE은 클래스, 인터페이스, 열거 타입에 어노테이션을 붙일 수 있다는 의미이고 FILD는 말 그대로 필드에 어노테이션을 붙일 수 있다는 의미이다. 따라서 위 코드의 @Annotation 어노테이션은 메소드나 생성자 등에 사용할 수 없다.

어노테이션 유지 정책(@Retention)

어노테이션 정의 시 사용 용도에 따라 어노 범위까지 유지할 것인지 지정해야 한다. 예를 들어 소스상에서만 유지할 것인지, 컴파일된 클래스까지 유지할 것인지, 런타임 시에도 유지할 것인지를 들 수 있다. 이 정책은 java.lang.annotation.RetentaionPolicy열거 상수로 정의되어 있다.

  • SOURCE
    • 소스상에서만 어노테이션 정보를 유지한다.
    • 소스 코드 분석할 때만 의미가 있다.
    • 바이트 코드 파일에는 정보가 남지 않는다.
  • CLASS
    • 바이트 코드 파일까지 어노테이션 정보를 유지한다.
    • 다만 리플렉션(쉽게 말해 런타임 시, 클래스의 메타 정보인 필드, 생성자 등의 정보를 얻는 것)을 이용해서 어노테이션 정보를 얻을 수 없다.
    • 리플렉션은 다음에서 더 자세히 다룬다.
  • RUNTIME
    • 바이트 코드 파일까지 어노테이션 정보를 유지한다.
    • 리플렉션을 이용해서 런타임 시 어노테이션 정보를 얻을 수 있다.

이런 유지 정책을 적용하려면 @Retention어노테이션을 사용한다. 적용 방법은 @Retention 어노테이션에 RetentionPolicy.열거상수를 넣어주면 된다. 다음 예제를 참고하자.

@Target({ElementType.TYPE, ElementType.FILD})
@Retention(RetentionPolicy.CLASS)//CLASS 열거 상수를 사용했다.
public @interface Annotation{ }