어노테이션

이기영·2024년 7월 3일

Java 기초학습

목록 보기
12/14
post-thumbnail

목표

자바의 어노테이션에 대해 학습

목차

1. 어노테이션 정의하는 방법
2. @retention
3. @target
4. @documented
5. 어노테이션 프로세서


1. 어노테이션 정의하는 방법

Java에서 어노테이션(Annotation)은 메타데이터를 제공하는 특별한 종류의 인터페이스입니다. 어노테이션은 코드에 대한 추가 정보를 제공하며, 주로 컴파일러 지시자, 런타임 정보 제공, 또는 코드 분석 도구에서 사용됩니다.


1-1 어노테이션 정의하기

  1. 어노테이션 인터페이스 생성
    @interface 키워드를 사용하여 어노테이션을 정의합니다.

  2. 요소 정의
    어노테이션 내에 요소(Element)를 정의할 수 있습니다. 요소는 기본값을 가질 수 있습니다.

예제

// 어노테이션 정의
public @interface MyAnnotation {
    String value();
    int number() default 0;
}

// 어노테이션 사용
@MyAnnotation(value = "Hello", number = 5)
public class MyClass {
    // 클래스 내용
}

1-2 어노테이션 요소의 기본값 설정

어노테이션 요소에 기본값을 설정할 수 있습니다. 기본값을 설정하면 어노테이션을 사용할 때 해당 요소를 생략할 수 있습니다.

// 어노테이션 정의
public @interface MyAnnotation {
    String value() default "default value";
    int number() default 42;
}

@MyAnnotation
public class MyClass {
    // 클래스 내용
    // 기본값을 설정해 두었기때문에, 요소를 생략할 수 있습니다.
}

1-3 어노테이션의 메타-어노테이션

  어노테이션도 다른 어노테이션으로 설명할 수 있습니다. 이를 메타-어노테이션(Meta-Annotation)이라고 합니다. Java에서는 여러 가지 메타-어노테이션이 있습니다.

  • @Retention : 어노테이션의 유지 정책을 정의합니다.
  • @Target : 어노테이션이 적용될 수 있는 위치를 정의합니다.
  • @Documented : 어노테이션이 Javadoc에 포함되도록 합니다.
  • @Inherited : 어노테이션이 하위 클래스에 상속되도록 합니다.

예제

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

// 어노테이션 정의
@Retention(RetentionPolicy.RUNTIME) // 런타임까지 어노테이션 유지
@Target(ElementType.METHOD) // 메서드에만 적용 가능
public @interface MyAnnotation {
    String value() default "default value";
    int number() default 42;
}



2. @Retention

@Retention 어노테이션은 Java에서 어노테이션이 얼마나 오래 유지될지를 지정하는 메타-어노테이션입니다. 이를 통해 어노테이션이 소스 코드, 클래스 파일, 런타임 중 어느 단계까지 유지될지를 결정할 수 있습니다.


2-1 @Retention 사용 방법

@Retention 어노테이션을 사용하여 어노테이션의 유지 정책을 설정할 수 있습니다. 유지 정책은 java.lang.annotation.RetentionPolicy 열거형을 통해 지정됩니다. RetentionPolicy는 다음과 같은 세 가지 값을 가질 수 있습니다.


1. RetentionPolicy.SOURCE
어노테이션이 소스코드에만 유지되고, 컴파일 과정에서 제거됩니다. 이는 주로 컴파일러에 대한 힌트로 사용됩니다.

2. RetentionPolicy.CLASS
어노테이션이 컴파일된 클래스 파일에 포함되지만, JVM에서 실행될 때는 사용할 수 없습니다. 이는 기본값입니다.

3. RetentionPolicy.RUNTIME
어노테이션이 런타임까지 유지되며, 리플렉션을 사용하여 런타임에 접근할 수 있습니다. 런타임 시에 동적으로 어노테이션 정보를 필요로 하는 경우에 사용됩니다.


예제

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface MyRuntimeAnnotation {
    String value();
}

// ----------------------------------------------------------

public class MyClass {
    @MyRuntimeAnnotation(value = "Example")
    public void myMethod() {
        // 메서드 내용
    }

    public static void main(String[] args) {
        MyClass obj = new MyClass();
        // 런타임에 어노테이션 정보 읽기
        MyRuntimeAnnotation annotation 
        = obj.getClass().getMethod("myMethod")
        .getAnnotation(MyRuntimeAnnotation.class);

		System.out.println(annotation.value()); 
        // "Example" 출력
    }
}

