본문 바로가기

Java

자바의 애너테이션(Annotation)

728x90

애너테이션이란, 주석처럼 프로그래밍 언어에 영향을 미치지는 않으면서도 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킴으로써 다른 프로그램에게 유용한 정보를 제공할 수 있는 기능을 제공하는 '메모'라고 할 수 있습니다. 이번 포스팅은 자바에서 제공하는 애너테이션에 대해서 알아보겠습니다.



자바에서 기본적으로 제공하는 애너테이션 중 대표적인 종류는 아래와 같습니다.


애너테이션 설명
@Override 컴파일러에게 오버라이딩하는 메서드라는 것을 알려줍니다.
@Deprecated 앞으로 사용하지 않을 것을 권장하는 대상에 붙입니다.
@SuppressWarnings 컴파일러의 특정 경고메시지가 나타나지 않도록 해줍니다.
@FunctionalInterface 함수형 인터페이스임을 나타냅니다.

 

그리고 자바에서 제공하는 애너테이션 중 '메타 애너테이션'이라는 것이 있습니다. 이 애너테이션은 애너테이션을 정의할 때 애너테이션 위에 붙이는 애너테이션, 즉 '애너테이션을 위한 애너테이션'입니다.  종류는 아래가 있습니다.


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

 


우선 기본적인 표준 애너테이션부터 살펴보겠습니다.

표준 애너테이션

@Override

부모 메서드를 오버라이딩한 메서드임을 나타냄으로써 개발자가 메서드의 이름을 잘못 작성했거나 타입을 잘못 지정했을 경우 컴파일러가 오류를 잡아낼 수 있도록 도와줍니다.


class Person{
	void printName(){
   		System.out.println("I'm Parent.");
    }
}

class Child extends Person{
	@Override
	void printName(){
   		System.out.println("I'm a child.");
    }
}

 


@Deprecated

새로운 버전의 JDK가 개발될 때 새로운 기능이 개발되면서 이전 기능들이 더 이상 필요하지 않은 경우가 있습니다. 하지만 이미 이 기능들이 다른 곳에서 사용되고 있을 수도 있기 때문에 함부로 삭제할 수 없습니다. 이런 경우 '앞으로는 이 기능을 사용하지 않는 것을 권장한다.'라는 의미를 나타내기 위해 @Deprecated 애너테이션을 사용합니다.


public class TestClass {
   @Deprecated
   int oldField;

   @Deprecated
    int getOldField(){
       return oldField;
   }
}


public class Main {
    public static void main(String[] args) {
        TestClass animal=new TestClass();
        System.out.println(animal.getOldField());
    }
}

@FunctionalInterface

함수형 인터페이스를 선언할 때 이 애너테이션을 붙이면 컴파일러가 함수형 인터페이스를 올바르게 선언했는지 확인하고 잘못된 경우 에러를 발생시킵니다. @Override처럼 이 애너테이션을 붙이면 실수를 방지할 수 있습니다.


// 자바에서 제공하는 Runnable 인터페이스
@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

@SuppressWarnings

컴파일러가 보여주는 경고 메시지를 억제해 주는 (나타나지 않게 해 주는) 역할을 하는 애너테이션입니다. 이 애너테이션으로 억제할 수 있는 경고는 여러 가지가 있지만 대표적으로는 'deprecation', 'unchecked', 'rawtypes', 'varags'가 있습니다.

 

  1. deprecation: @Deprecated가 붙은 대상을 사용해서 발생하는 경고
  2. unchecked: 제네릭(Generics)으로 타입을 지정하지 않았을 때 발생하는 경고
  3. rawtypes: 제네릭(Generics)을 사용하지 않아서 발생하는 경고
  4. varargs: 가변인자의 타입이 제네릭 타입일 때 발생하는 경고

 

아래와 같이 억제하고자 하는 경고 메시지를 애너테이션의 () 안에 지정할 수 있습니다. 여러 경고를 억제하고 싶을 때는 { } 안에 여러 개를 지정하면 됩니다.


@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "unchecked"})

 
아래 예시를 보면 "deprecation"을 사용하면 원래는 노란 줄로 경고를 내던 컴파일러의 메시지가 없어지는 것을 확인할 수 있습니다.

애너테이션 사용 X
애너테이션 사용

 

