티스토리 뷰

애노테이션(@, Annotation)이란?

  • 사전적 의미로는 주석을 의미하며, 프로그램에 대한 데이터를 제공하는 메타데이터의 한 종류이다.
  • 소스코드에 대한 문서를 따로 만들기 보다는 소스 코드와 문서를 하나의 파일로 관리하는 것이 더 낫다고 생각했다고 한다. 그래서 개발 시 설명이 필요한 부분의 경우 /**~*/ 안에 해당 로직에 대한 설명을 달고 이러한 주석으로 부터 HTML 문서를 생성하는 프로그램(javadoc.exe)을 만들고 사용했었다. 이 기능을 응용하여 프로그램 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킨 것이 애노테이션이라고 한다.  
  • 예를들어, 자신이 작성한 소스코드 중에서 특정 메서드만 테스트하기를 원한다면, 다음과 같이 '@Test'라는 애너테이션을 메서드 앞에 붙인다. '@Test'는 '이 메서드를 테스트해야 한다'는 것을 테스트 프로그램에게 알리는 역할을 할 뿐, 메서드가 포함된 프로그램 자체에는 아무런 영향을 미치지 않는다. 주석처럼 존재하지 않는 것이나 다름없다. 
@Test // 이 메서드가 테스트 대상임을 테스트 프로그램에게 알린다. 
public void method() {
	...
}

애노테이션을 정의하는 방법

애노테이션 타입을 정의하는 방법은 '@interface'를 사용하여 정의한다. 

// public @interface {annoation name}

public @interface myannotation {
     타입 요소이름(); // 애너테이션 요소를 선언한다.
     ...
}

애노테이션의 요소

  • 애너테이션에 선언된 메서드를 '애너테이션의 요소(element)'라고 한다.
  • 반환 값이 있으며, 매개 변수가 없는 추상 메소드의 형태이다.
  • 애노테이션 적용 시 이 요소들에 대한 값을 모두 지정해주어야 한다.
  • 각 요소는 default 값을 가질 수 있다.
  • 애노테이션의 요소가 오직 하나이며, 이 요소의 이름이 value라면, 애노테이션을 적용할 때 생략이 가능하다.
  • 배열을 선언하여 요소를 지정할 수 있다.
  • 애노테이션도 인터페이스 처럼 상수 정의가 가능하지만 default 메소드는 정의할 수 없다.
  • 다른 애노테이션을 포함할 수 있다. 
@interface TestInfo(){
    int count();
    String testedBy();
    String[] testTools();
    TestType testType(); // enum TestType { FIRST, FINAL }
    DateTime testDate(); // 자신이 아닌 다른 애너테이션 (@DateTime)을 포함할 수 있다.
}

@interface DateTime{
    String yymmdd();
    String hhmmss();
}
@TestInfo(
    count=3, testedBy = "Kim",
    testTools = {"JUnit","AutoTester"}
    testType = TestType.FIRST,
    testDate = @DateTime(yymmdd="160101", hhmmss="235959")
) // 요소의 이름을 같이 적어주므로 순서는 상관없다.
@interface TestInfo {
	int count() default 1; // 기본 값을 1로 지정(default 값)
}

@TestInfo  // @TestInfo (count = 1) 과 동일
@interface TestInfo {
    String value();
}
// 애너테이션의 요소가 오직 하나 뿐이고, 이름이 value인 경우, 애너테이션을 적용할 때 요소의 이름을 생략하고 값만 적어도 된다.

@TestInfo("passed") // @TestInfo(value = "passed")와 동일

 

 

@Retention

  • 애너테이션이 유지되는 범위를 지정하는데 사용한다.
  • 3가지 정책이 존재한다.
    • RetentionPolicy.SOURCE: 컴파일 이후 컴파일러에 의해 삭제된다.
    • RetentionPolicy.CLASS: 컴파일러에 의해 클래스 파일에 기록되지만 런타임까지 유지되지 않기 때문에 리플렉션을 이용하여 애노테이션의 정보를 얻을 수 없다.
    • RetentionPolicy.RUNTIME: 클래스 파일에도 애노테이션 정보가 기록되고 런타임 시에 리플렉션을 이용하여 애노테이션 정보를 얻을 수 있다. 

@Target

  • 애너테이션이 적용가능한 대상을 지정하는데 사용된다.
  • '@Target'으로 지정할 수 있는 적용 대상의 종류는 다음과 같다.

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
	String[] value();
}

@Documented

  • 애너테이션에 대한 정보가 javadoc으로 작성한 문서에 포함되도록 한다. 
  • 자바에서 제공하는 기본 애너테이션 중에 '@Override''@SuppressWarnings'를 제외하고는 모두 이 메타 애너테이션이 붙어있다. 
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.Type)
public @interface FunctionalInterface {}

애노테이션 프로세서

애노테이션 프로세서는 자바 컴파일러의 컴파일 단계에서 애노테이션 정보를 스캔하고 처리하는 Hook이다. 즉, 컴파일 도중에 애노테이션을 만나면 특정한 동작을 하도록 만들어진 코드를 말한다. 애노테이션 프로세서는 소스코드 파일(.java)나 클래스 파일(.class)를 입력 받아서 새로운 소스코드 파일 혹은 클래스 파일을 생성해낸다.

사용예제

  • Lombok
  • AutoService : java.util.ServiceLoader 용 파일 생성 유틸리티
  • @Override
  • Dangger 2 : 컴파일 타임 DI 제공

어노테이션 프로세싱 API

  • 애노테이션 프로세싱은 여러 라운드로 수행된다. 각 라운드는 컴파일러가 소스 파일에서 애노테이션을 검색하고 이러한 애노테이션에 적합한 애노테이션 프로세서를 선택하는 것으로 시작된다. 차례로 각 애노테이션 프로세서는 해당 소스에서 호출된다.
  • 프로세스 중에 파일이 생성되면 생성된 파일을 입력으로 사용하여 다른 라운드가 시작이된다. 이 프로세스는 처리단계에서 새 파일이 생성되지 않을 때까지 계속된다
  • 각 애노테이션 프로세서는 해당 소스에서 차례로 호출된다. 이 프로세스 중에 파일이 생성되면 생성된 파일을 입력으로 사용하여 다른 라운드가 시작된다. 이 프로세스는 처리 단계에서 새 파일이 생성되지 않을 때까지 계속된다.
  • 애노테이션 처리 API는 javax.annotation.processing 패키지에 있다. 구현해야 할 주요 인터페이스는 AbstractProcessor 클래스 형태의 부분 구현이 있는 프로세서 인터페이스다 이 클래스는 자체 주석 프로세서를 만들기 위해 확장할 클래스이다
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함