[인프런 워밍업 스터디 클럽] 백엔드 과제1

[질문]

  • 어노테이션을 사용하는 이유 (효과) 는 무엇일까?

    - 코드량이 감소하고 유지보수하기 쉬우며, 생산성이 증가한다.

  • 나만의 어노테이션은 어떻게 만들 수 있을까?

[ 커스텀 어노테이션 만들기 ]

예를 들어 다음과 같은 RestMemberController를 개발하여 Swagger로 문서화한다고 하자. 여기서 @Api와 @RestController 어노테이션은 다른 RestController들에도 공통적으로 적용되는데, 이를 커스텀 어노테이션으로 만들어 반복 작업을 줄여보도록 하자.

@Api
@RestController
@RequiredArgsConstructor
@RequestMapping("/member")
public class RestMemberController {

    private final MemberService memberService;
    
    @ApiOperation("멤버 목록 반환")
    @GetMapping("/list")
    public ResponseEntity<String> upload() {
        return ResponseEntity.ok(memberService.getList());
    }

}

1. 어노테이션 생성

어노테이션은 다음과 같이 인터페이스 앞에 @를 붙여서 생성할 수 있다.

public @interface RestControllerWithSwagger {
    
}

위와 같이 생성된 어노테이션은 다른 곳에서 참조되지만 아무런 기능도 하지 않는다.

 

2. 메타 어노테이션 추가

앞서 다른 어노테이션에 적용되기 위한 메타 어토네이션에 대해 살펴보았다. 그 중에서 필요한 것들을 적용하면 된다.

@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Target(ElementType.TYPE)
public @interface RestControllerWithSwagger {

}

 

위의 예제에서는 컴파일 이후에도 JVM에 의해 계속 참조가 가능하도록 @Retention(RetentionPolicy.RUNTIME) 을 적용하였으며, 하위 클래스에도 적용가능하도록 @Inherited를 적용하였다. 또한 javadoc에 의해 문서화가 되도록 @Documented를 적용하였으며, 타입 선언 시 어노테이션을 적용할 수 있도록 @Target(ElementType.TYPE)를 적용하였다. 여러 타겟을 원하는 경우에는 @Target({ElementType.TYPE, ElementType.Field}) 와 같이 사용하면 된다.

 

3. 적용할 어노테이션 추가

추가적으로 적용할 어노테이션이 있으면 추가해준다. 우리는 @Api와 @RestController라는 어노테이션을 공통으로 묶을 것이므로 이를 추가해준다.

@Api
@RestController
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Target(ElementType.TYPE)
public @interface RestControllerWithSwagger {
    String name() default "RestController";
    String value();
}

 

4. 변수 추가

어노테이션에 값을 부여하기를 원한다면 변수를 다음과 같이 선언해줄 수 있다.

@Api
@RestController
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Target(ElementType.TYPE)
public @interface RestControllerWithSwagger {
    String name() default "RestController";
    String value();
}

 

5. 적용하기

위와 같은 과정으로 어노테이션을 생성하였으면 이제 다음과 같이 적용할 수 있다.

@RestControllerWithSwagger(value = "RestMemberController", name = "RestMemberController")
@RequiredArgsConstructor
@Test1
@RequestMapping("/member")
public class RestMemberController {

    private final MemberService memberService;

    @ApiOperation("멤버 목록 반환")
    @GetMapping("/list")
    public ResponseEntity<String> upload() {
        return ResponseEntity.ok(memberService.getList());
    }

}

출처: https://mangkyu.tistory.com/130 [MangKyu's Diary:티스토리]