2-2 요약

  • @Retention 어노테이션은 어노테이션의 유지 정책을 결정합니다.

  • RetentionPolicy.SOURCE : 컴파일 후 어노테이션 제거

  • RetentionPolicy.CLASS : 컴파일된 클래스 파일에 어노테이션 유지

  • RetentionPolicy.RUNTIME : 런타임까지 어노테이션 유지



3. @Target

@Target 어노테이션은 Java에서 어노테이션이 적용될 수 있는 프로그램 요소를 지정하는 메타-어노테이션입니다. 이 어노테이션을 어디에 적용할 수 있는지 제한할 수 있습니다.


3-1 @Target 사용 방법

  @Target 어노테이션은 java.lang.annotation.ElementType 열거형을 인수로 받습니다. ElementType은 어노테이션이 적용될 수 있는 프로그램 요소를 정의하는 여러 상수를 제공합니다. 주요 ElemetType 값은 다음과 같습니다.


1. ElementType.Type
클래스, 인터페이스(어노테이션 유형 포함), 열거형에 적용됩니다.

2. ElementType.FIELD
필드(인스턴스 변수 포함)에 적용됩니다.

3. ElementType.METHOD
메서드에 적용됩니다.

4. ElementType.PARAMETER
메서드의 매개변수에 적용됩니다.

5. ElementType.CONSTRUCTOR
생성자에 적용됩니다.

6. ElementType.LOCAL_VARIABLE
지역 변수에 적용됩니다.

7. ElementType.ANNOTATION_TYPE
다른 어노테이션에 적용됩니다.

8. ElementType.PACKAGE
패키지 선언에 적용됩니다.

9. ElementType.TYPE_PARAMETER
제네릭 타입 매개변수에 적용됩니다.

10. ElementType.TYPE_USE
타입 사용에 적용됩니다.


3-2 @Target 예제

  다음은 @Target 어노테이션을 사용하여 어노테이션이 메서드에만 적용되도록 하는 예제입니다.

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

@Target(ElementType.METHOD)
public @interface MethodOnlyAnnotation {
    String value();
}

//-----------------------------------------------
public class MyClass {
    @MethodOnlyAnnotation(value = "This is a method")
    public void myMethod() {
        // 메서드 내용
    }

    // 잘못된 사용 - 컴파일 오류 발생
    // @MethodOnlyAnnotation(value = "This is a field")
    // private String myField;
}

@Target 어노테이션은 배열 형태로 여러 ElementType 값을 지정할 수 있습니다.

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

@Target({ElementType.TYPE, ElementType.METHOD})
public @interface TypeAndMethodAnnotation {
    String value();
}

//-----------------------------------------------

@TypeAndMethodAnnotation(value = "This is a class")
public class MyClass {
    @TypeAndMethodAnnotation(value = "This is a method")
    public void myMethod() {
        // 메서드 내용
    }
}

3-3 요약

  • @Target 어노테이션은 어노테이션이 적용될 수 있는 프로그램 요소를 지정합니다.

  • 주요 ElementType 값은 클래스, 메서드, 필드, 생성자, 매개변수 등 다양한 프로그램 요소를 포함합니다.

  • 여러 ElementType 값을 배열 형태로 지정할 수있습니다.



4. @Documented

@Documented 어노테이션은 Java에서 메타-어노테이션 중 하나로, 어노테이션이 Javadoc 문서에 포함되도록 지정하는 데 사용됩니다. 이를 통해 어노테이션이 문서화되고, Javadoc 도구를 사용하여 생성된 API 문서에 어노테이션의 존재와 설명이 포함됩니다.


4-1 @Documented 사용방법

  @Documented 어노테이션은 단순히 어노테이션 타입에 적용하여 Javadoc에 포함되도록 하는 역할을 합니다. 이는 주로 라이브러리나 API를 작성할 때 유용하며, 사용자가 어노테이션의 의미와 사용 방법을 문서에서 쉽게 확인할 수 있게 합니다.

예제

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyDocumentedAnnotation {
    String value();
}

// -----------------------------------------------

public class MyClass {
    /**
     * 이 메서드는 예제 메서드입니다.
     *
     * @param param 예제 매개변수
     */
    @MyDocumentedAnnotation(value = "Example annotation")
    public void myMethod(String param) {
        // 메서드 내용
    }
}

  이제 Javadoc 도구를 사용하여 문서를 생성하면 myMethod 메서드에 @MyDocumentedAnnotation 어노테이션이 포함된다는 내용이 문서화됩니다.

