[인프런 워밍업 클럽]BE 첫번째 과제 - annotation에 대해

hyungjunn·2024년 2월 19일
0
post-thumbnail

Annotation

일반적인 Annotation

annotatioin의 정의를 알아보자. wikipedia - Annotation을 다음과 같이 설명한다.

An annotation is extra information associated with a particular point in a document or other piece of information.

annotation은 문서나 정보의 일부분과 관련된 추가 정보이다.

쉽게 말해 어떤 것에 대한 부가 정보다.

위와 같은 표시([1])도 annotation이다.

Java annotation

그렇다면 Java에서 annotation은 어떻게 정의할까? 이것 역시 wikipedia - Java annotation에서 설명하고 있다.

In the Java computer programming language, an annotation is a form of syntactic metadata that can be added to Java source code.

자바 프로그래밍에서 annotation은 자바 소스 코드에 추가할 수 있는 구문적인 metadata의 한 형태이다.

자바 소스 코드에 대한 metadata이다. metadata라고 하면 뭔가 어렵다. 위의 내용과 대응시켜보면 자바 소스 코드에 대한 부가 정보라고 할 수 있다.

Why?

Java annotation은 왜 쓰는걸까? 실생활에서 먼저 생각해보면 바로 와닿을 수 있다.

우리는 어떠한 풍경, 인물, 장면을 한 화면에 담기 위해 디지털 카메라로 사진을 찍는다. 카메라로 촬영한 장면은 부가 정보가 있다. 촬영했을 때의 GPS, 촬영 날짜, 카메라의 기종 등등 수많은 metadata가 저장된다.

GPS를 통해 어디에서 찍었는지를 알 수 있고 이를 활용하여 찍은 장소를 알 수 있거나 같은 장소에서 찍은 또다른 사진을 검색할 수 있다. 즉, metadata를 가공하거나 분석하여 추가 정보를 얻거나 혹은 검색성을 향상시킬 수 있다.

Java에서는 어떨까? 다음 예제 코드를 통해 알아보자.

class A {

    @Deprecated
    static void methodFrist() {
        System.out.println("This is first method");
    }

    void methodSecond() {
        System.out.println("This is second method");
    }

}

class B extends A {
    @Override
    void methodSecond() {
        super.methodSecond();
    }
}

@Deprecated는 javadoc에서 다음과 같이 정의한다.

A program element annotated @Deprecated is one that programmers are discouraged from using.

프로그래머가 사용하지 못하도록 하는 것이라고 한다. 청개구리 심보로 한번 사용을 해보겠다.

다음과 같이 컴파일하기 전에 노란색의 경고가 뜬다.

@Override는 javadoc에서 다음과 같이 정의한다.

Indicates that a method declaration is intended to override a method declaration in a supertype.

supertype의 메서드 선언을 override하기 위한 것이라고 가리킨다.

위의 override한 메서드인 methodSecond의 철자를 methodSeconds로 하면??

위와 같이 @Override에 컴파일 에러가 난다.

이처럼 Java annotaiton은 자바 소스 코드에 대한 부가 정보를 알려주고 이를 통해 컴파일러가 오류를 감지하거나 이를 통해 프로그래머에게 경고를 줄 수 있다.

나만의 annotation만들기

The Java™ Tutorials 에서는 Annotation Type을 선언하는 방법을 소개한다.

중요한 코드를 그룹으로 만든다고 가정하자.

@interface ClassPreamble {
    String author();
    String date();
    int currentRevision() default 1;
    String lastModified() default "N/A";
    String lastModifiedBy() default "N/A";
    // Note use of array
    String[] reviewers();
}

위의 코드처럼 선언이 가능하다. 주요 부분을 설명하면 다음과 같다.

  • @interface : annotation type은 interface 형태로 나타낸다.

  • body 부분 : method처럼 보이는 부분. 위와 같이 선언한다.

  • default : 사용자정의에 따라 기본값도 설정할 수 있다.

