[인프런 워밍업 클럽(백엔드, 0기)]  - 개별 정리 : 자바 어노테이션

[인프런 워밍업 클럽(백엔드, 0기)] - 개별 정리 : 자바 어노테이션

스프링으로 프로젝트를 하면서 자바 어노테이션을 항상 사용해 왔지만 아직 잘 모르는 부분이 많은 것 같아서 1일 차에 대한 과제 제출 기간은 지났지만, 추가적으로 인프런 블로그를 통해 다시 한 번 정리해 보고자 한다.

 

(1) https://twojun-space.tistory.com/178

본인 블로그에 내용을 별도로 정리했지만 한 번 더 리마인드해 보고자 한다.

 

 

 

1. 자바 어노테이션(Java Annotation)

1-1. 정의

(1) 어노테이션은 사전적 정의로는 "주석"이라는 의미를 가지고 있지만 자바에서의 어노테이션은 소스 코드에 추가할 수 있는 일종의 메타 데이터라고 볼 수 있다.

(2) 애플리케이션 레벨에서 처리되어야 하는 대상이 아닌, 컴파일, 런타임 시점에 코드를 어떻게 처리해야 할지 알려주기 위한 정보로 볼 수 있겠다.

 

 

1-2. 장점

(1) 코드 가독성, 컴파일 시점에서의 오류 체크

  • 코드 레벨에서 동일하게 작성되기 때문에 코드의 가독성이 좋고, 일부 어노테이션의 경우 컴파일 시점에 문법 에러(아래에서 설명할 @Override, @FunctionalInterface)를 잡아주기도 한다.

 

(2) 중복 코드 제거

  • 중복되는 어노테이션의 경우 공통화시킬 수 있고 재사용이 가능하기 때문에 코드의 중복을 줄이고 효율적인 코드 작성이 가능하다.

 

(3) 커스텀 어노테이션 (사용자 정의 어노테이션) 사용 가능

  • 직접 용도에 맞게 커스텀 어노테이션을 작성할 수 있다. 프로젝트를 진행함에 따라 각각 필요한 제약사항들을 별도로 정리해서 커스텀 어노테이션 구성이 가능하다.

 

 

1-3. 단점

(1) 런타임 시 발생할 수 있는 오버헤드

  • 만약 런타임 시점에 자바의 리플렉션(Reflection) 등을 사용해서 처리되는 어노테이션이라면 이 부분을 처리하기 위한 별도의 오버헤드가 발생할 수 있다 (성능 상 문제)

 

 

 

 

2. 어노테이션의 종류

  • 살펴볼 어노테이션의 종류로 총 2가지가 있다.

(1) 표준 어노테이션(빌트 인 어노테이션)

(2) 메타 어노테이션

 

 

 

 

3. 표준 어노테이션

(1) 표준 어노테이션의 경우 자바에서 기본적으로 제공하고 있는 어노테이션이다. 대표적으로 아래와 같이 3가지가 있다.

 

3-1. @Override

(1) 현재 메서드가 부모 타입 클래스 또는 인터페이스의 메서드를 오버라이딩했음을 컴파일러에게 명시하는 역할을 수행한다. 만약 형식에 맞지 않게 오버라이딩되었다면, 컴파일러가 이를 인지하고 오류를 발생시킨다.

 

 

3-2. @Deprecated

(1) 현재 메서드를 사용하지 않도록 유도한다. 만약 해당 어노테이션이 붙은 메서드를 사용하면 컴파일러가 오류를 발생시킨다.

 

 

3-3. @FunctionalInterface

(1) 해당 인터페이스가 함수형 인터페이스임을 명시한다. 함수형 인터페이스의 경우 추상 메서드가 반드시 1개 존재해야 한다. 추상 메서드가 존재하지 않거나 2개 이상이라면 컴파일러가 오류를 발생시킨다.

 

 

 

 

4. 메타 어노테이션(Meta Annotation)

