언젠간 한번 정리하려고 했지만 이제서야 하게 됐다..
이미 만들어진 애노테이션을 많이 사용하기는 했는데 어떤방식으로 돌아가는지, 특히 런타임 중에 애노테이션이 달린 코드를 어떻게 찾아서 특정 기능을 수행하는지는 잘 몰랐다.
이번 포스팅에서는 애노테이션의 개념과 주로 활용되는 예시를 함께 정리하려고 한다.
애노테이션이란?
애노테이션은 프로그램의 코드에 추가하는 메타데이터로, 컴파일러나 런타임 시 코드를 처리하는 도구들에게 어떻게 처리해야 할지 추가적인 정보를 제공한다.
애노테이션은 Retention에 따라 다음 세 가지 용도로 활용된다.
1. 컴파일러에게 필요한 정보 제공
2. 빌드 툴이 코드를 자동으로 생성할 때 사용하는 정보 제공
3. 런타임 시 특정 기능을 처리할 때 사용하는 정보 제공(with Reflection)
애노테이션의 정의 예시
@Target({ElementType.CLASS, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation{
//애노테이션 속성
String myStr();
int myNumber default 1();
}
메타 애노테이션 - 애노테이션을 정의하기 위한 애노테이션
@Target - 애노테이션 적용 대상 명시

@Retention - 애노테이션 유지 정책 지정

@Documented - 해당 애노테이션을 javadoc에 포함
@Inherited - 애노테이션의 상속을 가능하게 함
@Repeatable - 애노테이션의 반복 사용을 가능하게 함
여기까지 자바 애노테이션의 개념에 대해 살펴보았다. 애노테이션은 필요한 코드에 꽂는 깃발 정도라고 생각하면 될 것 같은데 런타임 중에 꽂힌 깃발을 무슨 수로 찾아서 필요한 기능을 붙이는지 자세히 알아보도록 하자.
리플렉션
JVM은 클래스 정보를 클래스 로더를 통해 읽어와서 해당 정보를 JVM메모리에 저장한다. 그렇게 저장된 클래스에 대한 정보가 마치 거울에 투영된 모습과 닮아있어 리플렉션이라는 이름을 가지게 되었다.
리플렉션을 사용하면 클래스의 생성자, 메서드, 필드 등의 정보를 아주 자세히 알아낼 수 있다.
이러한 리플렉션의 원리를 이용해 특정 클래스에 붙은 애노테이션 정보를 조회할 수 있으며, 이를 통해 런타임 중 애노테이션이 달린 코드를 찾아 특정 기능을 붙일 수 있는 것이다.
물론 스프링 등 프레임워크의 애노테이션도 이러한 리플렉션의 원리를 사용한다.
리플렉션을 통해 애노테이션 정보를 얻는 과정
- 특정 클래스의 클래스나 메서드, 파라미터 정보 등을 가져온다.
- 리플렉션의 getAnnotation(s), getDeclaredAnnotation(s)등의 메서드를 사용해 원하는 애노테이션이 붙어있는지 확인한다.
- 붙어있다면 원하는 로직을 수행한다.
결론적으로 리플렉션의 원리를 통해 애노테이션 정보를 가져올 수 있다는 사실을 알 수 있었다. 마지막으로 리플렉션의 사용법을 알아보고 마무리하자.
Class 클래스
실행중인 자바 애플리케이션의 클래스와 인터페이스의 정보를 가진 클래스. Class 객체의 메서드를 호출해 특정 클래스의 여러 정보를 얻을 수 있다.
Class 객체 획득 방법

리플렉션 API의 애노테이션 정보 획득 메서드

리플렉션의 단점
Reflection API는 컴파일 시점이 아닌 런타임 시점에 클래스를 분석한다. 이에 따라 JVM을 최적화할 수 없기 때문에 성능저하가 발생하며, 일반적인 메서드 호출보다 성능이 떨어진다.
또한 코드가 지저분해지고 추상화를 파괴하는 등의 단점이 명확하기 때문에 직접 라이브러리를 만드는 등의 특수한 경우가 아니라면 리플렉션 사용을 지양해야겠다.
레퍼런스
https://www.youtube.com/watch?v=67YdHbPZJn4&ab_channel=%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC
https://steady-coding.tistory.com/614
이것이 자바다 Part.12
'Language > Java' 카테고리의 다른 글
| [Java] TreeSet에 중복된 값을 넣어야한다면? (1) | 2024.03.15 |
|---|---|
| The method sort(int[]) in the type Arrays is not applicable for the arguments (int[], Collections.reverseOrder()) (0) | 2023.11.28 |
| Arrays.fill()에 참조타입을 매개변수로 전달하면? (0) | 2023.11.25 |
| 메서드 내에서 포장객체의 값을 변경한다면? (0) | 2023.04.25 |
| Java Raw Type의 정의와 사용 시 문제점 (0) | 2023.04.03 |