커스텀 어노테이션(Custom Annotation)은 개발자가 정의한 어노테이션으로, Java에서 특정한 기능을 수행하기 위해 사용하는 메타데이터다. 기본적으로 Java는 여러 내장 어노테이션(예: @Override, @Deprecated, @Entity 등)을 제공하지만, 개발자가 필요에 맞게 새로운 어노테이션을 정의하여 사용할 수 있다.
커스텀 어노테이션의 정의와 사용
어노테이션 정의
커스텀 어노테이션을 정의하려면 @interface 키워드를 사용한다.
예시 : 사용자가 정의한 @UserId 어노테이션
@Target(ElementType.PARAMETER) // 어노테이션이 적용될 위치
@Retention(RetentionPolicy.RUNTIME) // 어노테이션의 유지 기간
public @interface UserId {
// 필드나 메서드를 정의할 수도 있음
}
@interface: 어노테이션을 정의할 때 사용@Target: 이 어노테이션이 어디에 적용될 수 있는지 지정(ElementType.PARAMETER,ElementType.METHOD,ElementType.FIELD등)@Retention: 어노테이션이 어느 시점까지 유지될지를 지정 (RUNTIME은 실행 시점에 어노테이션을 사용할 수 있도록 설정)
어노테이션 종류
1️⃣ @Target: 어노테이션 적용 대상을 지정
@Target 어노테이션은 어노테이션이 어디에 적용될 수 있는지를 명시하는 메타 어노테이션
즉, 어노테이션이 적용될 대상 요소를 정의한다.
| 주요 값 | 설명 |
|---|---|
ElementType.TYPE |
클래스, 인터페이스, 열거형 등 클래스 타입에 적용 |
ElementType.METHOD |
메서드에 적용 |
ElementType.FIELD |
필드에 적용 |
ElementType.PARAMETER |
매개변수에 적용 |
ElementType.CONSTRUCTOR |
생성자에 적용 |
ElementType.LOCAL_VARIABLE |
지역 변수에 적용 |
ElementType.ANNOTATION_TYPE |
다른 어노테이션 타입에 적용 |
ElementType.PACKAGE |
패키지에 적용 |
예시:
@Target(ElementType.METHOD)
public @interface MyMethodAnnotation {
// 메서드에만 적용되는 어노테이션
}
2️⃣ @Documented: Javadoc 문서화 포함
@Documented는 어노테이션이 Javadoc 문서에 포함될 수 있도록 지정하는 메타 어노테이션. 어노테이션이 붙은 어노테이션은 Javadoc 문서화 대상에 포함된다.
| 용도 | 설명 |
|---|---|
| 어노테이션이 Javadoc 문서화 대상에 포함되도록 함 | 해당 어노테이션이 붙은 클래스나 메서드는 Javadoc 문서화 시 포함되어 API 문서에 명확히 나타남 |
예시:
@Documented
@Target(ElementType.TYPE)
public @interface MyDocumentedAnnotation {
String description() default "Documentation enabled for this annotation.";
}
3️⃣ @Inherited: 상속 가능 어노테이션
@Inherited는 어노테이션이 하위 클래스에 상속되도록 한다. 부모 클래스에 적용된 어노테이션이 자식 클래스에서 자동으로 상속되어, 자식 클래스도 동일한 어노테이션을 가지게 된다.
| 용도 | 설명 |
|---|---|
| 상속을 통해 어노테이션을 전파 | 부모 클래스에서 정의된 어노테이션을 자식 클래스가 상속받음 |
예시:
@Inherited
@Target(ElementType.TYPE)
public @interface MyInheritedAnnotation {
String value() default "Inherited annotation";
}
@MyInheritedAnnotation
class ParentClass {}
class ChildClass extends ParentClass {
// ParentClass에서 상속된 @MyInheritedAnnotation이 자동으로 적용됨
}
4️⃣ @Retention: 어노테이션의 유지 기간
@Retention은 어노테이션이 어떤 시점까지 유지될지를 정의하는 메타 어노테이션입니다. 어노테이션이 컴파일 후, 런타임까지 유지될지 등을 설정할 수 있다.
| 주요 값 | 설명 |
|---|---|
RetentionPolicy.SOURCE |
소스 코드에서만 유지되고, 컴파일 시에 제거됩니다. |
RetentionPolicy.CLASS |
클래스 파일에서만 유지되고, 런타임에서는 제거됩니다. |
RetentionPolicy.RUNTIME |
런타임까지 유지됩니다. 리플렉션을 통해 어노테이션에 접근 가능합니다. |
예시:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyRuntimeAnnotation {
String value() default "Runtime annotation";
}
5️⃣ @Repeatable: 어노테이션 반복 적용
@Repeatable은 어노테이션을 여러 번 적용할 수 있도록 허용하는 메타 어노테이션입니다. 자바 8부터 도입된 기능으로, 동일한 요소에 대해 여러 번 동일한 어노테이션을 적용할 수 있게 해줍니다.
| 용도 | 설명 |
|---|---|
| 동일한 요소에 대해 동일한 어노테이션을 여러 번 적용 | @Repeatable을 사용하여 여러 개의 동일한 어노테이션을 하나의 요소에 적용 가능하게 함 |
예시:
@Repeatable(MyAnnotations.class)
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyRepeatableAnnotation {
String value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotations {
MyRepeatableAnnotation[] value();
}
public class Example {
@MyRepeatableAnnotation("First")
@MyRepeatableAnnotation("Second")
public void myMethod() {
// 두 개의 @MyRepeatableAnnotation이 적용됨
}
}
☑️ 메타 어노테이션 요약
| 어노테이션 | 설명 |
|---|---|
@Target |
어노테이션이 적용될 수 있는 대상 지정. |
@Retention |
어노테이션이 유지되는 기간 정의. |
@Documented |
어노테이션을 Javadoc 문서에 포함시킴. |
@Inherited |
부모 클래스에서 정의된 어노테이션을 자식 클래스에 상속. |
@Repeatable |
동일한 요소에 대해 어노테이션을 여러 번 적용할 수 있도록 허용. |
어노테이션의 메타데이터 구성
커스텀 어노테이션을 정의할 때, 어노테이션에 속성(Attribute)을 추가할 수 있다. 속성은 메서드 형식으로 정의되며 기본값을 설정할 수 있다.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LogExecutionTime {
String value() default "Method execution time:"; // 기본값
}
이 어노테이션은 메서드 실행 시간을 로그로 출력하기 위한 것으로, value라는 속성을 가지고 있다.
어노테이션 처리
커스텀 어노테이션을 사용하려면, 해당 어노테이션을 처리하는 로직을 구현해야 한다. 보통 Java에서는 Reflection을 사용하여 어노테이션을 처리하는데, Spring AOP나 Custom Annotation Processors와 같은 도구를 사용해서 구현하는 방법도 있다.
☑️ AOP와 결합한 커스텀 어노테이션
해당 아티클을 참고해서 AOP와 결합한 사용자 정의 어노테이션을 통해 로깅하는 방법을 참고하면 된다.
(노션 페이지로 넘어갑니다.)
Spring에서는 AOP(Aspect-Oriented Programming)를 사용하여 커스텀 어노테이션을 처리할 수 있다. 예를 들어, @LogExecutionTime 어노테이션이 적용된 메서드를 호출할 때, 실행 시간을 로깅하는 AOP를 설정할 수 있다.
@Aspect
@Component
public class LogExecutionTimeAspect {
@Around("@annotation(logExecutionTime)") // @LogExecutionTime 어노테이션을 처리
public Object logExecutionTime(ProceedingJoinPoint joinPoint, LogExecutionTime logExecutionTime) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long end = System.currentTimeMillis();
System.out.println(logExecutionTime.value() + " " + (end - start) + "ms");
return result;
}
}
이 코드는 @LogExecutionTime 어노테이션이 적용된 메서드가 호출될 때마다 실행 시간 차이를 계산하여 로그로 출력한다.
커스텀 어노테이션의 활용 사례
| 목적 | 설명 | 예시 |
|---|---|---|
| 보안 | JWT 토큰에서 userId를 추출하여 인증된 사용자 정보를 처리하는 어노테이션 작성 |
@UserId 어노테이션을 사용하여 컨트롤러 메서드에서 인증된 사용자의 ID를 자동으로 주입 |
| 로깅 | 메서드 실행 시간과 입출력 값을 로깅하여 애플리케이션 성능을 모니터링 | 메서드 실행 시간 및 입출력 값 로깅을 위한 커스텀 어노테이션 작성 |
| 트랜잭션 관리 | @Transactional 어노테이션과 유사하게 커스텀 트랜잭션 처리를 비즈니스 로직에 적용 |
@CustomTransactional 어노테이션을 사용하여 트랜잭션 처리 |
| 검증 | 특정 조건을 만족하는지 확인하는 검증 어노테이션을 작성하여 필드나 메서드에 유효성 검사 자동 적용 | @ValidValue 어노테이션을 사용하여 필드의 유효성 검사 자동화 |
'Backend > Spring' 카테고리의 다른 글
| 동시성 제어 방법 총 정리 (0) | 2025.05.22 |
|---|---|
| AWS SDK v1 기반 S3 이미지 업로드 구현 (Spring Boot 연동 포함) (0) | 2025.05.13 |
| 공통 관심 사항 - Filter, Intercepter, AOP (1) | 2025.04.21 |
| 회원 탈퇴를 구현하며 겪은 Soft Delete 설계와 Jackson의 LocalDateTime 직렬화 문제 (0) | 2025.04.11 |
| Helper Class (0) | 2025.04.02 |