1. 커스텀 어노테이션 생성
우선 컨트롤러 파라미터에 사용할 어노테이션을 정의한다.
@Target(ElementType.PARAMETER) // 파라미터에 사용
@Retention(RetentionPolicy.RUNTIME) // 런타임까지 유지
public @interface CurrentUser {
}
Java
복사
2. ArgumentResolver 구현
HandlerMethodArgumentResolver를 구현한다.
Spring Security의 SecurityContextHolder에서 인증 정보를 꺼내와서 컨트롤러 파라미터에 넘겨주는 핵심 로직이다.
@Component
public class CurrentUserArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
// 파라미터에 @CurrentUser가 붙어 있고, 타입이 User(엔티티 또는 DTO)인지 확인
return parameter.hasParameterAnnotation(CurrentUser.class) &&
parameter.getParameterType().equals(User.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// 인증 정보가 없거나 익명 사용자인 경우 null 반환
if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {
return null;
}
// Principal에 담긴 객체를 반환 (보통 UserDetails를 상속받은 객체)
return authentication.getPrincipal();
}
}
Java
복사
3. WebConfig에 Resolver 등록
Resolver 동작할 수 있도록 Spring 설정에 추가
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {
private final CurrentUserArgumentResolver currentUserArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(currentUserArgumentResolver);
}
}
Java
복사
4. 컨트롤러에서 사용
•
기존 방식
@GetMapping("/me")
public ResponseEntity<UserResponse> getMyProfile() {
// 1. SecurityContext에서 Authentication 객체를 꺼냄
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// 2. Principal 정보를 가져와서 내가 정의한 User 객체로 형변환
// (이때 익명 사용자인지, null인지 체크하는 로직이 추가되어야 함)
User user = (User) authentication.getPrincipal();
return ResponseEntity.ok(UserResponse.from(user));
}
Java
복사
•
커스텀 어노테이션 적용 방식
@RestController
@RequestMapping("/api/profile")
public class ProfileController {
@GetMapping("/me")
public ResponseEntity<UserResponse> getMyProfile(@CurrentUser User user) {
// 별도의 캐스팅이나 SecurityContext 접근 없이 바로 User 객체 사용 가능
return ResponseEntity.ok(UserResponse.from(user));
}
}
Java
복사

