[Java] Annotation

2024. 10. 10. 15:19·Java
728x90
반응형

애노테이션 정의

애노테이션은 해석 가능한 주석이라고 생각하면 편하다. 일반 주석과 달리, 애노테이션은 컴파일러나 런타임에서 해석될 수 있는 메타데이터를 제공한다. 즉, 애노테이션은 코드에 메모를 달아놓는 것처럼 특정 정보나 지시를 추가하는 도구로, 코드에 대한 메타데이터를 표현하는 방법이다.
=> 애노테이션은 코드에 대한 추가적인 정보를 주석처럼 달아놓는 것이고, 이는 컴파일러나 런타임에 사용된다


예시 코드

@Retention(RetentionPolicy.RUNTIME)
public @interface AnnoElement {
  String value();

  int count() default 0;

  String[] tags() default {};

  //MyLogger data(); // 다른 타입은 적용X

  Class<? extends MyLogger> annoData() default MyLogger.class; // 클래스 정보는 가능
}

애노테이션 정의 규칙

  • 데이터 타입
    • 기본 타입 (int, float, boolean 등)
    • String
    • Class (메타데이터) 또는 인터페이스
    • enum
    • 다른 애노테이션 타입
    • 위의 타입들의 배열
    • 앞서 설명한 타입 외에는 정의할 수 없다. 쉽게 이야기해서 일반적인 클래스를 사용할 수 없다.
  • default 값
    • 요소에 default 값을 추가할 수 있다
    • ex) String value() default "기본값";
  • 요소 이름
    • 메서드 형태로 정의된다
    • 괄호를 포함하되 매개변수는 없어야 한다.
  • 반환 값
    • void를 반환 타입으로 사용 불가
  • 예외
    • 예외를 선언할 수 없다
  • 특별한 요소 이름
    • value라는 이름의 요소를 하나만 가질 경우, 애노테이션 사용 시 요소 이름을 생략할 수 있다

애노테이션 사용 예시

@AnnoElement(value = "data", count = 10, tags = {"t1", "t2"})
public class ElementData1 {

}
public class ElementData1Main {
  public static void main(String[] args) {
    Class<ElementData1> annoClass = ElementData1.class;
    AnnoElement annotation = annoClass.getAnnotation(AnnoElement.class);

    String value = annotation.value();
    System.out.println("value = " + value);

    int count = annotation.count();
    System.out.println("count = " + count);

    String[] tags = annotation.tags();
    System.out.println("tags = " + Arrays.toString(tags));
  }
}
  • annoClass.getAnnotation(AnnoElement.class): 클래스 메타데이터를 통해 특정 애노테이션 정보를 조회할 수 있다.
  • annotation 정보 조회 후, 애노테이션에 지정된 값을 메서드 호출을 통해 조회할 수 있다.

메타 애노테이션

: 애노테이션을 정의하는데 사용하는 특별한 애노테이션

  • @Retention: 애노테이션의 생존 기간을 지정한다.
    • RetentionPolicy.SOURCE: 소스 코드에만 남아잇다. 컴파일 시점에 제거된다 (= 진짜 주석 같은 느낌)
    • RetentionPolicy.CLASS: 컴파일 후 class 파일까지는 남아있지만 자바 실행 시점에 제거된다. (기본값)
    • RetentionPolicy.RUNTIME: 자바 실행 중에도 남아있다. 대부분 이 설정을 사용한다.
  • @Target: ElementType을 인자로 넘겨주어 애노테이션을 적용할 수 있는 위치를 지정한다.
      public enum ElementType {
        TYPE,
        FIELD,
        METHOD,
        PARAMETER,
        CONSTRUCTOR,
        LOCAL_VARIABLE,
        ANNOTATION_TYPE,
        PACKAGE,
        TYPE_PARAMETER,
        TYPE_USE,
        MODULE,
        RECORD_COMPONENT;
      }
    • 주로 TYPE, FIELD, METHOD를 사용한다.
  • @Documented: 자바 API 문서를 만들 때 해당 애노테이션이 함께 포함되는지 지정한다. 보통 함께 사용한다.
  • @Inherited: 자식 클래스가 애노테이션을 상속 받을 수 있다.

적용 예시)

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Documented
public @interface AnnoMeta {
}

애노테이션과 상속

  • 모든 애노테이션은 java.lang.annotation.Annotation 인터페이스를 묵시적으로 상속 받는다.
  • 모든 애노테이션은 기본적으로 Annotation 인터페이스르 확장하며, 이로 인해 자바에서 애노테이션은 특별한 형태의 인터페이스로 간주된다.
    • 하지만 자바에서 애노테이션을 정의할 때, 개발자가 명시적으로 Annotation 인터페이스를 상속하거나 구현할 필요는 없다.
    • @interface 키워드를 통해 정의하면, 자바 컴파일러가 자동으로 Annotation 인터페이스를 확장하도록 처리해준다.
    • public @interface MyAnnotation {} -> public interface MyAnnotation extends java.lang.annotation.Annotation {}
  • 애노테이션과 상속
    • 애노테이션은 다른 애노테이션이나 다른 인터페이스를 직접 상속할 수 없다. -> 애노테이션 사이에는 상속이라는 개념이 없다.
    • 오직 java.lang.annotation.Annotation 인터페이스만 상속한다.

@Inherited

애노테이션끼리는 상속을 할 수 없지만, 애노테이션을 적용한 클래스들의 상속은 자유이다. Parent 클래스에서 애노테이션을 붙이면, 이를 상속한 Child 클래스는 해당 애노테이션의 영향을 받을까?


