클린코드 11장 시스템에서 다룬 관심사 분리를 적용합니다.
/**
* 알림함 조회
*/
@GetMapping("/messages")
public ResponseEntity<ReadFcmMessagesResponse> readFcmMessages(@Nullable @RequestParam Long lastMessageId) {
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
long userId = Long.parseLong(userDetails.getUsername());
return new ResponseEntity<>(fcmService.readMessages(userId, DEFAULT_ONE_PAGE_SIZE, lastMessageId), HttpStatus.OK);
}
/**
* 닉네임 변경
*/
@PutMapping("")
public ResponseEntity<String> updateUser(@RequestBody UpdateUserRequest request) {
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
long userId = Long.parseLong(userDetails.getUsername());
userService.updateUser(request.getNickname(), userId);
return new ResponseEntity<>("유저 업데이트 성공", HttpStatus.OK);
}
/**
* 회원 탈퇴
*/
@DeleteMapping("")
public ResponseEntity<String> deleteUser() {
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
long userId = Long.parseLong(userDetails.getUsername());
userService.deleteUser(userId);
return new ResponseEntity<>("회원 탈퇴 성공", HttpStatus.OK);
}
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
long userId = Long.parseLong(userDetails.getUsername());
“인증된 사용자 정보 추출” 이라는 관심사를 분리한다면?
→ 중복이 제거되어 변경 범위가 줄어들며, 유지보수하기 용이해 질 것입니다.
→ 책임이 명확히 분리될 것입니다.
@AuthenticationPrincipal
implements HandlerMethodArgumentResolver
@Getter
@AllArgsConstructor
public class AuthUserDTO {
private Long userId;
}
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthUser {
}
@Component
public class AuthenticationArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
boolean hasAuthUserAnnotation = parameter.getParameterAnnotation(AuthUser.class) != null;
boolean isAuthUserInfoType = parameter.getParameterType().equals(AuthUserDTO.class);
return hasAuthUserAnnotation && isAuthUserInfoType;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return new AuthUserDTO(Long.parseLong(userDetails.getUsername()));
}
}
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {
private final AuthenticationArgumentResolver authenticationArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(authenticationArgumentResolver);
}
}
/**
* 알림함 조회
*/
@GetMapping("/messages")
public ResponseEntity<ReadFcmMessagesResponse> readFcmMessages(@AuthUser AuthUserDTO authUserDTO,
@Nullable @RequestParam Long lastMessageId) {
return new ResponseEntity<>(
fcmService.readMessages(authUserDTO.getUserId(), DEFAULT_ONE_PAGE_SIZE, lastMessageId), HttpStatus.OK);
}
/**
* 닉네임 변경
*/
@PutMapping("")
public ResponseEntity<String> updateUser(@AuthUser AuthUserDTO authUserDTO,
@RequestBody UpdateUserRequest request) {
userService.updateUser(request.getNickname(), authUserDTO.getUserId());
return new ResponseEntity<>("유저 업데이트 성공", HttpStatus.OK);
}
/**
* 회원 탈퇴
*/
@DeleteMapping("")
public ResponseEntity<String> deleteUser(@AuthUser AuthUserDTO authUserDTO) {
userService.deleteUser(authUserDTO.getUserId());
return new ResponseEntity<>("회원 탈퇴 성공", HttpStatus.OK);
}