@ClassPreamble(
        author = "제임스 고슬링",
        date = "02/10/2024",
        currentRevision = 1,
        lastModified = "02/19/2024",
        lastModifiedBy = "조슈아 블로크",
        reviewers = {"빌조이", "브라이언 고츠", "아서 반 호프"}
)
class GenerateCode {
	// field, method을 선언한다
}

위의 예제처럼 class선언 위에 @ClassPreamble을 선언하여 GerateCode class에 대한 부가정보를 알 수 있게 해준다.

이것 말고도 나만의 어노테이션을 만들 수 있다.

이 때, 추가적으로 알아야 하는 meta annotaiton이 있다. meta annotaion은 annotation을 설명해주는 annotation이다. @Retention@Target이다. Java Language Specification 참고

@Target

  • java.lang.annotation.Target에 위치

  • annotation type 선언에 사용된다.

  • 선언하는 annotation이 적용되는 context(범위)를 설정한다.

  • context를 지정하기 위해 java.lang.annotation.ElementType[] 유형의 단일 요소를 적용한다.

ElementType

@Target의 대상이다.

  • 패키지 선언 : java.lang.annotation.ElementType.PACKAGE

  • 타입 선언 : java.lang.annotation.ElementType.TYPE

  • 메서드 선언 : java.lang.annotatioin.ElementType.METHOD

  • 생성자 선언 : java.lang.annotation.ElementType.CONSTRUCTOR

  • gerneric class, interfaces, methods, constructors의 타입 파라미터 선언 : java.lang.annotation.ElementType.TYPE_PARAMETER

  • Field 선언 : java.lang.annotation.ElementType.FIELD

  • Formal & 예외 파라미터 선언 : java.lang.annotation.ElementType.PARAMETER

  • Local 변수 선언 : java.lang.annotation.ElementType.LOCAL_VARIABLE

@Retention

java api - RetentionPolicy

  • annotation이 달린 interface가 얼마나 annotation을 유지할 것인지 정한다.

java.lang.annotation.RetentionPolicy.SOURCE

  • source code까지만 유지

  • 컴파일하면서 annotation정보가 사라진다

  • 대표적인 annotation : lombok의 @Getter, @Setter

@Getter 가 RetentionPolicy가 SOURCE로 되어 있다. 처리 순서를 알면 왜 RetentionPolicy가 SOURCE인지 알게 된다.

  1. 게터, 세터 등등의 lombok annotation들은 파일이 실행될 때 lombok의 전처러기에 해당 메서드(ex.getNumber(), setNumber())가 생성되도록 지시한다.

  2. 컴파일타임이 실행될 때 롬복이 메서드들을 바이트코드로 생성한다.

  3. lombok annotation은 2번에서 역할을 다했기 때문에 결국 RetentionPolicy는 SOURCE까지 이면 된다.

java.lang.annotation.RetentionPolicy.CLASS

  • 클래스 파일까지만 유지

  • runtime에는 annotation정보가 사라진다

  • Java에서 default로 정해져 있다.

java.lang.annotation.RetentionPolicy.RUNTIME

  • 런타임 시점까지 유지

  • 대표적인 annotation : spring의 @Controller, @Service, @Autowired

이 @Controller, @Service, @Autowired는 Reflection api를 활용하여 런타임에 동적으로 컴포넌트 스캔이 가능해야 하기 때문에 RetentionPolicy가 RUNTIME이어야 한다.

그렇다면 이제 이 meta annotation들을 활용한 annotation을 만들어 보자.

나만의 annotation - @NeedOptimization

어떤 최적화가 필요한 메서드가 있다고 가정하자.

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface NeedOptimization {
    String reason() default "";
}

위처럼 표시할 수 있게 돼 다른 사람이 최적화가 필요한 메서드의 부가 정보를 알 수 있다.

나만의 annotation - @ApiVersion

한가지만 더 만들어 보자
API의 버전을 명시해주고 싶다고 하자. 그렇다면 다음과 같이 annotation type을 만들 수 있다.

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface ApiVerison {
    String value();
}

이렇게 Api의 버전정보를 명시해주는 annotation을 만들 수 있다.


참고

자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]의 첫번째 과제

0개의 댓글