애노테이션을 정의할 때 @Inherited 메타 애노테이션을 붙이면, 애노테이션을 적용한 클래스의 자식도 해당 애노테이션을 부여받을 수 있다.
즉, Parent가 @Inherited가 붙은 애노테이션을 사용 중이라면, Child 클래스도 해당 애노테이션을 부여받는다.


단, 주의할 점으로 이 기능은 클래스 상속에서만 작동하고, 인터페이스의 구현체에는 적용되지 않는다. 그 이유는 다음과 같다. - **클래스 상속과 인터페이스 구현의 차이** - 인터페이스는 메서드의 시그니처만을 정의할 뿐, 상태나 행위를 가지지 않기 때문에, 인터페이스의 구현체가 애노테이션을 상속한다는 개념이 잘 맞지 않는다. - 구현과 상속은 다르다 - **인터페이스와 다중 구현, 다이아몬드 문제** - 인터페이스는 다중 구현이 가능하다. 만약 인터페이스의 애노테이션을 구현 클래스에서 상속하게 되면, 여러 인터페이스의 애노테이션 간의 충돌이나 모호한 상황이 발생할 수 있다.

자바 기본 애노테이션

앞서 확인해본 메타 애노테이션 말고도 코드에 직접 사용할 수 있는 자바 언어가 기본으로 제공하는 애노테이션도 있다.

  • @Override
      @Target(ElementType.METHOD)
      @Retention(RetentionPolicy.SOURCE)
      public @interface Override {
      }
    • 메서드 재정의가 정확하게 잘 되었는지 컴파일러가 체크하는데 사용한다.
  • @Deprecated
      @Documented
      @Retention(RetentionPolicy.RUNTIME)
      @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE,
      PARAMETER, TYPE})
      public @interface Deprecated {
          String since() default "";
          boolean forRemoval() default false;
      }
    • @Deprecated` 는 더 이상 사용되지 않는다는 뜻이다. 이 애노테이션이 적용된 기능은 사용을 권장하지 않는다.
    • 인자
      • since: 더 이상 사용하지 않게 된 버전 정보
      • forRemoval: 미래 버전에 코드가 제거될 예정
  • @SuppressWarnings
      @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
      @Retention(RetentionPolicy.SOURCE)
      public @interface SuppressWarnings {
      String[] value();
      }
    • 이름 그대로 경고를 억제하는 애노테이션이다. 자바 컴파일러가 문제를 경고하지만, 개발자가 해당 문제를 잘 알고 있기 때문에, 더는 경고하지 말라고 지시하는 애노테이션이다.
    • 사용되는 대표적인 값
      • all: 모든 경고를 억제
      • deprecation: 사용이 권장되지 않는(deprecated) 코드를 사용할 때 발생하는 경고를 억제
      • unchecked: 제네릭 타입과 관련된 unchecked 경고를 억제
      • serial: Serializable 인터페이스를 구현할 때 serialVersionUID 필드를 선언하지 않은 경우 발생하는 경고를 억제
      • rawtypes: 제네릭 타입이 명시되지 않은(raw) 타입을 사용할 때 발생하는 경고를 억제
      • unused: 사용되지 않는 변수, 메서드, 필드 등을 선언했을 때 발생하는 경고를 억제

스프링에서의 애노테이션(with 리플렉션)

스프링은 리플렉션과 애노테이션을 활용하여 다음의 마법 같은 기능들을 제공한다

  • 의존성 주입: 스프링은 리플렉션을 사용하여 객체의 필드나 생성자에 자동으로 의존성을 주입한다. 개발자는 단순히 @Autowired 애노테이션만 붙이면 된다.
  • ORM: JPA는 애노테이션을 사용하여 자바 객체와 데이터베이스 테이블 간의 매핑을 정의한다. 예를 들어, @Entity , @Table , @Column 등의 애노테이션으로 객체-테이블 관계를 설정한다
  • AOP: 스프링은 리플렉션을 사용하여 런타임에 코드를 동적으로 주입하고, @Aspect , @Before , @After 등의 애노테이션으로 관점 지향 프로그래밍을 구현한다.
  • 설정의 자동화: @Configuration,@Bean` 등의 애노테이션을 사용하여 다양한 설정을 편리하게 적용한다.
  • 트랜잭션 관리: @Transactional 애노테이션만으로 메서드 레벨의 DB 트랜잭션 처리가 가능해진다.
728x90
반응형

'Java' 카테고리의 다른 글

[Java] 자바 기본 개념 정리 (기본 문법 제외)  (2) 2025.01.02
[Java] Garbage Collection  (3) 2025.01.02
[Java] JVM / JRE / JDK  (3) 2025.01.01
[Java] Reflection  (0) 2024.10.10
[Java] I/O  (0) 2024.10.10
'Java' 카테고리의 다른 글
  • [Java] Garbage Collection
  • [Java] JVM / JRE / JDK
  • [Java] Reflection
  • [Java] I/O
mxruhxn
mxruhxn
소소하게 개발 공부 기록하기
    반응형
    250x250
  • mxruhxn
    maruhxn
    mxruhxn
  • 전체
    오늘
    어제
    • 분류 전체보기 (152)
      • Java (21)
      • Spring (6)
      • Database (13)
      • Operating Syste.. (1)
      • Computer Archit.. (0)
      • Network (24)
      • Data Structure (6)
      • Algorithm (11)
      • Data Infra (7)
      • DevOps (12)
      • ETC (27)
      • Project (21)
      • Book (1)
      • Look Back (1)
  • 블로그 메뉴

    • 링크

      • Github
    • 공지사항

    • 인기 글

    • 태그

    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.0
    mxruhxn
    [Java] Annotation
    상단으로

    티스토리툴바