λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
Java

[JAVA] Annotation μ–΄λ…Έν…Œμ΄μ…˜μ΄λž€?

by 상후 2024. 1. 12.
728x90
λ°˜μ‘ν˜•

πŸ‘€ Annotationμ΄λž€? (μ–΄λ…Έν…Œμ΄μ…˜, μ• λ„ˆν…Œμ΄μ…˜)

 
μ£Όμ„μ²˜λŸΌ ν”„λ‘œκ·Έλž˜λ° 언어에 영ν–₯을 λ―ΈμΉ˜μ§€ μ•ŠμœΌλ©°, μœ μš©ν•œ 정보λ₯Ό μ œκ³΅ν•œλ‹€.
 

πŸ“Œ Annotation μ—­ν• 

βœ”οΈ μ»΄νŒŒμΌλŸ¬μ—κ²Œ 문법 μ—λŸ¬λ₯Ό μ²΄ν¬ν•˜λ„λ‘ 정보λ₯Ό μ œκ³΅ν•œλ‹€.
βœ”οΈ ν”„λ‘œκ·Έλž¨μ„ λΉŒλ“œν•  λ•Œ μ½”λ“œλ₯Ό μžλ™μœΌλ‘œ 생성할 수 μžˆλ„λ‘ 정보λ₯Ό μ œκ³΅ν•œλ‹€.
βœ”οΈ λŸ°νƒ€μž„μ— νŠΉμ • κΈ°λŠ₯을 μ‹€ν–‰ν•˜λ„λ‘ 정보λ₯Ό μ œκ³΅ν•œλ‹€. (Reflection)
 

πŸ“Œ Annotation μ’…λ₯˜(ν‘œμ€€ μ–΄λ…Έν…Œμ΄μ…˜, 메타 μ–΄λ…Έν…Œμ΄μ…˜)

βœ”οΈ ν‘œμ€€ μ–΄λ…Έν…Œμ΄μ…˜ : μžλ°”μ—μ„œ 기본적으둜 μ œκ³΅ν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜
βœ”οΈ 메타 μ–΄λ…Έν…Œμ΄μ…˜ : μ–΄λ…Έν…Œμ΄μ…˜μ„ μœ„ν•œ μ–΄λ…Έν…Œμ΄μ…˜, μ–΄λ…Έν…Œμ΄μ…˜μ„ 개발 μ‹œ ν™œμš©
βœ”οΈ μ‚¬μš©μž μ •μ˜ μ–΄λ…Έν…Œμ΄μ…˜ : 메타 μ–΄λ…Έν…Œμ΄μ…˜μ„ 톡해 κ°œλ°œμžκ°€ μ›ν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜ μ •μ˜ν•˜μ—¬ ν™œμš©
 

πŸ“Œ Meta Annotation μ’…λ₯˜(메타 μ–΄λ…Έν…Œμ΄μ…˜)

πŸ” @Target

βœ”οΈ μ–΄λ…Έν…Œμ΄μ…˜μ„ μ μš©ν•  수 μžˆλŠ” λŒ€μƒμ˜ 지정에 μ‚¬μš©
@Target({TYPE, FIELD, METHOD})
public @interface TestAnnotation() {}

πŸ” @Retention

βœ”οΈ μ–΄λ…Έν…Œμ΄μ…˜μ΄ μœ μ§€(Retention) λ˜λŠ” 기간을 μ§€μ •ν•˜λŠ”λ° μ‚¬μš©
@Retention(RetentionPolicy.RUNTIME)
public @interface FunctionalInterface {}
 
❓ 의문점 : SOURCE 레벨과 CLASS λ ˆλ²¨μ€ 차이가 μ—†μ–΄ 보인닀. 뭘까?
λ‘¬λ³΅μ—μ„œ 자주 μ‚¬μš©ν•˜λŠ” @Getter 와 @NotNull μ–΄λ…Έν…Œμ΄μ…˜μ΄ μ‘΄μž¬ν•œλ‹€.
@Getter λŠ” SOURCE 레벨둜 μ •μ˜ν–ˆκ³ , @NotNull은 CLASS 레벨둜 μ •μ˜ν–ˆλ‹€.
두 κΈ°λŠ₯의 곡톡점은 JAVAνŒŒμΌμ„ CLASS 파일둜 μ»΄νŒŒμΌν•  λ•Œ νŠΉμ • μ½”λ“œλ₯Ό μ‚½μž…ν•œλ‹€λŠ” 것이닀.
 
ν•˜μ§€λ§Œ 차이점이 μ‘΄μž¬ν•˜λŠ”λ°,
SOURCE λ ˆλ²¨μ€ CLASS νŒŒμΌμ— μ–΄λ…Έν…Œμ΄μ…˜μ΄ λ‚¨μ•„μžˆμ§€ μ•Šλ‹€λŠ” 것이고
CLASS λ ˆλ²¨μ€ CLASS νŒŒμΌμ— μ–΄λ…Έν…Œμ΄μ…˜μ΄ κ·ΈλŒ€λ‘œ μœ μ§€λœλ‹€λŠ” 점이닀.
→ CLASS νŒŒμΌμ„ λ””μ»΄νŒŒμΌν•΄λ³΄λ©΄ 확인할 수 μžˆλ‹€
 