(1) 메타 어노테이션이란 다른 어노테이션에서 사용될 수 있는 어노테이션을 의미하며 아래에서 작성할 커스텀 어노테이션(사용자 정의 어노테이션)을 생성할 때 주로 사용되는 어노테이션이다.

 

 

 

4-1. @Target

(1) 어노테이션을 적용할 위치를 알려주는 어노테이션이다.

 

(2) 예를 들어 @Target(ElementType.TYPE)의 경우 해당 어노테이션을 다른 어노테이션의 대상으로 사용할 수 있다는 의미이다.

 

(3) 메타 어노테이션을 선언해 줄 때 사용되는 일반적인 방법 중 하나다.

@Target({ ElementType.PACKAGE, 			// 패키지 선언
		ElementType.TYPE, 		// 타입 선언
		ElementType.CONSTRUCTOR,        // 생성자 선언
		ElementType.FIELD, 		// 멤버 변수 선언
		ElementType.METHOD, 		// 메소드 선언
		ElementType.ANNOTATION_TYPE, 	// 어노테이션 타입 선언
		ElementType.LOCAL_VARIABLE, 	// 지역 변수 선언
		ElementType.PARAMETER, 		// 매개 변수 선언
		ElementType.TYPE_PARAMETER,	// 매개 변수 타입 선언
		ElementType.TYPE_USE 		// 타입 사용
})

 

 

4-2. @Retention

(1) @Retention의 경우 어노테이션이 적용되고 유지되는 범위를 설정하기 위해 사용되는 메타 어노테이션이다.

@Retention(RetentionPolicy.RUNTIME) // 컴파일 이후에도 JVM에 의해서 참조가 가능하다.
@Retention(RetentionPolicy.CLASS)   // 컴파일러가 클래스를 참조할 때까지 유효하다.
@Retention(RetentionPolicy.SOURCE)  // 어노테이션 정보는 컴파일 이후 없어진다.

 

 

4-3. @Inherited

(1) 해당 어노테이션이 적용된 경우 자식 클래스가 해당 어노테이션을 상속받을 수 있게 된다.

(2) 따라서 부모 클래스에 선언된 @Inherited 어노테이션은 하위 클래스에서 자동으로 상속받는다.

 

 

4-4. @Repeatable

(1) 반복 가능한 어노테이션을 정의할 때 사용될 수 있는 어노테이션이다.

 

 

 

 

5. 커스텀 어노테이션(Custom Annotation, 사용자 정의 어노테이션)

 

5-1. 정의, 사용 방법

public @interface SimpleAnnotation {
 
}

(1) 자바에서는 위와 같이 @interface 키워드를 통해 커스텀 어노테이션을 정의할 수 있다.

 

 

 

5-2. 실제로 커스텀 어노테이션 적용해 보기

@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Target(ElementType.TYPE)
@RestController
@RequestMapping("/new")
public @interface CustomMyAnnotation {

    String name() default "MemberController";
    String value();
}

 

@CustomMyAnnotation(name = "MemberController", value = "MemberController")
@RequiredArgsConstructor
public class MemberController {

    private final MemberService memberService;

    @GetMapping("/list")
    public List<MemberListResponseDto> getAllMemberList() {
        List<Member> allMemberList = memberService.findAllMembersList();

        return allMemberList.stream()
                .map(member -> new MemberListResponseDto(member))
                .collect(Collectors.toList());
    }
}

 

 

5-3. 자바의 리플렉션(Reflection)

(1) 현재 어노테이션을 사용해서 코드의 가독성이 좋아짐은 물론 어노테이션 자체가 되게 많은 일을 대신 해주고 있는 것을 확인해 볼 수 있다. 이 부분은 자바의 리플렉션 기술들이 해결해 주고 있는데 추후에 리플렉션에 관한 내용을 블로그에 다시 한 번 정리해 볼 예정이다.

 

 

  • 마지막으로 부족하지만 글을 읽어주신 분들께 감사드립니다!!

     

 

댓글을 작성해보세요.