찝찝하니 힘든 하루였던거 같다.
어제 댓글 달기 구현이 포스트하고 유사하여, 좀 더 흥미로운 걸 찾아다녔다.
User
Redis에 저장하기 위해 @JsonIgnore 를 추가 된 부분 ?
AuthenticatedPrincipal
구현부SRP 위반 ? 보다는 사실 분리 해볼까? ㅎㅎ
내가 레거시...
Post 와 Comment 구현하면서 인증객체가 가진 role 뿐이지만, 노출을 최소화 하면서 구현하자 생각으로 Member DTO 이용
User는 인증 객체로만 인지 되었고
서비스에서 연관관계로 조회해올 때 UserEntity 에서 role 까지 가져오는 로직이 필요 ?
내가 딱 하나 기억하는, 마틴파울러님이 리팩토링은 ... 확실할 때 ~
두 부분을 각각 분리해 봤다.
AuthenticatedPrincipal → SecurityUser
Redis → User
컨트롤러에서 SprignSecurity 의 Authentication 타입 2가지 이용
(이때쯤부터 시야가 좁아진 거 같다.)
AuthenticatedPrincipal 을 구현한 SecurityUser 자체로 getName() 은 변동사항 없었지만,
User 로의 타입 캐스팅이 문제였다.
SecurityUser securityUser = (SecurityUser)authentication.getPrincipal();
securityUser.toUser().getId();
.toUser().getId();
괜히 쓰고 싶지 않은 코드 였다…..
우선 SecurityUser.class 타입으로 형변환하고 싶다는 의미를 담아 메서드 분리하니
Class 타입으로 전달 됐다. (IDE ❤️)
clazz.cast(obj)
💕 통해서 형변환 했지만, User로의 반환이 계속 고민
IDE로 두근 대던 심장은 금세 두통이 됐다 …
캐스팅을 여러 컨트롤러에서 해줘야 하기 때문에, 클래스 분리가 좋을 거 같은데 …
정의를 어떻게 내려야 할지 …. ( 이럴 때 클래스명 짓기는 더 어렵다. )
private User toUserFrom(
Authentication authentication,
Class<SecurityUser> clazz,
Class<User> userClass) {
SecurityUser securityUser = clazz.cast(authentication);
return securityUser.toUser();
}
제네릭을 이용해서 util 성으로 분리
컨트롤러에서 호출시
User user = TypeCastingUtil.fromAndSecTo(authentication, SecurityUser.class, User.class);
TypeCastingUtils
public static <E, T> E fromAndSecTo(Object obj, Class<T> clazz, Class<E> secClass) {
return secClass.cast(fromAndTo(obj, clazz));
}
public static <T> T fromAndTo(Object obj, Class<T> clazz) {
return clazz.cast(obj); // need to object, TODO ClassCastException
}
( 나는 혼자 왜 이러고 있을까... )
컴파일 오류 집착하다가 실제 동작이 어떻게 되는지는 놓치고, 그렇게 실행하면서 에러가 발생했다.
User 를 Redis 저장 위해 쓰던 @Getter 를 AuthenticationUser 로
컨트롤러에서 TypeCastingUtils 호출부분 toAuthenticationUser 메서드로 분리
private AuthenticationUser toAuthenticationUser(Authentication authentication) {
return TypeCastingUtils.fromAndSecTo(
authentication.getPrincipal(),
SecurityUser.class,
AuthenticationUser.class);
}
AuthenticationUser으로 추상화 하면서, 메서드명이 맘에 걸리는 TypeCastingUtils fromAndSecTo 사용하지 말까 생각이 들었지만,
private AuthenticationUser toAuthenticationUser(Authentication authentication) {
SecurityUser securityUser = TypeCastingUtils.fromAndTo(authentication.getPrincipal(), SecurityUser.class);
return (AuthenticationUser)securityUser;
}
SecurityUser 가 좀 찝찝
코드로 보면 그냥 더 찝찝
public class SecurityUser implements AuthenticatedPrincipal, AuthenticationUser {
SecurityUser 가 여러 메서드 정의를 하게 된게 아닌가, 줄여볼까 싶어서 상속받아 구현 해봤습니다.
코드는 훨씬 간편해집니다.
public class SecurityUserSec extends User implements AuthenticatedPrincipal {
@Override
public String getName() {
return super.getNickname();
}
}
캐스팅 전달 파라미터도 기존보다 간편 (이상한 메서드명 안써도 된다)
AuthenticationUser user = TypeCastingUtils.fromAndTo(authentication.getPrincipal(), AuthenticationUser.class);
그렇지만 ...
User 를 상속 받는건, 어쨌든 캐싱으로 저장할 객체의 모든 역할까지 상속 받는 거고,
AuthenticationUser을 구현하는게 더 좋지 않을까 생각했습니다.
TIL … 찝찝하니.. 쉬어야 겠다.
GitHub