개발자는 기록이 답이다

🐙 Java의 어노테이션이란 무엇이고 어떻게 사용할까? 본문

언어/Java

🐙 Java의 어노테이션이란 무엇이고 어떻게 사용할까?

slow-walker 2023. 12. 22. 18:59

 

이번 포스팅은 나에게 매우 의미있는 부분이다. 면접에서 Java내에서 어노테이션의 작동원리를 제대로 말 못했기 때문이다.

Java가 아닌 Spring내에서 어노테이션이 어떻게 작동하는지를 말했다.

 

면접 3일전에 강의를 보고 어노테이션과 "리플렉션"과의 관계도 알고 있었고 1차 면접에서도 살짝 언급했었는데,

왜 2차 면접 당시 그 순간 생각이 나지 않았을까? 흝어진 조각들을 잘 정리해서 말할 수 있도록 해보자.


Java의 어노테이션이란?

 

 

어노테이션(Annotation)은 자바 프로그래밍 언어에서 코드에 부가적인 정보(메타데이터)를 부여하기 위한 방법 중 하나이다.

코드에 주석을 다는 것과 달리, 프로그램이 빌드되거나 실행될 때 활용되는 메타데이터를 제공한다.

 

Lombok으로 자주보던 "Getter"와 "RestController"를 살펴보면 어노테이션이 어떻게 구성되어있는지 쉽게 이해할 것 같다.

 

 

어노테이션의 동작원리 3단계

 

1. @interface를 사용하여 정의 : 속성, 기본값, 적용 대상을 지정할 수 있다

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
    String value() default "";
}

 

 

2. 프로그램 소스코드에서 적용 : 클래스, 메서드, 필드 등에 어노테이션을 부여하여 메타데이터를 추가한다.

public class MyClass {
    @MyAnnotation(value = "example")  // 어노테이션이 부여된 메서드
    public void myMethod() {
     ...  
    }
}

 

3. 런타임 환경에서 처리 : 프로세서나 특정 환경에서 Reflection을 통해 어노테이션 정보를 읽고 다양한 동작을 수행한다.

public class AnnotationProcessor {
    public static void processAnnotations(Class<?> clazz) {
        for (Method method : clazz.getMethods()) {
            MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
            if (myAnnotation != null) {
                System.out.println("Method: " + method.getName() + ", Annotation value: " + myAnnotation.value());
                // 여기에서 어노테이션 처리 로직 추가
            }
        }
    }
}

 

 

어노테이션은 주로 컴파일러에게 특정 작업을 수행하도록 지시하거나, 런타임에 프로그램의 동작을 변경하거나, 코드 분석 도구에게 정보를 제공하는 데 사용된다. 어노테이션은 커스텀하게 만들어 특정 기능을 수행하도록 사용자가 원하는 메타데이터를 추가할 수 있다. 또한, 어노테이션의 메타데이터는 리플렉션(reflection)을 통해 런타임에 접근할 수 있어서 동적으로 코드를 분석하거나 처리하는 데에 유용하게 사용된다.

애너테이션 종류

자바 코드에 적용되는 내장 애너테이션(표준 애너테이션)

 

  속성 타입 속성 종류 설정 방식 예시 설명
@Override
(오버라이딩)
- - @Override 해당 애노테이션을 안해도 오버라이드를 할 수 있지만,
@Override 적용하면
컴파일러 오버라이딩을
올바르게 했는지 체크
@Deprecated
(사용 안함)
- - @Deprecated 해당 요소가 더 이상
사용되지 않음을 나타냄
주로 메서드, 클래스에 사용.

@Deprecated이 붙은 대상이 사용되면 컴파일할때 -Xlint:deprecation 메시지
@SuppressWarnings
(경고 억제)
String[] "deprecation",
"unchecked",
"varargs",
"rawtypes"
@SuppressWarnings("unchecked") 컴파일러 경고를 억제하기 위한 어노테이션으로, 경고의 종류를 지정

 

메타 애너테이션(애너테이션 만들때 사용)

 

java.lang.annotation 패키지에 포함되어 있다.

