본문 바로가기
개발/Java

자바 애노테이션이란?

by Devsong26 2022. 3. 24.

애노테이션이란?

애노테이션 사전적 의미로는 주석이라는 뜻이며 자바에서 사용될 때의 애노테이션은 코드 사이에 주석처럼 쓰여서 특별한 의미, 기능을 수행하도록 하는 기술입니다. 즉, 프로그램에게 추가적인 정보를 제공해주는 메타데이터(meta data: 데이터를 위한 데이터)라고 볼 수 있습니다.

 

다음은 애노테이션의 용도를 나타낸 것입니다.

- 컴파일러에게 코드 작성 문법 에러를 체크하도록 정보를 제공

- 소프트웨어 개발툴이 빌드나 배치시 코드를 자동으로 생성할 수 있도록 정보 제공

- 실행시(런타임시) 특정 기능을 실행하도록 정보를 제공

 

기본적으로 애노테이션을 사용하는 순서는 다음과 같습니다.

1. 애노테이션의 정의

2. 클래스에 애노테이션을 배치

3. 코드가 실행되는 중에 Reflection을 이용하여 추가정보를 획득하여 기능 실시

 

1. 애노테이션의 정의

- 애노테이션을 적용할 때는 애노테이션이 어디에 적용되며 언제까지 애노테이션 소스가 유지될 것인지를 설정하여야 하는데 소스 코드에는 다음과 같이 애노테이션을 정의해 주면 됩니다.

@Target({ElementType.[적용대상]})
@Retention(RetentionPolicy.[정보유지되는 대상])
public @interface [어노테이션명]{
	public 타입 elementName() [default 값]
    ...
}

 

@Target에는 어떠한 값(ex: 클래스, 필드, 메서드 ...)에 애노테이션을 적용할 것인지를 명시할 수 있으며 아래의 표와 같습니다.

ElementType 열거 상수 적용대상
TYPE 클래스, 인터페이스, 열거 타입
ANNOTATION_TYPE 애노테이션
FIELD 필드
CONSTRUCTOR 생성자
METHOD 메서드
LOCAL_VARIABLE 로컬 변수
PACKAGE 패키지

 

@Retention에는 애노테이션 값들을 언제까지 유지할 것인지 값을 입력하는데 각 값이 가지는 의미는 다음 표와 같습니다.

RetentionPolicy 열거 상수 설명
SOURCE 소스상에서만 애노테이션 정보를 유지하며 소스 코드를 분석할 때만 의미가 있고, 바이트 코드 파일에는 정보가 남지 않는다.
CLASS 바이트 코드 파일까지 애노테이션 정보를 유지하지만 리플렉션을 이용해서 
애노테이션 정보를 얻을 수는 없다.
RUNTIME 바이트 코드 파일까지 애노테이션 정보를 유지하면서 리플렉션을 이용해서 
런타임에 애노테이션 정보를 얻을 수 있다.

 

2. 애노테이션의 배치 및 사용

간단한 애노테이션을 생성하여 특정 메서드에 지정 후 테스트 코드를 작성하였습니다.

메서드에서 리플렉션 라이브러리를 사용하여 애노테이션 정보를 가져오는지 확인해봅시다.

 

SimpleAnnotation.java

- 애노테이션 생성

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

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SimpleAnnotation {
    /**
     * default 키워드는 자바 8에서부터 인터페이스에 사용할 수 있도록 도입이 되었고,
     * 이 키워드를 사용하면 인터페이스에 추상 메서드가 아닌 구현부를 지닌 메서드를 정의할 수 있다.
     */
    String value() default "-";
    int number() default 10;
}

 

SimpleService.java

- 애노테이션을 메서드에 지정합니다.

public class SimpleService {

    @SimpleAnnotation(value = "*", number = 15)
    public void foo(){
        System.out.println("foo");
    }

}

 

SimpleServiceTest.java

- 애노테이션의 정보를 리플렉션 라이브러리를 통해 가져와 예상된 결과를 검증합니다.

import org.junit.jupiter.api.Test;
import parts.rest.annotation.SimpleAnnotation;

import java.lang.reflect.Method;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

class SimpleServiceTest {

    /**
     * Retention.Runtime으로 지정된 SimpleAnnotation을
     * 타겟 메서드 정보를 통해 조회하여 확인하는 학습테스트
     */
    @Test
    public void check_annotation_on_foo(){
        AtomicReference<Method> m = new AtomicReference<>();

        assertDoesNotThrow(() -> {
            m.set(SimpleService.class.getMethod("foo"));
        });

        assertTrue(m.get().isAnnotationPresent(SimpleAnnotation.class));
        assertEquals(m.get().getName(), "foo");

        SimpleAnnotation annotation= m.get().getDeclaredAnnotation(SimpleAnnotation.class);
        String value=annotation.value();
        int number=annotation.number();

        StringBuilder sb = new StringBuilder();

        for(int i=0; i<number; i++) sb.append(value);

        assertEquals("***************", sb.toString());
    }

}

 

 


 

참고

https://honeyinfo7.tistory.com/56#2.%20%EC%96%B4%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98%EC%9D%98%20%EB%B0%B0%EC%B9%98%20%EB%B0%8F%20%EC%82%AC%EC%9A%A9