programming language/Java

어노테이션(annotation)이란?

공대키메라 2022. 3. 31. 22:29

평소 어노테이션을 많이 사용하지만 이에 대해 무엇이라고 설명할 수 없는 자신을 가르치기(?) 위해 이 글을 정리한다.

 

다음 정리할 내용을 사이트와 함께 java의 정석도 참고했다.

출처 : https://www.geeksforgeeks.org/annotations-in-java/ 

1. 어노테이션이란?

프로그램의 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킨 것
- java의 정석 발췌 -

 

  • 어노테이션은 @로 시작한다.
  • 어노테이션은 컴파일된 프로그램의 행동을 바꾸지 않는다. 
  • 어노테이션은 프로그램 elements와 메타데이터를 어울리도록 돕는다. 즉, 인스턴스 변수, 생성자, 메소드, 클래스 등등
  • 어노테이션은 한 프로그램이 컴파일러에 의해 다뤄지는 방식을 바꿀 수 있기에 순수한 주석이 아니다. 
  • 어노테이션은 기본적으로 추가적인 정보를 제공하는데 사용된다. 그래서 xml혹은 자바 마커 인터페이스로 대체가 가능하다. 

2. 어노테이션 종류

 

어노테이션은 표준 어노테이션과 우리가 만든 커스텀 어노테이션으로 나뉠 수 있다.

 

표준 어노테이션을 기반으로 framework에서 많은 어노테이션을 만들어서 좋은 기능을 제공하는 것이다. 

 

사실 우리가 무언가 annotation을 새로 정의해서 사용할 일은 많지 않다. 그래도 이번 기회에 제대로 이해하고 넘어가려고 한다. 

General Purpose Annotations

  • Overrice : 컴파일러에게 오버라이딩하는 메서드라는 것을 알림
  • Deprecatd : 앞으로 사용하지 않을 것을 권장하는 대상에 붙임
  • SurpressWariungs : 컴파일러의 특정 경고메시지가 나타나지 않게 함
  • SafeVarargs : 지네릭스 타입의 가변인자에 사용
  • FuntionalInterface : 함수형 인터페이스라는 것을 알림

 

Meta Annotations

  • Target : 애너테이션이 적용가능한 대상을 지정하는데 사용
  • Documented :  애너테이션 저옵가 javadoc으로 작성된 문서에 포함되게 함
  • Inherited : 애너테이션이 자손 클래스에 상속되도록 함
  • Retention : 애너테이션이 유지되는 범위를 지정하는데 사용
  • Repeatable : 애너테이션을 반복해서 적용할 수 있게 함

3. 메타 애너테이션 분석

@Target, @Retention, @Inherited, @Documented, @Repeatable이 있다.

@Target

애너테이션 이 적용가능한 대상을 지정하는데 사용

 

//사용 예시

@Target({ElementType.TYPE, ElementType.FIELD})
class TargeTest{

}

 

 

@Target으로 지정할 수 있는 애너테이션 적용 대상의 종류는 아래와 같다. 

 

  • ANNOTATION_TYPE : 애노테이션
  • CONSTRUCTORE : 생성자
  • FIELD : 필드
  • LOCAL_VARIAVLE : 지역변수
  • METHOD : 메소드
  • PACKAGE : 패키지
  • PARAMETER : 매개변수
  • TYPE : 타입. class, interface, enum 에 적용
  • TYPE_PARAMETER : 타입 매개변수
  • TYPE_USE : 타입이 사용되는 모든 곳

 

보니까 어디에 사용할 지 원하는 항목만 지정해주면 된다. 

@Retention

애너테이션 유지 기간 설정에 사용

 

//사용 예시

@Retention(RetentionPolicy.RUNTIME)
public class test{
...
}

 

유지 정책

  • SOURCE : 소스 파일에만 존재. 클래스파일에는 존재하지 않음
  • CLASS : 클래스 파일에 존재. 실행시에 사용 불가. 기본값
  • RUNTIME : 클래스 파일에 존재. 실행시에 사용가능.

SOURCE는 실제로 컴파일러를 작성할 것이 아니면 사용할 일이 없다. 

 

CLASS는 컴파일러가 애너테이션의 정보를 클래스 파일에 저장할 수 있게는 하는데 JVM 로딩시에는 이 정보가 무시되어 애너테이션에 대한 정보를 못 얻는다. 그럴바에는 RUNTIME을 많이 사용한다. 

 

RUNTIME는 실행시 Reflection을 통해 클래스파일에 저장된 애너테이션 정보를 읽어 처리한다. 

@Documented

애너테이션 정보가 javacdoc으로 작성된 문서에 포함되도록 한다. 

@Inherited

애너테이션이 자손 클래스에 상속되도록 한다. 

 

// 사용 예시

public @interface TestAno1 { }

@TestAno1
class TestParentClass{
    static class ChildClass extends TestParentClass{}
}

@Native

네이티브 메서드에 의해 참조되는 상수 필드에 붙이는 애너테이션

 

4. 커스텀 어노테이션 만들기

 

애너테이션 요소 선언시 반드시 지켜야 하는 규칙이 있다고 한다.

 

  • 요소의 타입은 기본형, String, enum, 애너테이션, Class만 허용한다.
  • ()안에 매개변수를 선언할 수 없다.
  • 예외를 선언할 수 없다. 
  • 요소를 타입 매개변수로 정의할 수 없다. 

 

package realBasic.core.autowired;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface CustomAnnotation { }

@CustomAnnotation
class TestParentClass{

    //@CustomAnnotation <= target은 Type(class, interface, enum만 적용 가능.)
    String test1;
    
    @CustomAnnotation
    static class ChildClass extends TestParentClass{

    }
}

 

 

Type을 잘 설정해주면 어떤 것이든 애너테이션 적용이 가능하다. 

 


사실 그렇게 어려운 내용들은 아니고 내가 실제로 만들어서 사용할 일은 거의 없다. 

 

그래도 무언가 매일 사용하는데 내부에 의미라고 잘 알고 싶어서 간단히 정리해봤다.