Languege/Java & Spring / / 2023. 4. 19. 22:40

스프링부트 어노테이션이란? 커스텀 어노테이션 추가하는 방법

어노테이션이란?

어노테이션은 소스 코드에 메타데이터를 추가하기 위한 것으로, 스프링부트에서는 다양한 용도로 사용됩니다.

1.스프링 빈(Bean) 등록을 위한 어노테이션
 - @Component, @Controller, @Service, @Repository 등
 - 해당 어노테이션이 붙은 클래스는 스프링 컨테이너에서 빈으로 관리됩니다.
2.의존성 주입(Dependency Injection)을 위한 어노테이션
 - @Autowired, @Resource 등
 - 해당 어노테이션이 붙은 필드나 생성자 등에 의존성 주입이 자동으로 이루어집니다.
3.스프링 MVC에서 컨트롤러(Controller)를 위한 어노테이션
 - @RestController, @RequestMapping, @GetMapping, @PostMapping 등
 - 해당 어노테이션이 붙은 클래스나 메소드는 스프링 MVC에서 컨트롤러로 동작합니다.
4.트랜잭션(Transaction) 처리를 위한 어노테이션
 - @Transactional 등
 - 해당 어노테이션이 붙은 메소드에서는 트랜잭션 처리가 자동으로 이루어집니다.

스프링부트에서 어노테이션은 다양한 기능을 사용하기 위한 필수적인 요소이며 스프링부트 개발에 있어서 개발을 하는데다양한 장점이 있습니다.

장점
1.코드의 가독성이 좋아진다.
 - 어노테이션을 사용하면 코드의 의미를 보다 명확하게 전달할 수 있습니다.
 - 예를 들어, @Autowired 어노테이션을 사용하면 해당 필드나 생성자가 어떤 의존성을 주입받는지 명확하게 알 수 있습니다.
2.개발 생산성이 향상된다.
 - 어노테이션을 사용하면 코드의 작성 양이 줄어듭니다.
 - 또한, 스프링부트에서는 어노테이션을 사용하여 설정 작업을 간소화할 수 있습니다.
3.유지보수가 쉬워진다.
 - 어노테이션을 사용하면 코드의 의미를 보다 명확하게 전달할 수 있기 때문에, 이후 유지보수하는 경우에도 코드를 이해하기 쉬워집니다.

단점
1.어노테이션의 남발로 인한 가독성 저하 가능성이 있다.
 - 어노테이션을 과도하게 사용하면 코드의 가독성이 저하될 수 있습니다. 따라서, 적절한 양의 어노테이션을 사용하는 것이 좋습니다.
2.어노테이션의 사용 방법을 정확히 알지 못하면 오류가 발생할 수 있다.
 - 어노테이션의 사용 방법을 정확히 알지 못하면, 잘못 사용하거나 누락할 수 있습니다.
 - 이 경우에는 코드의 오류가 발생할 수 있으므로, 어노테이션을 사용하기 전에 사용 방법을 꼼꼼히 파악하는 것이 중요합니다.

이런 어노테이션을 직접 만드는 방법은 어떻게 될까요?

예를 들어서 로그인된 유저의 정보를 들고오려고 할때, 아래와 같이 사용이 가능합니다.

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Login {
}

해당 어노테이션은 @Login이라는 이름으로 정의되어 있으며, ElementType.PARAMETER와 RetentionPolicy.RUNTIME이라는 두 가지 속성을 가지고 있습니다.

ElementType.PARAMETER는 해당 어노테이션을 메소드의 매개변수(Parameter)에 적용할 수 있다는 것을 의미합니다. 이러한 어노테이션을 매개변수 어노테이션이라고 부릅니다.

RetentionPolicy.RUNTIME은 해당 어노테이션이 실행 시에도 유지되어야 함을 의미합니다. 따라서, 이 어노테이션 정보를 실행 시에도 사용할 수 있습니다.

즉, 이 어노테이션은 메소드의 매개변수에 @Login을 적용하여 해당 매개변수가 로그인 정보를 나타낸다는 것을 나타내는 용도로 사용될 수 있습니다.

위와 같이 Login 어노테이션을 생성한 뒤 등록을 해야만 의미있는 어노테이션이 됩니다.

public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        boolean hasLoginAnnotation = parameter.hasParameterAnnotation(Login.class);
        boolean hasLoginUserClass = LoginUser.class.isAssignableFrom(parameter.getParameterType());

        return hasLoginAnnotation && hasLoginUserClass;
    }

    @Override
    public LoginUser resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        
        //로그인된 사용자를 가져오는 로직
        
        return result;
    }
}

 

위의 코드에서 HandlerMethodArgumentResolver를 구현한 클래스 LoginUserArgumentResolver를 생성하고, supportsParameter와 resolveArgument를 구현합니다. supportsParameter 메소드에서는 파라미터에 @Login 어노테이션이 붙어 있는지와 LoginUser 클래스를 상속하거나 구현한 파라미터인지를 체크하여, 해당 파라미터를 지원하는지 여부를 결정합니다.

resolveArgument 메소드에서는 실제로 파라미터를 바인딩합니다. 여기서는 로그인된 사용자 정보를 가져와 LoginUser 객체를 생성하여 반환합니다.

이 클래스를 등록하면, 컨트롤러 메소드에서 LoginUser 객체를 파라미터로 선언하면 자동으로 바인딩됩니다. 예를 들어 다음과 같은 메소드가 있다면,

@RequestMapping("/user")
public String userPage(@Login LoginUser user) {
    // ...
}

LoginUserArgumentResolver 클래스가 등록되어 있다면, @Login 어노테이션이 붙어 있고 LoginUser 클래스를 상속하거나 구현한 파라미터인 user 파라미터가 자동으로 resolveArgument 메소드에서 바인딩되어 전달됩니다.

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유