-
[live-study] 12주차 :: 애노테이션JAVA/라이브 스터디 | whiteship 2021. 2. 15. 00:12
참고도서 : Java의 정석(3rd Edition)
0. 애노테이션애노테이션이란
- 애노테이션(Annotation)은 주석이라는 뜻이다.
- 자바를 개발한 사람들은 소스코드에 대한 문서를 따로 만들기 보다는, 소스코드와 문서를 하나의 파일로 관리하는 것이 낫다고 생각했다. 그래서 주석 /** ~ **/ 에 소스코드에 대한 정보를 저장하고, 그 소스코드의 주석으로부터 HTML문서를 생성해내는 프로그램 (javadoc.exe)을 만들어서 사용했다.
- 주석과 마찬가지로 프로그래밍 언어에 영향을 끼치지 않으면서, 유용한 정보를 제공한다.
- 그리고 모든 애노테이션의 조상은 Annotation (java.lang.annotation.Annotation) 이다. 하지만, 애노테이션은 상속이 허용되지 않으므로 아래와 같이 extends 할 수는 없다.
- 아래와 같이 모든 애노테이션의 조상인 Annotation은 애노테이션이 아니라 인터페이스로 정의가 되어 있다. 따라서, 모든 애노테이션 객체에 대해 equals(), toString()과 같은 객체 호출이 가능하다.
표준 애노테이션과 메타 애노테이션
- 자바에서 기본적으로 제공하는 표준 애노테이션과 애노테이션을 정의하는데 사용되는 '애노테이션의 애노테이션'인 메타 애노테이션이 있다.
- JDK에서 제공하는 표준 애노테이션은 주로 컴파일러를 위한 것으로 컴파일러에게 유용한 정보를 제공한다.
- 메타 에노테이션 중에 @retention, @target, @documented는 아래에서 조금 더 살펴본다.
1. 애너테이션 정의하는 방법
애노테이션 정의
- 직접 애노테이션을 만드는 방법은 interface 정의하는 방법 + @를 붙이는 것이라고 보면 된다.
애노테이션 요소 (element)
- 애노테이션 내에 선언된 메소드를 애노테이션의 요소라고 한다.
- 애노테이션 요소를 선언할 때에는 다음과 같은 규칙을 따른다.
- 요소의 타입은 기본형, String, enum, 애노테이션, class만 허용된다.
- ()안에 매개변수를 선언할 수 없다.
- 예외를 선언할 수 없다.
- 요소를 타입 매개변수로 정의할 수 없다.
- 그리고 아래와 같이 요소들을 정의할 수 있으며, 애노테이션의 요소는 반환값이 있고 매개변수는 없는 추상 메소드의 형태를 가지며, 상속을 통해 구현하지 않아도 된다.
- 다만, 애노테이션을 적용할 때 아래와 같이 요소들을 빠짐없이 지정해주어야한다. 순서는 상관없다.
- 기본값이 있는 요소라면, 에노테이션을 적용할 때 값을 지정하지 않으면 기본값이 사용된다.
+) 표준 애노테이션
@Override
- 메소드 앞에만 붙일 수 있는 애노테이션이다.
- 조상의 메소드를 오버라이딩하는 것을 컴파일러에게 알려주는 역할을 한다.
- 예를 들어, 아래와 같이 오버라이딩을 할 때 메소드의 이름을 잘못 적는 경우가 있다고 가정해보자. 컴파일러는 잘못 적은 메소드를 오버라이딩 하는 메소드로 인식하는 것이 아니라, 새로운 메소드가 추가 되었다고 인식한다.
- 하지만, @Override라는 애노테이션을 붙이면 컴파일러가 조상 메소드와 같은 이름이 있는지 체크하고 아래와 같이 에러메시지를 출력한다.
@Deprecated
- 새로운 버젼은 JDK가 소개될 때, 이 과정에서 기존의 기능을 대체할 것들이 추가되어도 이미 여러곳에서 사용되고 있을지도 몰라서 기존의 것들을 함부로 삭제할 수 없다.
- 그래서 더 이상 사용되지 않는 필드나 메소드에 '@Deprecated'를 붙이는 것이다.
- 예를 들어 java.util.Date 클래스의 대부분의 메소드에는 @Deprecated가 붙어있다. 그 중에서 getDate()를 보면 아래와 같이 Calendar클래스의 get()을 사용하라고 적혀 있고, Date클래스의 getDate()메소드에는 @Deprecated가 붙어 있는 것을 볼 수 있다.
- 사용 할 수는 있겠지만, 권장하지는 않는다.
@FunctionalInterface
- 함수형 인터페이스(functional interface)를 선언할 때, 컴파일러가 함수형 인터페이스를 올바르게 선언했는지 확인하고 아니라면 에러를 발생시키는 애노테이션이다.
@SuppressWarnings
- 컴파일러가 보여주는 경고메시지를 나타나지 않게 해준다. 묵인해야하는 경고가 발생하는 대상에는 반드시 @SuppressWarnings를 붙여서 경고 메시지가 발생하지 않도록 해주어야한다.
- 주로 억제하는 경고 메시지의 종류에는 derpecation, unchecked, rawtypes, varargs가 있다.
- deprecation은 '@Deprecated'가 붙은 대상을 사용해서 발생하는 경고 억제
- unchecked는 generics로 타입을 지정하지 않았을 때 발생하는 경고 억제
- rawtypes는 generics를 사용하지 않아서 발생하는 경고 억제
- varargs는 가변인자의 타입이 generic type일 떄 발생하는 경고 억제
@SafeVarargs
- 메소드에 선언된 가변인자의 타입이 non-reifiable타입(컴파일 후에 제거되는 타입)일 경우, unchecked경고가 발생한다. 해당 코드에 문제가 없다면, @SafeVarargs를 사용하여 경고를 억제해야한다.
2. @Retention
@Retention
- 애노테이션인 유지(retention)되는 기간을 지정하는데 사용된다.
- 애노테이션의 유지 정책(retention policy). 종류는 다음과 같다.
- 컴파일러가 사용하는 애노테이션(@Override, @SuppressWarnings)은 유지 정책이 SOURCE이다. 컴파일러를 직접 작성할 것이 아니라면 이 유지정책은 필요없다.
- @FunctionalInterface는 @Override처럼 컴파일러가 체크해주는 애노테이션이지만, 실행 시에도 사용되므르 유지 정책인 RUNTIME으로 되어 있다.
- CLASS 유지정책은 기본값임에도 불구하고, 잘 사용되지 않는다. 컴파일러가 애노테이션의 정보를 클래스 파일에 저장할 수 있게 해주지만, 클래스 파일이 JVM에 로딩될 떄는 애노테이션의 정보가 무시되어 실행 시에 애노테이션에 대한 정보를 얻을 수 없기 때문이다.
3. @Target
@Target
- 애노테이션이 적용가능한 대상을 지정하는데 사용된다.
- 아래와 같이 @SuppressWarnings 정의를 보면, 이 애노테이션에 적용할 수 있는 대상을 @Target으로 지정한 것을 볼 수 있다.여러개의 값을 지정할 때는 괄호 { }를 사용한다.
4. @Documented
@Documented
- 애노테이션에 대한 정보가 javadoc으로 작성한 문서에 포함되도록 한다. 자바에서 제공하는 기본 애노테이션 중에 @Override, @SuppressWarnings를 제외하고는 모두 @Documented 메타 애노테이션이 붙어 있다.
5. 애노테이션 프로세서
애노테이션 프로세서
- 애노테이션 프로세서란 컴파일 시에 해당하는 어노테이션에 대한 소스 코드를 수정, 생성하는 역할을 한다. 대표적인 예로 Lombok(롬복)이 있다.
- 애노테이션 프로세서는 라운드(회차) 개념으로 작동한다. 각 라운드마다 프로세스가 가지고 있는 element를 찾으면서 처리를 시킨다.
- 아래 예제는 더 자바, 코드를 조작하는 다양한 방법 예제를 일부 가져왔다.
- 우리가 구현하고자 하는 것은 @Magic이라는 커스텀 애노테이션을 만들고, @Magic 애노테이션이 붙어있는 Moja라는 인터페이스에서 MagicMoja.class 파일을 생성해주는 코드이다.
- @Magic 이라는 커스텀 애노테이션이다.
- MagicMojaProcessor 클래스를 만든다. (중간에 javapoet등을 이용한 부분은 생략했다..)
- 이렇게 만든 패키지를 직접 사용할 Moja 인터페이스가 있는 프로젝트로 가서 의존성 주입을 해주면 에러 없이 @Magic 애노테이션을 사용할 수 있다. 그리고 컴파일 하고 나면 MagicMoja.class 파일이 생성되는 것을 볼 수 있다. 마지막으로 MagicMoja 파일을 소스 파일로 인식할 수 있게 모듈에서 바꿔주고 나면 MagicMoja를 사용할 수 있는 것을 볼 수 있다.
참고자료
'JAVA > 라이브 스터디 | whiteship' 카테고리의 다른 글
[live-study] 14주차 :: 제네릭 (0) 2021.02.27 [live-study] 13주차 :: I/O (0) 2021.02.21 [live-study] 11주차 :: Enum (0) 2021.02.15 [live-study] 10주차 :: 멀티쓰레드 프로그래밍 (0) 2021.02.15 [live-study] 9주차 :: 예외 처리 (0) 2021.02.06