[Java] 어노테이션이 뭔데??
스프링을 사용하면서, 어노테이션을 자주 사용하게 되었다.
가슴 한 켠에서는 "이렇게 어노테이션 적용하면 컴터가 어떻게 알지?"라는 궁금증이 생겼다.
그래서 정리한다.
목차
- 어노테이션이란?
- 표준 어노테이션
- 메타 어노테이션
- 어노테이션 생성하기
- 모든 어노테이션의 조상
- 마커 어노테이션
- 어노테이션 규칙
- 마치며
🤔어노테이션이란?
위키백과에서는 다음과 같이 설명한다.
자바 애너테이션(Java Annotation)은 자바 소스 코드에 추가하여 사용할 수 있는 메타데이터의 일종이다. 보통 @ 기호를 앞에 붙여서 사용한다. JDK 1.5 버전 이상에서 사용 가능하다. 자바 애너테이션은 클래스 파일에 임베디드되어 컴파일러에 의해 생성된 후 자바 가상머신에 포함되어 작동한다.
음.. 이해하기 힘들다..ㅋㅋ
쉽게 이해해보자!
다음 그림을 먼저 보자.
위의 그림은 과거의 파일 관리 방법이었다.
자바 코드와 관련 설정 파일을 따로 저장하고, "ver @.@"로 구분하여 관리했다.
위와 같이 관리를 하는데 두 가지의 어려움이 있었다.
1. 사람들이 자바 코드는 변경하는데 설정 파일을 업데이트 하지 않는 어려움
- 설정과 코드가 분리되어있어, 개발에 대한 어려움
그래서 다음과 같은 관리방법을 채택하게 되었다.
이제 하나의 파일에서 코드와 설정을 관리할 수가 있던 것이다.
📌어노테이션의 종류
어노테이션에도 종류가 있다.
- 표준(내장) 어노테이션 : 자바가 기본적으로 제공해주는 어노테이션
- 메타 어노테이션 : 어노테이션을 위한 어노테이션
- 사용자정의 어노테이션 : 사용자가 직접 정의하는 어노테이션
어노테이션을 하나씩 살펴보자!
🔎표준 어노테이션
표준 어노테이션(메타 어노테이션 제외)의 종류는 다음과 같다.
- @Override
- @Deprecated
- @SuppressWarnings
📌@Override
오버라이딩을 올바르게 했는지 컴파일러가 체크한다.
Override는 오버라이딩할 때, 메서드의 이름을 잘못적는 실수를 방지해준다.
class Parent{
void parentMethod(){}
}
class Child extends Parent{
@Override
void pparentmethod(){} // 컴파일 에러! 잘못된 오버라이드 스펠링 틀림
📌@Deprecated
앞으로 사용하지 않을 것을 권장하는 필드나 메서드에 붙인다.
자바에서 메소드를 사용했는데 다음과 같이 표시된 경험이 있을 것이다.
"getDate()"
이유는 해당 메소드 상위에 @Deprecated 어노테이션이 붙어있기 때문이다.
자바의 Date 클래스의 getDate()
@Deprecated
public int getDate(){
return normalize().getDayOfMonth();
}
위의 "getDate" 메서드는 자바에서 사용하지 않을 것을 권장하는 메소드이다.
없애지 그랬니?
자바는 하위 호환성을 엄청나게 중요하게 여긴다. 이전에 해당 메소드로 개발을 진행한 프로젝트들이 있기 때문에 유지는 하되, 권장하지 않는다.
📌@FunctionalInterface
함수형 인터페이스에 붙이면, 컴파일러가 올바르게 작성했는지 체크
해당 어노테이션은, 함수형 인터페이스의 "하나의 추상메서드만 가져야 한다는 제약"을 확인해준다.
또한 함수형 인터페이스라는 것을 알려주는 역할도 한다.
📌@SuppressWarnings
컴파일러의 경고메세지가 나타나지 않게 한다.
@SuppressWarnings("unchecked")
ArrayList list = new ArrayList(); // 제네릭 타입을 지정하지 않음!
list.add(obj); // 경고 발생 !!! 경고 내용 = unchecked
위의 코드를 보자.
Array를 선언할 때 제네릭을 통해서 타입에 대한 정보를 기입하지 않았다.
그래서 타입을 선언하지 않았다는 "unchecked"라는 경고가 뜬다.
하지만 "@SuppressWarnings("unchecked)"를 입력해주었기 때문에 "unchecked"에 대한 경고는 억제된다.
보통 경고가 많을 때, 확인된 경고는 해당 어노테이션을 붙여서 새로운 경고를 알아보지 못하는 것을 방지하기 위해 사용한다.
🔎메타 어노테이션
메타 어노테이션은 어노테이션을 위한 어노테이션이다.
📌@Target
어노테이션을 정의할 때, 적용대상을 지정하는데 사용한다.
@Target({TYPE, FIELD, TYPE_USE})
@Retention(RetentionPolicy.SOURCE)
public @interface MyAnnotation{}
@MyAnnotation // 적용 대상이 Type(클래스, 인터페이스)
class MyClass{
@MyAnnotation //적용 대상이 FIELD인 경우
int i;
@MyAnnotation //적용 대상이 TYPE_USE인 경우
MyClass mc;
}
📌@Retention
어노테이션이 유지되는 기간을 지정하는데 사용
- SOURCE : 소스 파일에만 존재.
- RUNTIME : 클래스 파일에 존재. 실행시에 사용가능
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override{}
📌@Documented
javadoc으로 작성한 문서에 포함시키려면 해당 어노테이션을 붙인다.
📌@Inherited
어노테이션도 상속이 가능하다. 어노테이션을 자손 클래스에 상속하고자 할 때, @Inherited를 붙인다.
@Inherited
@interface SuperAnno{}
@SuperAnno
class Parent{}
// <- 여기에 @SuperAnno 가 붙은 것으로 인식
class Child extends Parent{}
📌@Repeatable
반복해서 붙일 수 있는 어노테이션을 정의할 때 사용
@Repeatable(ToDos.class)
@interface ToDo{
String value();
}
@ToDo("delete test codes.")
@ToDo("override inherited methods")
class MyClass{
~~
}
@interface ToDos{
ToDo[] value();
}
MyClass를 보면 "@ToDo" 어노테이션이 여러개가 정의된 것을 볼 수 있다.
@Repeatable 어노테이션은 위의 "ToDos"처럼 "컨테이너 어노테이션"도 정의해야 한다.
🔎어노테이션 생성하기
어노테이션을 생성하는 것은 매우 쉽다.
다음 코드와 같이 작성해주면 끝이다.
@interface 이름{
타입 요소 이름(); // 어노테이션의 요소를 선언
...
}
실제로 만들고, 적용해보자.
@interface DateTime{
String yymmdd();
String hhmmss();
}
@interface TestInfo{
int count() default 1;
String testedBy();
TestType testType();
DateTime testDate();
}
@TestInfo{
testedBy="Kim",
testTools={"JUnit", "AutoTester"},
testType=TestType.FIRST,
testDate=@DateTime(yymmdd="210922", hhmmss="211311")
)// count를 생략했으므로 default인 "count=1"이 적용된다.
public class NewClass{...}
그리고 추가적인 특징을 보자.
📌어노테이션 요소 특징
-
적용시 값을 지정하지 않으면, 사용될 수 있는 기본값을 지정할 수 있다.(위의 default)
-
요소가 하나이고 이름이 value일 때는 요소의 이름 생략가능하다.
@interface TestInfo{
String value();
}
@TestInfo("passed") // value="passed"와 동일
class NewClass{...}
- 요소의 타입이 배열인 경우, 괄호{}를 사용해야 한다.
@interface TestInfo{
String[] testTools();
}
@TestInfo(testTools={"JUnit", "AutoTester"})
@TestInfo(testTools="JUnit") // 요소가 1개일 때는 {}를 사용하지 않아도 된다.
@TestInfo(testTool={}) // 요소가 없으면 {}를 써넣어야 한다.
🔎모든 어노테이션의 조상
Annotation은 모든 어노테이션의 조상이지만 상속은 불가능하다.
Annotation은 모든 어노테이션의 조상이지만 상속은 불가능하다.
"Annotation"은 다음과 같이 생겼다.
public interface Annotation{
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extends Annotation> annotationType();
}
🔎마커 어노테이션
요소가 하나도 정의되지 않은 어노테이션
요소가 하나도 정의되지 않은 어노테이션
대표적으로 "@Test"가 있다.
해당 어노테이션은 테스트 프로그램에게 테스트 대상임을 알리는 어노테이션이다.
🔎어노테이션 규칙
어노테이션에도 반드시 지켜주어야 하는 규칙이 있다. 다음 4가지를 살펴보자.
- 요소의 타입은 기본형, String, enum, 어노테이션, Class만 허용된다.
- 괄호()안에 매개변수를 선언할 수 없다.
- 예외를 선언할 수 없다.
- 요소의 타입을 매개변수로 정의할 수 없다.(<T>)
잘못된 예시를 통해서 이해해보자!
@interface AnnoConfigTest{
int id = 100; // 상수 ok
String major(int i, int j) //매개변수 x
String minor() throws Exception; // 예외 x
ArrayList<T> list(); // 요소의 타입을 매개변수 x
📒마치며
오늘 어노테이션에 대해서 공부를 했다. 드디어 스프링에 존재하던 어노테이션에 대한 궁금증을 풀렸다.
하지만 ㅠ
더 완벽한 이해가 필요해 보인다. 그러기 위해서는 직접 실용적으로 사용하거나, 필요성을 느껴야 할 듯 하다. ㅋㅋ
다음에 추가적으로 사용해보면서 이 내용을 보충하고 복습하자!
🧷Reference
Author And Source
이 문제에 관하여([Java] 어노테이션이 뭔데??), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@jkijki12/annotation
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Author And Source
이 문제에 관하여([Java] 어노테이션이 뭔데??), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jkijki12/annotation저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)