/**
 * 이 메서드는 예제 메서드입니다.
 *
 * @param param 예제 매개변수
 * @MyDocumentedAnnotation(value = "Example annotation")
 */
public void myMethod(String param) {
    // 메서드 내용
}

4-2 요약

  • @Documented 어노테이션은 어노테이션이 Javadoc 문서에 포함되도록 지정합니다.

  • 이는 API 문서를 작성할 때 어노테이션의 의미와 사용 방법을 문서에 포함시켜 사용자에게 제공하는 데 유용합니다.



5. 어노테이션 프로세서

Java 어노테이션 프로세서(Annotation Processor)는 컴파일러가 소스 코드를 컴파일하는 동안 어노테이션을 처리할 수 있는 도구입니다.

어노테이션 프로세서를 사용하면 컴파일 타임에 어노테이션을 분석하고, 소스코드를 생성하거나 검증 작업을 수행할 수 있습니다. 이를 통해 코드의 유지보수성과 생산성을 높일 수 있습니다.

5-1 어노테이션 프로세서의 동작 원리

  어노테이션 프로세서는 컴파일러 API를 사용하여 특정 어노테이션이 적용된 코드를 분석하고, 이에 따라 추가적인 작업을 수행합니다. 주요 단계는 아래와 같습니다.


1. 어노테이션 프로세서 정의
어노테이션 프로세서 클래스를 정의하고 javax.annotation.processing.Processor 인터페이스를 구현합니다.

2. 어노티이션 프로세서 등록
META-INF/service/javax.annotation.processing.Processor 파일에 어노테이션 프로레서 클래스 이름을 등록합니다.

3. 어노테이션 프로세서 실행
컴파일 시 컴파일러가 어노테이션 프로세서를 자동으로 실행하여 어노테이션을 처리합니다.


5-2 어노테이션 프로레서 구현 예제

  이 예제에서는 @MyAnnotation 어노테이션이 적용된 클래스의 정보를 출력하는 어노테이션 프로세서를 작성합니다.


어노테이션 정의
먼저, @MyAnnotation 어노테이션을 정의합니다.

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.SOURCE)
public @interface MyAnnotation {
    String value();
}

어노테이션 프로세서 구현
다음으로, @MyAnnotation 어노테이션을 처리하는 어노테이션 프로세서를 구현합니다.

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import java.util.Set;

@SupportedAnnotationTypes("MyAnnotation")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class MyAnnotationProcessor extends AbstractProcessor {

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        for (Element element : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
            MyAnnotation annotation = element.getAnnotation(MyAnnotation.class);
            System.out.println("Found @MyAnnotation with value: " + annotation.value());
        }
        return true; // 어노테이션이 처리되었음을 표시
    }
}

어노테이션 프로세서 등록
META-INF/services/javax.annotation.processing.Processor파일을 생성하고, 어노테이션 프로세서 클래 이름 등록을 합니다.

MyAnnotationProcessor

어노테이션 프로세서 사용
이제 @MyAnnotation 어노테이션을 사용하여 클래스를 작성하고 컴파일하면 어노테이션 프로세서가 실행됩니다.

@MyAnnotation(value = "Hello, World!")
public class MyClass {
    public static void main(String[] args) {
        // 메인 메서드 내용
    }
}

5-3 주요 클래스와 인터페이스

  • AbstractProcessor
    Processor 인터페이스의 기본 구현을 제공하는 추상 클래스입니다. 어노테이션 프로세서를 작성할 때 주로 이 클래스를 확장합니다.

  • ProcessingEnvironment
    어노테이션 프로세서 환경을 제공하는 인터페이스로, 필수 유틸리티 메서드와 메시지 출력을 지원합니다.

  • RoundEnvironment
    현재 프로세스 라운드에 대한 정보를 제공하는 인터페이스로, 어노테이션이 적용된 요소들을 탐색할 수 있습니다.


5-4 요약

  • 어노테이션 프로세서는 컴파일 타임에 어노테이션을 처리하여 추가적인 작업을 수행합니다.

  • 어노테이션 프로세서를 정의하려면 AbstractProcessor 클래스를 확장하고, 필요한 메서드를 구현해야 합니다.

  • 어노테이션 프로세서를 등록하려면 META-INF/services/javax.annotation.processing.Processor 파일에 프로세러 클래스를 등록해야 합니다.

profile
안녕나를소개하지이름은HaBu직업은Programer취미는tai chi meditation

0개의 댓글