JAVA - 12 : 어노테이션

Seok-Hyun Lee·2021년 7월 18일
0

JAVA

목록 보기
12/21

12 어노테이션

12.1 어노테이션이란

어노테이션( @ )은 자바로 프로그래밍을 하다 보면 생각보다 자주 접하게 된다. 이전 포스트에서 메서드 오버라이딩을 다룰 때도 본적이 있다.

@Override

이렇게 보면 어노테이션은 일종의 설명이나 주석 같은 느낌인데 일반적인 주석과는 달리 "메타데이터"라고 불린다. 메타데이터란 애플리케이션이 처리해야 할 데이터가 아니라, 컴파일 과정과 실행 과정에서 코드를 어떻게 컴파일하고 처리할 지를 알려주는 정보이다. 그래서 어노테이션은 주로 아래와 같은 용도로 사용된다.

  • 컴파일러에게 코드 문법 에러를 체크하도룍 정보 제공
  • 소프트웨어 개발 툴이 빌드나 배치 시 코드를 자동으로 생성할 수 있도록 정보 제공
  • 런타임 시 특정 기능을 실행하도록 정보 제공
  • 런타임에 리플렉션을 이용(어노테이션은 정적인 값만 가능)

그래서 @Override 어노테이션은 컴파일러가 해당 메소드가 오버라이드 되었다는 정보를 제공받고 정확히 오버라이드가 되지 않았다면 에러를 발생시킨다. 그리고 어노테이션은 도입은 아래와 같은 장점이 있다.

  • 어노테이션 재사용 가능, 생산성 증가
  • 높은 가독성 (별도 문서 필요 X)

12.1.1 커스텀 어노테이션 정의하기

비즈니스 로직을 작성하면서 우리가 자연스럽게 접할 수 있는 기본적인 어노테이션들이 있다. 대표적으로는 @Override, @Depricated, @Suppresswarnings 이 있고 이들은 빌트인 어노테이션이라고 부른다.

  • @Override : 부모의 메소드를 재정의한 것임을 컴파일러에 정보 제공, 부모에 이 메서드가 없으면 에러 발생
  • @Depricated : 소프트웨어 상위 버전에서 지원 제외로 인한 에러 발생 가능 정보 제공
  • @Suppresswarnings : 개발자의 의도에 의해 컴파일러에게 에러 발생을 무시하라는 정보 제공

하지만 어노테이션은 주석과 같이 메타데이터를 제공하는 방법이기 때문에 사용자가 직접 정의해서 사용할 수도 있다. 커스텀 어노테이션을 정의하는 방법은 인터페이스를 정의하는 방법과 유사하다. 아래는 어노테이션을 선언하는 방법이다.

public @interface AnnotationName {

}

위와 같이 @interface 키워드를 사용해 정의한 어노테이션은 아래와 같이 사용된다

@AnnotationName

그리고 어노테이션은 엘리먼트(Element)를 멤버로 가질 수 있다. 엘리먼트는 타입과 이름으로 구성되며 default 값을 가질 수도 있다.

public @interface AnnotationName {
    // Element 선언
    타입 이름() default 값;
}

엘리먼트로 선언할 수 있는 타입은 아래와 같다.

Primitive, String, Enum, Class, Array

하지만 주의할 점은, 엘리먼트는 타입과 무관하게 항상 추상 메서드의 형태를 가져야 한다. 그리고 어노테이션은 언제까지나 주석과도 같은 역할이기 때문에 런타임에도 정적인 값만 가능하다. 아래는 그 예시이다.

public @interface AnnotationName {
    String work();
    int wage() default 5;
}

그리고 이렇게 정의된 어노테이션은 아래와 같이 쓰일 수 있다.

@AnnotationName("Cleaning")
// 또는
@AnnotationName(value="Cleaning",wage=10)

12.2 어노테이션 적용 대상

지금까지 어노테이션의 의미와 용도 그리고 커스텀 어노테이션을 만드는 것을 알아보았는데 이제는 어디에 어떻게 적용되는 지를 알아볼 차례이다. 어노테이션을 적용할 수 있는 대상은 java.lang.annotation.ElementType 에 enum으로 정의되어 있고 아래의 정리된 표를 통해 확인해보자.

여기서 알아볼 것은 메타 어노테이션이다.메타 어노테이션은 다른 어노테이션에게 정보를 제공하기 위해 사용되는 어노테이션을 의미하고 여기에는 @Retention, @Target, @Documented, @Inherited 가 있다.

12.2.1 @Retention

어노테이션이 유지되는 기간(Life Time)을 설정하는 어노테이션

public enum RetentionPolicy {
    SOURCE,
    CLASS,
    RUNTIME
}
  • SOURCE : 소스파일에만 존재하고, 바이트코드 파일에 존재 X
  • CLASS : default 값, 바이트코드 파일까지 정보 유지, 리플렉션 불가
  • RUNTIME : 바이트코드 파일까지 유지, 리플렉션 가능, 런타임에 어노테이션 정보를 얻을 수 있음

사용법은 아래와 같다.

@Retention(RetentionPolicy.RUNTIME)
public @interface Custom {

}

-> 리플렉션과 어노테이션 보러가기

12.2.2 @Target

어노테이션을 적용할 대상을 지정할 때 사용하는 어노테이션이다.

  • @Target의 기본 엘리먼트인 value 는 엘리먼트타입 배열이다.

아래는 @Target 어노테이션으로 적용 대상을 지정하는 예시이다.

@Target({ElementType.TYPE, ElementType,METHOD, ElementType,FIELD})
public @interface Custom {

}

위의 @Custom 어노테이션은 이제 클래스,인터페이스, 열거형, 메소드, 필드에만 적용 가능하기 때문에 생성자나 다른 어노테이션에는 적용할 수 없다.

12.2.3 이외

  • @Documented : @Override,@SuppressWarnings를 뺴고 기본적으로 어노테이션은 문서화 지원 X, 어노테이션의 정보가 javadoc의 문서에 포함되도록 명시
  • @Inherited : 자식 클래스에게도 어노테이션이 상속되도록 하는 어노테이션
  • @Repeatable : 어노테이션을 반복적으로 선언할 수 있게 하는 어노테이션

12.3 어노테이션 프로세서

애노테이션 프로세서는 컴파일러가 컴파일 하는 중에 어노테이션을 읽어서 새로운 소스코드를 생성하거나 기존 소스코드를 변경한다. 그리고 별도의 바이트코드(클래스)파일이나 리소스파일을 생성할 수 있도 있다.

  • 컴파일하며 어노테이션을 읽어 소스 코드 수정/추가
  • 어노테이션 프로세싱을 통해 컴파일 에러나 컴파일 경고 생성
  • 별도의 소스코드(.java)와 바이트코드(.class) 생성도 가능
profile
Arch-ITech

0개의 댓글