종류 설정 방식 예시 속성 종류 설명
@Retention
(유지 정책)
@Retention(RetentionPolicy.RUNTIME) RUNTIME
(클래스 파일 .class에 존재
실행 시 런타임까지 사용 가능),
SOURCE
(소스파일 .java에만 존재 - 컴파일후 사라짐
클래스 파일 .class 에 존재X),
CLASS
(기본값, 클래스 파일에 존재.
실행시에 사용 불가. 잘 안씀)
유지 정책 설정
@Target
(적용 대상)
@Target(ElementType.METHOD) TYPE, FIELD, METHOD,
PARAMETER, CONSTRUCTOR,
LOCAL_VARIABLE(지역변수),
TYPE_USE(참조변수)
적용 대상을 설정
@Documented
(문서화)
@Documented - 어노테이션이 javadoc에
포함되도록 표시
@Inherited
(상속)
@Inherited - 어노테이션을 상속 가능하도록 지정
@Repeatable
(반복 가능)
@Repeatable - 어노테이션을 반복해서 적용할 수 있게 함
(JDK 1.8 이후)

 

※ 자세한 속성 종류는 다른 분이 정리를 엄청 잘해놓으셔서 여기를 참고하면 될 것 같습니다.

 

사용자 정의 어노테이션(커스텀 어노테이션)을 만들려면?

 

1. @interface 키워드 사용:용자 정의 어노테이션을 만들려면 @interface 키워드를 사용한다.

이 키워드는 인터페이스를 정의하는 것과 유사하게 보이지만, 실제로 어노테이션을 정의할 때 사용된다.

public @interface MyCustomAnnotation {
	
}


2. 속성 추가: 어노테이션에 필요한 속성을 선언할 수 있다. 속성은 추상메서드처럼 선언된다.

  • 적용 시 값을 지정하지 않으면, 사용될 수 있는 기본 값 default 지정 가능(null제외)
  • 요소가 하나이고 이름이 value일 때는, 요소의 이름 생략 가능
  • 요소의 타입이 배열인 경우, 해당 애너테이션 적용 시 괄호{}를 사용해야 한다. 
    • e.g. @Test(testTools = {"Junit", "AutoTester"})
public @interface MyCustomAnnotation {
    String value() default "기본값";
    int number();
}



3. 유지 정책 설정 및 적용 대상 지정

  • 유지 정책 설정 : 어노테이션이 어느 시점까지 유지될지를 @Retention 어노테이션을 사용하여 지정한다.
    • RetentionPolicy.RUNTIME - 런타임까지 어노테이션이 유지되어야 함을 나타낸다.
  • 적용 대상 지정 : 어노테이션을 어디에 적용할 수 있는지를 @Target 어노테이션을 사용하여 지정한다.
    • ElementType.TYPE - 클래스 타입에 어노테이션을 적용함을 나타낸다.
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomAnnotation {
    String value() default "기본값";
    int number();
}

 

4. 커스텀 애너테이션 적용

// 속성이 여러개인 경우(현재 value, number 2개)

@MyCustomAnnotation(number = 3)
public class NewClass {
    // ...
}

or

@MyCustomAnnotation(value = "다른 값", number = 3)
public class NewClass {
    // ...
}

or

// 요소가 하나이고 이름이 value일 때

@MyCustomAnnotation(3)
public class NewClass {
    // ...
}

 



🤔 느낀점

어노테이션은 리플랙션, 프록시 개념도 관련되어 있어서 포스팅 내용이 길어질 것 같다.

단순하게 어노테이션을 사용하기만하고 동작원리에 대해서 깊게 생각해보지 않았던 것 같다.


@SuppressWarnings를 통해 경고를 억제 하는 경우는 언제 사용할까? 
이미 확인했던 경고는 억제를 해주고, 새로운 경고를 놓치지 않을때 사용하는 것같다.

 

커스텀 애너테이션을 만드는건 알겠는데, 해당 애너테이션이 적용된 클래스를 갖고 특정 로직이 필요한 상황은 어떤 상황일까?

AOP를 이용해서 트랜잭션 관리나, 로깅처리를 하거나, 알림이 필요한 상황에서 커스텀 애너테이션을 사용하고, AOP내에서 로직을 처리하는걸로 이해하면 될까?

 

자바 어노테이션(@Annotation)

자바 어노테이션의 모든 것 1
자바 어노테이션의 모든 것 2

자바의 정석 - 애너테이션이란 무엇일까?

자바의 정석 - 표준 애너테이션

자바의 정석 - 메타 애너테이션

자바의 정석 - 애너테이셥 타입 정의, 요소 정리

자바 메타 어노테이션 정리 및 활용