ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java]STEP1 - 10) 어노테이션(Annotation)
    개발 공부/Java 2020. 9. 19. 18:16

     

    본 게시글은 도서 "이것이 자바다" 동영상 강의를 듣고 기록하는 TIL(Today I Learned) 입니다.
    모든 저작권은 출판사 한빛미디어와 신용권님께 있음을 알립니다.👍

     

     

    이번 게시물에서는 자바의 메타데이터를 처리하는 어노테이션에 대해서 알아보겠습니다.

     

     

    어노테이션(Annotation)은 메타데이터라고 볼 수 있다.

    메타데이터(metadata)는 애플리케이션이 처리해야 할 데이터가 아니라, 컴파일 과정과 실행 과정에서 코드를 어떻게 컴파일하고 처리할 것인지를 알려주는 정보이다.

     

    어노테이션은 다음과 같이 작성될 수 있다.
    @AnnotationName

     

    어노테이션의 세 가지 용도

    1. 컴파일러에게 코드 문법 에러를 체크하도록 정보를 제공한다.
    2. 소프트웨어 개발 툴이 빌드나 배치시 코드를 자동으로 생성할 수 있도록 정보를 제공한다.
    3. 실행 시(런타임 시) 특정 기능을 실행하도록 정보를 제공한다.
    어노테이션의 대표적인 예로 @Override 어노테이션이 있다.
    @Override 는 메소드 선언 시, 메소드가 오버라이드(재정의) 된 것임을 컴파일러에게 알려주어 컴파일러가 오버라이드 검사를 하도록 해준다.

     

     

    어노테이션 타입 정의하기

    public @interface AnnotationName {
        타입 elementName() [default 값];
    }

    위와 같이 어노테이션을 정의할 수 있으며
    정의한 어노테이션은 아래와 같이 코드에서 사용한다.

    @AnnotationName

    또한 어노테이션은 엘리먼트(element)를 멤버로 가질 수 있는데,
    타입 elementName() [default 값]; 과 같이 선언한다.

    타입은 int, double, String, Class, Array 타입 등 기본, 참조 타입이 사용가능하다.
    default 값은 파라미터로 엘리먼트 타입이 따로 들어오지 않을 때 기본적으로 갖는 값을 의미한다.


    엘리먼트에 default 값이 아니라 원하는 값을 파라미터로 넘겨주고 싶다면

    @AnnotationName(elementName = "값"); 의 형태로 넘겨줄 수 있다.

    어노테이션은 엘리먼트 이름이 "value"인 기본 엘리먼트를 가지고 있는데,
    만약 value를 엘리먼트 이름으로 정했다면
    파라미터를 넘겨줄 때 @AnnotationName("값"); 으로만 넘겨주어도 알아서 value 엘리먼트에 적용된다.

     

    어노테이션의 이름과 엘리먼트를 적용했다면

    어노테이션을 적용할 수 있는 대상과 어노테이션을 얼마나 유지시킬 것인지 유지 정책을 정의해주어야 한다.

    <어노테이션을 적용할 수 있는 대상>
    java.lang.annotation.ElementType에 열거 상수로 다음과 같이 정의되어 있다.

    TYPE                                   클래스, 인터페이스, 열거 타입에 적용가능 하다.
    ANNOTATION_TYPE    어노테이션에 적용가능 하다.
    FIELD                                  필드에 적용 가능하다.
    CONSTRUCTOR             생성자에 적용 가능하다.
    METHOD                           메소드에 적용 가능하다.
    LOCAL_VARIABLE         로컬 변수에 적용 가능하다.
    PACKAGE                          패키지에 적용 가능하다.

    적용될 대상을 지정할 때는 @Target 어노테이션을 사용하여 다음과 같이 지정한다.
    @Target ( { ElementType.TYPE, Element.FIELD, Element.METHOD } )
    public @interface AnnotationName {
        ....
    }

    위 어노테이션은 TYPE, FIELD, METHOD 에만 적용 가능하다는 의미가 된다.
    따라서 클래스, 인터페이스, 열거 타입, 필드, 메소드에만 해당 어노테이션을 적용할 수 있게 된다.

    <어노테이션 유지 정책>
    java.lang.annotation.RetentionPolicy 에 열거 상수로 다음과 같이 정의되어 있다.

    SOURCE     소스코드 상에서만 어노테이션을 유지한다. 바이트 코드 파일에는 정보가 남지 않는다.
    CLASS         바이트 코드 파일까지 어노테이션 정보를 유지한다.
    RUNTIME   리플렉션을 이용하여 런타임 시에도 어노테이션 정보를 얻을 수 있다.

    리플렉션(Reflection) 이란?
    런타임 시에 클래스의 메타 정보를 얻는 기능을 말한다.
    클래스가 가지고 있는 필드가 무엇인지, 어떤 생성자인지, 어떤 메소드를 가지는지, 적용된 어노테이션이 무엇인지를 알아내는 것이 바로 리플렉션!

    유지 정책을 지정할 때는 @Retention 어노테이션을 사용하여 다음과 같이 지정한다.
    @Target ( { ElementType.TYPE, Element.FIELD, Element.METHOD } )
    @Retention(RetentionPolicy.RUNTIME)
    public @interface AnnotationName {
        .....
    }

    위 어노테이션은 RUNTIME 까지 어노테이션의 정보를 얻을 수 있다는 의미가 된다.

     

     

    어노테이션 정보 사용하기

    클래스에 적용된 어노테이션의 정보: java.lang.Class를 사용

     

    필드, 생성자, 메소드에 적용된 어노테이션의 정보: java.lang.reflect 에서 Field, Constructor, Method 타입의 배열을 사용

    리턴 타입 메소드명(매개 변수) 설명
    Field[] getFields() 필드 정보를 Field 배열로 리턴
    Constructor[] getConstructors() 생성자 정보를 Constructor 배열로 리턴
    Method[] getDeclaredMethods() 메소드 정보를 Method 배열로 리턴

     

    이를 통해 어노테이션이 적용된 클래스에 사용되는 필드, 생성자, 메소드의 목록을 배열로 받아 올 수 있다.

    그 다음에는 Class, Field, Constructor, Method 타입이 가지고 있는 메소드를 호출하여

    해당 클래스, 필드, 생성자, 메소드에 적용된 어노테이션이 어떤 것이 있는지를 알아낼 수 있다.

    리턴 타입 메소드명(매개 변수)
    boolean isAnnotationPresent(Class) -> 지정한 어노테이션이 적용되었는지 여부를 반환한다.
    Annotation getAnnotation(Class) -> 지정한 어노테이션을 리턴하고, 없다면 null을 반환한다.
    Annotation[] getAnnotations() -> 적용된 모든 어노테이션을 배열 형태로 반환한다.
    Annotation[] getDeclaredAnnotations() -> 직접 적용된 모든 어노테이션을 배열 형태로 반환한다.

     

    앞서 Class, Field, Constructor, Method 타입에 각각 클래스, 필드, 생성자, 메소드가 담겨있었다.

    따라서 위 표에 나온 메소드를 통해 각각 타입에 어노테이션이 적용되었는지, 어떤 어노테이션이 적용되었는지까지 파악할 수 있다.

     

    결론적으로 이 과정을 거쳐나가다 보면, 어노테이션들이 반환값으로 등장하게 되기 때문에

    해당 어노테이션의 엘리먼트 값을 가지고 프로그램 로직을 짜거나 어떤 도구로 이용할 수 있게 된다.

     

     

     

     

    본 게시글은 여기서 마치겠습니다.

    읽어주셔서 감사하고, 혹시나 틀린 부분이나 보완해야할 부분이 있다면 댓글에 남겨주세요~!

    댓글

Designed by Tistory.