JDK 버전이 올라가면서 원래는 없던 경고가 새로 생기는 경우도 발생합니다. 이때 새로 생긴 경고의 이름을 확인하려면 -Xlint 옵션으로 컴파일해서 경고의 내용 중 대괄호[ ] 안에 있는 경고 이름을 확인하여 @SuppressWarnings()에 값을 넣어서 적용할 수 있습니다.


컴파일러 경고
컴파일 결과


두 번째로 메타 애너테이션에 대해서 간단히 살펴보겠습니다.
 

메타 애너테이션

@Target

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


// 자바에서 제공하는 SuppressWarnings
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();
}

적용대상 종류

  1. ANNOTATION_TYPE: 애너테이션
  2. CONSTRUCTOR: 생성자
  3. FIELD: 필드(멤버변수, enum 상수)
  4. LOCAL_VARIABLE: 지역변수
  5. METHOD: 메서드
  6. PACKAGE: 패키지
  7. PARAMETER: 매개변수
  8. TYPE: 타입(클래스, 인터페이스, enum, 애너테이션)
  9. TYPE_PARAMETER: 타입 매개변수
  10. TYPE_USE: 타입이 사용되는 모든 곳

@Target({FIELD, TYPE, TYPE_USE})
public @interface TestTime {}

@TestTime // TYPE
class MyClass{
    @TestTime
    int hour; // FIELD
    
    @TestTime
    MyClass myClass; // TYPE_USE
}

@Retention

애너테이션이 유지되는 기간을 지정하는 데 사용됩니다.


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

 

1. SOURCE
@Override나 @SuppressWarnings와 같은 컴파일러에 의해 사용되는 애너테이션은 'SOURCE' 정책을 사용합니다. 컴파일러를 직접 작성할 것이 아니라면 이 정책은 사용할 일이 없습니다.
 
2. CLASS
컴파일러가 애너테이션의 정보를 클래스 파일에 저장하지만, 클래스 파일이 JVM에 로딩될 때는 애너테이션의 정보가 무시되어 실행 시에는 애너테이션에 대한 정보를 얻을 수 없습니다. 그래서 보통 잘 사용하지 않습니다.
 
3. RUNTIME
실행 시에 클래스 파일에 저장된 애너테이션의 정보를 읽어서 처리할 수 있습니다. 보통 애너테이션을 개발자가 직접 정의하여 사용할 때 이 옵션을 사용합니다. 더 자세한 내용은 아래 포스팅에서 확인할 수 있습니다!

https://silver-programmer.tistory.com/m/entry/%EC%9E%90%EB%B0%94%EC%97%90%EC%84%9C-%EC%95%A0%EB%84%88%ED%85%8C%EC%9D%B4%EC%85%98Annotation-%EC%A7%81%EC%A0%91-%EC%A0%95%EC%9D%98%ED%95%98%EA%B8%B0

 

자바에서 애너테이션(Annotation) 직접 정의하기

애너테이션이란, 주석처럼 프로그래밍 언어에 영향을 미치지는 않으면서도 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킴으로써 다른 프로그램에게 유용한 정보를 제공할 수 있

silver-programmer.tistory.com

 


@Inherited

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


@Inherited
public @interface InheritedAnno{}

@InheritedAnno
class Parent{}

class Child extends Parent{} // Child에도 InheritedAnno가 붙은 것으로 인식

@Repeatable

@Repeatable이 붙으면 해당 애너테이션을 한 대상에 여러 번 사용할 수 있습니다.


@Repeatable()
public @interface RepeatAnno{ String value();}

@RepeatAnno("repeat1")
@RepeatAnno("repeat2")
class Parent{}

 
[참고자료]

남궁 성, [Java의 정석 3rd Edition], 도우출판, 2016, p715~720

https://docs.oracle.com/javase/8/docs/technotes/guides/language/annotations.html

 

Annotations

Annotations Many APIs require a fair amount of boilerplate code. For example, in order to write a JAX-RPC web service, you must provide a paired interface and implementation. This boilerplate could be generated automatically by a tool if the program were

docs.oracle.com

 

728x90
반응형

'Java' 카테고리의 다른 글

제네릭(Generic)이란?  (0) 2023.10.25
Thread 구현과 실행 (Runnable vs Thread)  (0) 2023.10.25
자바에서 애너테이션(Annotation) 직접 정의하기  (0) 2023.10.22
-Xlint 옵션  (0) 2023.10.21
열거형(enums)  (2) 2023.10.21