Spring/스프링 이론

로그인 유저 어노테이션 기반으로 정보 가져오기(@AuthenticationPrincipal 커스텀)

블로그 주인장 2023. 12. 24.

로그인 유저 어노테이션 기반으로 정보 가져오기

이전에 @AuthenticationPrincipal 을 커스텀해서 어노테이션으로 정보를 가져오는 방법에 대해 알아보겠습니다.

 


 

로그인 유저 어노테이션

프로젝트의 성능 개선을 어노테이션을 이용해서 해결하는 방법이다.

 

기존 @AuthencationPrincipal 의 Principal 객체를 사용할 경우 NullException 이 발생하는 경우가 있다.

Controller 단에서 Null 체크가 아닌 커스텀으로 ArgumentResolver를 만든 후에

@LoginUser라는 어노테이션을 만들어서 개선하는 방법이다.

 

(1) @LoginUser 어노테이션 생성

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

}

 

  1. Target(ElementType.PARAMETER)
    • 어노테이션이 생성될 수 있는 위치를 지정
    • PARAMETER로 지정함으로써, 메서드의 파라미터로 선언된 객체에서만 사용 가능하다.
    • 이 외에도 클래스 선언 시 사용할 수 있는 TYPE 등이 있다.
  2. @Retention(RetentionPolicy.RUNTIME)
    • 어노테이션의 라이플 사이클 즉, 어노테이션이 언제까지 살아남아 있을지 정하는 것이다.
    • SOURCE(소스코드), CLASS(클래스파일 = 바이트 코드), RUNTIME(런타임 -> 사실상 사라지지 않는다)
  3.  @interface
    • 해당 파일을 어노테이션 클래스로 지정
    • LoginUser라는 이름을 가진 어노테이션을 사용할 수 있다.

 

(2) LoginUserArgumentResolver 생성

HandlerMethodArgumentResolver 인터페이스를 구현한 클래스이다.

HandlerMethodArgumentResolver 조건이 맞는 경우 구현체의 지정된 값을 해당 메소드의 파라미터를 넘길 수 있다.

  • supportsParameter( )
    • 컨트롤러 메서드의 특정 파라미터를 지원하는지 판단한다.
    • 파라미터에 @LoginUser 어노테이션이 붙어 있고, 파라미터의 클래스 타입이 CustomUserDetails.class 인 경우 true로 반환한다
    • 본인의 경우에는 "findMemberInfo(@LoginUser CustomUserDetails userDetails)" 이기에 CustomUserDetails.class 로 사용
    • (컨트롤러에서 @LoginUser 어노테이션의 파라미터에 따라 클래스 타입은 변화무쌍하다)
  • resolveArgument( )
    • 파라미터를 전달할 객체를 생성한다.
    • 세션의 객체를 가져온다.

 

(3) WebConfig 클래스 생성

  • HandlerMethodArgumentResolver가 스프링에 인식이 될 수 있도록 WebMvcConfigurer의 addArgumentResolvers를 이용하여 추가한다.

 

(4 - 1) @LoginUser 생성 전

@GetMapping("/member")
public ResponseEntity<?> findMemberInfo(@AuthenticationPrincipal CustomUserDetails userDetails) {
  return ResponseEntity.ok(memberService.findMember(userDetails.getUsername()));
}

 

(4 - 2) @LoginUser 생성 후

@GetMapping("/member")
public ResponseEntity<?> findMemberInfo(@LoginUser CustomUserDetails userDetails) {
  return ResponseEntity.ok(memberService.findMember(userDetails.getUsername()));
}

 

(5) 참고자료

https://loosie.tistory.com/303

 

https://jeong-pro.tistory.com/234

 

https://seokr.tistory.com/813

 

https://velog.io/@nnakki/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%84%B1%EB%8A%A5-%EA%B0%9C%EC%84%A0

 

https://velog.io/@pjh612/AuthenticationPrincipal-%EC%BB%A4%EC%8A%A4%ED%85%80%ED%95%B4%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

반응형

댓글