μΆ”κ°€λ˜λŠ” κΈ°λŠ₯은 κ°™κ³  그럼 μ–Έμ œ CLASS λ ˆλ²¨μ„ μ¨μ•Όν•˜λŠ”κ±ΈκΉŒ?
→ μš°λ¦¬λŠ” κ°œλ°œν•˜λ©΄μ„œ λ‹€μ–‘ν•œ jar 파일, 라이브러리λ₯Ό ν¬ν•¨ν•˜μ—¬ κ°œλ°œμ„ μ§„ν–‰ν•œλ‹€.
λΌμ΄λΈŒλŸ¬λ¦¬λŠ” λŒ€λΆ€λΆ„ jar 파일둜 κ΄€λ¦¬λ˜κ³ μžˆκ³ , ν•΄λ‹Ή jarνŒŒμΌμ—” java파일이 μ•„λ‹ˆλΌ class νŒŒμΌλ“€λ§Œ λͺ¨μ—¬μžˆλ‹€.
 
μ–΄λ…Έν…Œμ΄μ…˜μ„ ν™œμš©ν•˜μ—¬ κΈ°λŠ₯을 κ΅¬ν˜„ν•œ λΌμ΄λΈŒλŸ¬λ¦¬λ“€μ„ μ‚¬μš©ν•˜λ©΄μ„œ IDE의 κ²½κ³ λ©”μ‹œμ§€, νƒ€μž… 체크 등을 μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œ CLASS 정책이 ν•„μš”ν•œ 것이닀.
 
→ μ°Έκ³  :  https://jeong-pro.tistory.com/234

 

πŸ” @Inherited

βœ”οΈ μžμ† ν΄λž˜μŠ€μ— μƒμ†ν•˜κ³ μž ν•  λ•Œ μ‚¬μš©
@Inherited
public @interface TestAnno() {}

@TestAnno
class Parent {}
class Child extends Parent {} // Child에 μ–΄λ…Έν…Œμ΄μ…˜μ΄ λΆ™μ€κ±Έλ‘œ 인식

πŸ” @Repeatable

βœ”οΈ λ°˜λ³΅ν•΄μ„œ 뢙일 수 μžˆλŠ” μ–΄λ…Έν…Œμ΄μ…˜μ„ μ •μ˜ν•  λ•Œ μ‚¬μš©
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Todos {
   Todo[] value();
}

@Repeatable(Todos.class)
public @interface Todo {
   String value() default "";
}

@Todo("집 κ°€κΈ°")
@Todo("빨래 ν•˜κΈ°")
class MyClass {}

πŸ” @Documented

βœ”οΈ javadoc으둜 μž‘μ„±ν•œ λ¬Έμ„œμ— ν¬ν•¨μ‹œν‚€λ €λ©΄ μ‚¬μš©
 

πŸ“Œ μ‚¬μš©μž μ •μ˜ Annotation (RUNTIME)

public class Anno {

   @Target(ElementType.TYPE)
   @Retention(RetentionPolicy.RUNTIME)
   public @interface Todos {
       Todo[] value();
   }

   @Repeatable(Todos.class)
   public @interface Todo {
       String value() default "";
       int num();
   }

   @Todo(value = "집 κ°€κΈ°", num = 0)
   @Todo(value = "빨래 ν•˜κΈ°", num = 1)
   class MyClass {

   }

   public static void main(String[] args) {
       Annotation[] annotations = MyClass.class.getDeclaredAnnotations();
//        Annotation[] annotations = MyClass.class.getAnnotations();

       for (Annotation i : annotations) {
           if (i instanceof Todos) {
               Todos todos = (Todos) i;
               for (Todo todo : todos.value()) {
                   System.out.println(todo.num() + " : " + todo.value());
               }
           }
       }
   }
}
 
// 좜λ ₯
0 : 집 κ°€κΈ°
1 : 빨래 ν•˜κΈ°
 
❓ getDeclaredAnnotations() vs getAnnotations()
→ getDeclaredAnnotations : 상속 μ–΄λ…Έν…Œμ΄μ…˜(@inherited) μ œμ™Έν•˜κ³  κ°€μ Έμ˜΄
→ getAnnotations() : λ‹€ κ°€μ Έμ˜΄
 
 

πŸ“Œ μ‚¬μš©μž μ •μ˜ Annotation (SOURCE, CLASS)

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {}

 

 
@Getter둜 μ˜ˆμ‹œλ₯Ό λ“€λ©΄ 직접 JAVA νŒŒμΌμ—λŠ” getter() λ©”μ„œλ“œλ₯Ό μž‘μ„±ν•˜μ§€ μ•Šμ•˜μ§€λ§Œ, μ–΄λ…Έν…Œμ΄μ…˜μ„ 지정을 톡해 μžλ™μ μœΌλ‘œ μΆ”κ°€λ˜μ–΄ μ‚¬μš©ν•  수 μžˆλ‹€. ν•΄λ‹Ή μ›λ¦¬λŠ” 컴파일 μ‹œμ μ— μ˜λ„λœ λ™μž‘μ„ μ‚½μž…ν•˜λŠ” 것이닀.
μ»΄νŒŒμΌμ‹œμ μ— getterλ©”μ„œλ“œλ₯Ό μΆ”κ°€ν•΄μ£ΌκΈ° μœ„ν•΄μ„  Annotation Processor λΌλŠ” 것을 ν™œμš©ν•˜λ©΄ λœλ‹€.
RUNTIME 레벨이 λŸ°νƒ€μž„μ— λ¦¬ν”Œλ ‰μ…˜μ„ 톡해 μ–΄λ…Έν…Œμ΄μ…˜μ„ ν•Έλ“€λ§ν•œλ‹€λ©΄, SOURCE, CLASSλŠ” 컴파일 μ‹œμ μ— Annotation Processorλ₯Ό 톡해 ν•Έλ“€λ§ν•˜λŠ” 것이닀.
 
 
728x90
λ°˜μ‘ν˜•

λŒ“κΈ€