일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- import 키워드
- JAVA데이터타입
- java_this
- javatime
- java 제네릭
- 생성형AI
- java스터디
- 오블완
- 티스토리챌린지
- this키워드
- java반복문
- 창의적도구
- java
- javascript
- java 애노테이션
- javautil패키지
- java super메소드
- java 패키지
- 화살표연산자
- asyncawait
- binraytree
- Java 자료구조
- java 람다식
- java objact클래스
- ai활용법
- java 메서드 오버라이딩
- gpt활용팁
- java final 키워드
- java 이진트리
- java 추상 클래스
- Today
- Total
코딩쿠의 코드 연대기
Java 애노테이션 본문
학습목표
- 애노테이션 정의하는 방법
- @retention
- @target
- @documented
- 애노테이션 프로세서
애노테이션이란?
- 소스 코드에 추가적인 정보를 제공하는 메타데이터입니다.
- 컴파일러에게 정보를 제공하거나, 런타임에 특정 동작을 수행하도록 지시할 수 있습니다.
- @ 기호로 시작하며, 클래스, 메서드, 필드 등에 붙여서 사용합니다.
애노테이션 정의하는 방법
Java에서 애노테이션을 정의하는 방법은 다음과 같습니다.
1. @interface
키워드 사용:
애노테이션을 정의하려면 @interface
키워드를 사용합니다. 이 키워드는 컴파일러에게 새로운 애노테이션 타입을 정의한다는 것을 알려줍니다.
Java
public @interface MyAnnotation {
// 애노테이션 요소들
}
2. 애노테이션 요소 정의 (선택 사항):
애노테이션은 속성과 유사한 요소를 가질 수 있습니다. 요소는 애노테이션에 정보를 추가하는 데 사용됩니다. 요소를 정의하려면 다음과 같은 규칙을 따라야 합니다.
- 요소의 타입은 기본형, String, enum, 애노테이션, Class 또는 이러한 타입의 배열만 가능합니다.
- 요소는 괄호
()
없이 선언해야 합니다. - 기본값을 지정할 수 있습니다.
Java
public @interface MyAnnotation {
String value() default "";
int number();
String[] names();
}
3. 메타 애노테이션 사용 (선택 사항):
메타 애노테이션은 다른 애노테이션에 적용되는 애노테이션입니다. Java는 @Retention
, @Target
, @Documented
, @Inherited
와 같은 몇 가지 기본 메타 애노테이션을 제공합니다.
@Retention
: 애노테이션이 유지되는 기간을 지정합니다. (SOURCE, CLASS, RUNTIME)@Target
: 애노테이션을 적용할 수 있는 요소 유형을 지정합니다. (TYPE, FIELD, METHOD, PARAMETER 등)@Documented
: 애노테이션을 javadoc에 포함할지 여부를 지정합니다.@Inherited
: 애노테이션을 하위 클래스에서 상속할지 여부를 지정합니다.
Java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
String value() default "";
int number();
String[] names();
}
예제:
Java
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface MyAnnotation {
String value() default "";
int number();
}
public class MyClass {
@MyAnnotation(value = "test", number = 10)
public void myMethod() {
// ...
}
}
위 예제에서 @MyAnnotation
은 RUNTIME
까지 유지되고 메서드에 적용될 수 있는 애노테이션입니다. value
와 number
라는 두 개의 요소를 가지고 있으며, MyClass
의 myMethod()
메서드에 적용되었습니다.
참고:
- 애노테이션은 인터페이스와 유사하지만,
interface
키워드 앞에@
기호가 붙습니다. - 애노테이션은 클래스, 메서드, 필드, 변수 등에 적용될 수 있습니다.
- 애노테이션은 컴파일 시간이나 런타임에 정보를 제공하는 데 사용됩니다.
@retention, @target, @documented
Java 애노테이션에서 @Retention
, @Target
, @Documented
는 애노테이션의 동작 방식을 지정하는 데 사용되는 중요한 메타 애노테이션입니다.
1. @Retention
- 애노테이션이 유지되는 기간을 지정합니다. 즉, 애노테이션 정보가 소스 코드, 컴파일된 클래스 파일, 런타임 중 언제까지 유지될지를 결정합니다.
RetentionPolicy
enum 값을 인자로 받습니다.RetentionPolicy.SOURCE
: 소스 코드에만 유지되고 컴파일 과정에서 제거됩니다. 컴파일러에게 정보를 제공하는 용도로 사용됩니다.RetentionPolicy.CLASS
: 컴파일된 클래스 파일에 유지되지만 런타임에는 사용할 수 없습니다.RetentionPolicy.RUNTIME
: 런타임까지 유지되어 리플렉션을 통해 애노테이션 정보에 접근할 수 있습니다.
예시:
Java
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
// ...
}
2. @Target
- 애노테이션을 적용할 수 있는 요소의 유형을 지정합니다.
ElementType
enum 값을 인자로 받습니다.ElementType.TYPE
: 클래스, 인터페이스, enumElementType.FIELD
: 필드ElementType.METHOD
: 메서드ElementType.PARAMETER
: 메서드의 파라미터ElementType.CONSTRUCTOR
: 생성자ElementType.LOCAL_VARIABLE
: 지역 변수ElementType.ANNOTATION_TYPE
: 애노테이션ElementType.PACKAGE
: 패키지ElementType.TYPE_PARAMETER
: 타입 매개변수 (Java 8 이상)ElementType.TYPE_USE
: 타입 사용 (Java 8 이상)
예시:
Java
@Target(ElementType.METHOD)
public @interface MyAnnotation {
// ...
}
3. @Documented
- 애노테이션 정보를 JavaDoc 문서에 포함시킬지 여부를 지정합니다.
- 이 애노테이션이 있는 경우 JavaDoc을 생성할 때 애노테이션 정보가 포함됩니다.
예시:
Java
@Documented
public @interface MyAnnotation {
// ...
}
요약:
@Retention
: 애노테이션 유지 기간 (SOURCE, CLASS, RUNTIME)@Target
: 애노테이션 적용 대상 (TYPE, FIELD, METHOD 등)@Documented
: JavaDoc에 포함 여부
이러한 메타 애노테이션을 사용하여 애노테이션의 동작 방식을 세밀하게 제어할 수 있습니다.
애노테이션 프로세서
Java 애노테이션 프로세서는 컴파일 과정에서 애노테이션을 처리하는 데 사용되는 강력한 도구입니다. 컴파일러에 플러그인처럼 동작하여 소스 코드에서 특정 애노테이션을 찾아내고, 그에 따라 코드를 생성하거나 수정, 검증하는 등 다양한 작업을 수행할 수 있습니다.
애노테이션 프로세서의 주요 기능:
- 코드 생성: 애노테이션 정보를 기반으로 새로운 소스 파일을 생성합니다. 예를 들어, Lombok은
@Getter
와 같은 애노테이션을 통해 getter 메서드를 생성합니다. - 코드 검증: 잘못된 애노테이션 사용이나 규칙 위반을 검출하여 컴파일 오류를 발생시킴으로써 코드를 검증합니다.
- 컴파일 타임 지원: 반복적인 작업을 자동화하여 개발자의 생산성을 높이고, 컴파일 타임에 타입 검증 및 코드 생성을 지원합니다.
애노테이션 프로세서의 장점:
- 컴파일 타임 처리: 런타임이 아닌 컴파일 타임에 동작하므로 성능 오버헤드가 없습니다.
- 코드 간결화: 보일러플레이트 코드를 줄이고 가독성을 높입니다.
- 자동화된 검증: 애노테이션 사용 규칙을 자동으로 검증하여 런타임 오류를 방지합니다.
- 유지보수성 향상: 코드 생성 및 검증을 자동화함으로써 유지보수가 쉬워집니다.
애노테이션 프로세서 사용 방법:
javax.annotation.processing.Processor
인터페이스 구현:process()
메서드를 오버라이드하여 애노테이션 처리 로직을 구현합니다.javax.annotation.processing.SupportedAnnotationTypes
애노테이션 사용: 처리할 애노테이션 타입을 지정합니다.javax.annotation.processing.SupportedSourceVersion
애노테이션 사용: 지원하는 Java 소스 코드 버전을 지정합니다.META-INF/services/javax.annotation.processing.Processor
파일 생성: 프로세서 클래스의 정규화된 이름을 파일에 명시합니다.
애노테이션 프로세서 예시 (Lombok):
Lombok은 애노테이션 프로세서를 활용하여 개발 생산성을 향상시키는 대표적인 라이브러리입니다.
Java
@Getter
@Setter
public class User {
private String name;
private int age;
}
@Getter
와 @Setter
애노테이션을 사용하면 Lombok이 컴파일 과정에서 getName()
, setName()
, getAge()
, setAge()
메서드를 자동으로 생성해줍니다.
애노테이션 프로세서 사용 방법:
AbstractProcessor
클래스 상속:process()
메서드를 오버라이드하여 애노테이션 처리 로직을 구현합니다.- 애노테이션 정의:
@SupportedAnnotationTypes
로 처리할 애노테이션을 지정하고,@SupportedSourceVersion
으로 지원할 소스 버전을 명시합니다. - 빌드 설정: Gradle 또는 Maven의
annotationProcessor
를 사용하여 애노테이션 프로세서를 등록합니다. (기존 방식인META-INF/services
파일 작성도 가능)
코드 예시 (커스텀 애노테이션 프로세서):
@SupportedAnnotationTypes("com.example.MyAnnotation")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class MyAnnotationProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (Element element : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Processing: " + element);
}
return true;
}
}
Lombok과 같은 애노테이션 프로세서의 동작 예시:
@Getter
@Setter
public class User {
private String name;
private int age;
}
이 코드는 Lombok 애노테이션 프로세서를 통해 컴파일 시 자동으로 다음과 같은 메서드를 생성합니다:
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
자주 사용되는 애노테이션 프로세서:
- Lombok:
@Getter
,@Builder
등으로 보일러플레이트 코드 제거. - Dagger: 의존성 주입을 위한 코드 생성.
- Room: SQLite 데이터베이스와의 상호작용을 위한 코드 생성.
- AutoValue: 불변 객체를 자동 생성.
애노테이션 프로세서는 코드 생성, 분석, 검증, 수정 등 다양한 작업을 자동화하여 개발 생산성을 높이는 데 기여합니다. Java 개발에서 매우 유용한 도구이므로, 적극적으로 활용해 보시기 바랍니다.
참고사항:
- 런타임 애노테이션과의 차이: 애노테이션 프로세서는 컴파일 타임에 동작하며, 런타임 리플렉션 기반 애노테이션(@Override 등)과는 다른 방식으로 사용됩니다.
- 프로세서 등록 방법: Gradle에서는
annotationProcessor
설정을 활용하여 프로세서를 쉽게 등록할 수 있습니다.
예시 (Gradle 설정):
dependencies {
annotationProcessor 'org.projectlombok:lombok:1.18.20'
}
보완 내용:
javax.annotation.processing.Processor
대신AbstractProcessor
사용 권장:- 대부분의 경우
javax.annotation.processing.AbstractProcessor
를 상속받아 사용하는 것이 더 편리합니다.AbstractProcessor
는 기본적인 메서드와 필드를 제공하여 코드 작성량을 줄여줍니다. - 따라서 "
javax.annotation.processing.Processor
인터페이스 구현" 대신 "javax.annotation.processing.AbstractProcessor
클래스 상속"을 권장합니다.
- 대부분의 경우
- 코드 수정 기능에 대한 부정확한 설명:
- 애노테이션 프로세서는 기존 소스를 직접 수정하는 방식으로 동작하지 않습니다. 대신 새로운 소스 파일을 생성하거나 컴파일 과정에서만 영향을 미치는 방식으로 작동합니다.
- 따라서 "기존 코드를 수정하거나 새로운 코드를 삽입할 수 있습니다"는 "새로운 코드를 생성하거나 컴파일 오류를 발생시켜 개발자를 돕는 데 사용됩니다"로 수정하는 것이 적절합니다.
- 애노테이션 프로세서와 런타임 애노테이션의 구분 필요:
- 애노테이션 프로세서는 컴파일 타임에 동작하며, 런타임에 동작하는 리플렉션 기반 애노테이션과는 다릅니다.
- 따라서 "컴파일 타임 처리"라는 표현을 명확히 하고, 런타임 애노테이션과의 차이점을 추가로 언급할 필요가 있습니다.
- META-INF 파일 생성 관련 최신 방식 추가:
- 최근에는
annotationProcessor
로 빌드 시스템(예: Gradle, Maven)에서 애노테이션 프로세서를 등록하는 것이 일반적입니다.META-INF/services
방식은 여전히 사용되지만, 빌드 시스템에서 더 쉽게 설정할 수 있음을 언급해야 합니다.
- 최근에는
'코딩스터디 > JAVA스터디' 카테고리의 다른 글
Java 제네릭 (1) | 2024.11.20 |
---|---|
Java) I/O (0) | 2024.11.19 |
Java) Enum (3) | 2024.11.17 |
Java 멀티쓰레드 프로그래밍 (2) | 2024.11.16 |
Java 예외 처리 (4) | 2024.11.15 |