☕️ Java/기본

[Java] 애너테이션에 대한 기초

말 랑 2022. 1. 22. 14:05
728x90

 

애너테이션이란 프로그램의 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킨 것이다.

마치 주석과도 같이 프로그래밍 언어에 영향을 미치지 않으면서도 다른 프로그램에게 유용한 정보를 제공할 수 있다는 장점이 있다. (스프링에서 사용되는 에너테이션은 영향을 미치지만, 우선 스프링이 아닌 기본 자바를 기준으로 설명하겠다.)

 

 


 

 

표준 애너테이션

자바에서 기본적으로 제공하는 애너테이션은 몇 개 존재하지 않는다.

게다가 그들 중 일부는 '메타 애너테이션'으로 애너테이션을 정의하는데 사용되는, 애너테이션을 위한 애너테이션이다.

 

자바에서 기본적으로 제공하는 표준 애너테이션의 종류는 다음과 같다.

애너테이션 설명
@Override 컴파일러에게 메서드를 오버라이딩 하는 것이라고 알린다.
@Deprecated 앞으로 사용하지 않을 것을 권장하는 대상에 사용한다.
@SuppressWarnings 컴파일러의 특정 경고메세지가 나타나지 않게 해준다.
@SafeVarargs 지네릭스 타입의 가변인자(...)에 사용한다.
@FunctionalInterface 함수형 인터페이스라는 것을 알린다.
@Native native 메서드에서 참조되는 상수 앞에 붙인다.
@Target* 애너테이션이 적용가능한 대상을 지정하는데 사용한다
@Documented* 애너테이션 정보가 javadoc으로 작성된 문서에 포함되도록 한다.
@Inherited* 애너테이션이 자손 클래스에 상속되도록 한다.
@Retention* 애너테이션이 유지되는 범위를 지정하는데 사용된다.
@Repeatable* 애너테이션을 반복해서 적용할 수 있게 한다.

(*이 붙은 것은 메타 애너테이션이다.)

 

 

 


 

 

@Override

자주 접해보았을 것이다.

(사실 모르는 사람이 없을 것이라 생각하여 간단히만 소개하고 넘어가겠다)

메서드 앞에만 붙일 수 있는 애너테이션으로, 부모의 메서드를 오버라이딩 하는 것이라는 것을 컴파일러에게 알려주는 역할을 한다.

 

 

 


 

@Deprecated

새로운 버전이 계속해서 탄생함에 따라, 새로운 기능이 추가될 뿐만 아니라 기존의 부족했던 기능들이 개선된다.

이러한 과정 속에서 기존의 기능을 대체할 것들이 추가되어도, 이미 여러 곳에서 사용되고 있을 지 모르는 기존의 것들을 함부로 삭제할 수 없다. (하위 호완성을 유지하기 위함)

따라서 생각해 낸 방법이 바로 더 이상 사용되지 않는 필드나 메서드에 @Deprecated 애너테이션을 붙이므로써, 기존의 사용되던 것과의 호완성을 유지하며, 새롭게 개발하는 코드에서는 다른 것으로 대체되었으니 더 이상 사용하지 않을 것을 권한다는 의미이다.

 

예를 하나 보자. 자바의 Date 클래스이다.

@Deprecated가 붙어있으며, 대체된 다른 클래스를 소개해준다.

 

 


 

 

@FunctionalInterface

함수형 인터페이스를 선언할 때, 컴파일러에게 올바르게 함수형 인터페이스를 선언했는지 확인하고, 잘못된 경우 에러를 발생시키게끔 만들어준다.

 

 

 

 


 

 

@SuppressWarnings

컴파일러가 보여주는 경고 메세지가 나타나지 않게 억제해준다.

컴파일러의 경고 메시지를 묵인해야 할 때가 종종 존재하는데, 이 경고를 그대로 놔두면 컴파일 할 때마다 메시지가 나타난다.

이렇게 묵인해야 하는 결고가 발생하는 대상에 @SuppressWarnings를 붙여서 컴파일 후에 어떤 경고 메세지도 나타나지 않게 해준다.

대표적으로 억제하는 경고 메세지는 "deprecation", "unchecked", "rawtypes", "varargs" 정도이다.

 

사용 예시는 다음과 같다.

@SuppressWarnings("unchecked")
ArrayList list = new ArrayList();
list.add(obj);

 

 

 


 

 

 

메타 애너테이션

앞서 잠깐 언급했듯이, 메타 애너테이션은 '애너테이션을 위한 애너테이션', 즉 애너테이션에 붙이는 애너테이션으로 애너테이션을 정의할 때 애너테이션의 적용대상(target)이나 유지기간(rentention) 등을 지정하는데 사용된다.

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

 

 

 


 

@Target

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

아래는 SuppressWarings 애너테이션의 정의인데, 한번 살펴보자.

 

@Target으로 여러 적용 대상을 정해주었다.

 

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

대상 타입 의미
ANNOTATION_TYPE 애너테이션
CONSTRUCTOR 생성자
FIELD 필드(멤버변수, enum 상수)
LOCAL_VARIABLE 지역변수
METHOD 메서드
PACKAGE 패키지
PARAMETER 매개변수
TYPE 타입(클래스, 인터페이스, enum)
TYPE_PARAMETER 타입 매개변수(<E>에서 E)
TYPE_USE 타입이 사용되는 모든 곳

 

 

TYPE은 타입을 선언할 때 이 애너테이션을 붙일 수 있다는 뜻이고, TYPE_USE는 해당 타입의 변수를 선언할 때 붙일 수 있다는 뜻이다.

 

 

 


 

 

 

@Rentention

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

종류는 다음과 같다.

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

(소스 파일은 컴파일 이전, 클래스 파일은 컴파일 이후이다.)

 

 

 


 

 

@Documented

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

 

 

 


 

 

 

@Inherited

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

@Inherited가 붙은 애너테이션을 조상 클래스에 붙이면, 자손 클래스도 이 애너테이션이 붙은 것과 같이 인식된다.

@Inherited
@interface SuperAnno{}

@SuperAnno
class Parent{}

class Child extends Parent{} //Child에 에네테이션이 붙은 것으로 인식

 

 

 


 

 

 

@Repeatable

보통은 하나의 대상에 한 종류의 애너테이션을 붙이지만, 여러 번 붙일 수 있도록 만들어 줄 때 사용한다.

 

 

 

 


 

 

 

애너테이션 타입 정의하기

지금까지는 애너테이션을 사용하는 방법에 대해서 살펴보았고, 이제 애너테이션을 직접 만드는 방법에 대해서 알아보자.

간단하다.

@interface 애너테이션이름 {
    타입 요소이름();
}

 

 

아래는 예시이다.

 

 

 

 

 

애너테이션의 요소

애너테이션 내에 선언된 메서드를 '애너테이션의 요소'라고 하며, 반환값은 있고, 매개변수는 없는 추상 메서드의 형태를 가진다.

애너테이션을 적용할 때 이 요소들의 값을 빠짐없이 지정해 주어야 하며, 순서는 상관없다.

만약 기본값을 지정해주고 싶다면, 다음과 같이 사용한다.

 

 

 

 

만약 요소의 타입이 배열이라면 괄호{}를 사용해서 여러 개의 값을 지정할 수 있다.

@Test(testTools={"JUnit", "AutoTester"})

728x90