일단, 블로그 포스팅을 잠깐 쉬면서, 코드를 다시 한번 돌아보았다.
좌충우돌 만드는 게시판 수준이라지만, 그래도 나름 '생각' 이라는 것을 해보면서 쓰고있다.
+ 플레이리스트에 아이묭(aimyon) 노래를 틀면서 하기 시작했는데, 기존에 듣던 재즈보다 힘차게 하는 느낌이다(TMI)
기존에, 회원가입 로직을 위해서
Member -> MemberRepository(+MemberCustomRepository) -> MemberService -> MemberController
RefreshToken -> RefreshTokenRepository -> RefreshTokenServie -> RefreshTokenController
로 만들려던 계획을 조금 수정했다.
DDD라는 것을 조금 찾아보면서, Member, Refresh라는 도메인이 같이 움직일 때는 하나로 움직이고, 따로 움직일 건 따로 움직이는 식으로, 나눠 놓았으면 나중에 편하게 합쳐쓰면 되는데 그러지 못한 느낌이 들었기 때문이다.
(아직 공부중이고, 머리속으로 정립되지 않은 개념이라 자세하게 쓰고 있지는 않다.)
그래서 결과는,
MemberService = Member 도메인, AuthService = Member 도메인 + RefreshToken 도메인 의 방식으로 합치게 되었다.
결국, auth의 기능은, 회원가입 + 로그인 + 토큰 재발행 정도가 될 것 같다.
이러한 방식으로 서비스를 리펙토링했다.
이렇게 만들면서 고민이 생겼었다.
auth = 회원가입 중에 아이디, 닉네임, 이메일, 비밀번호를 검증해야 한다.
member = 회원의 데이터 수정 중에 닉네임, 이메일, 비밀번호를 검증해야 한다.
이 두개가 공통적인 부분을 가지게 되었다.
그래서 간단하게 멤버의 인스턴스를 검증하는 클래스를 만들어주었다.
public void validateRegisterRequest(RegisterRequestDto registerRequestDto){
validateUsername(registerRequestDto.getUsername());
validateNickname(registerRequestDto.getNickname());
validateEmail(registerRequestDto.getEmail());
validatePasswordCheck(registerRequestDto.getPassword(), registerRequestDto.getPasswordCheck());
}
public void validateSignInRequest(SignInRequestDto signInRequestDto){
Member member = memberRepository.findByUsername(signInRequestDto.getUsername())
.orElseThrow(MemberNotFoundException::new);
if(!passwordEncoder.matches(signInRequestDto.getPassword(), member.getPassword()))
throw new PasswordNotMatchingException();
}
public void validateUsername(String username){
if(memberRepository.findByUsername(username).isPresent())
throw new UsernameAlreadyInUseException();
}
public void validateNickname(String nickname){
if(memberRepository.findByNickname(nickname).isPresent())
throw new NicknameAlreadyInUseException();
}
public void validateEmail(String email){
if(memberRepository.findByEmail(email).isPresent())
throw new EmailAlreadyInUseException();
}
public void validatePasswordCheck(String password, String passwordCheck){
if(!password.equals(passwordCheck)){
throw new PasswordNotMatchingException();
}
}
public void validateWithCurrentPassword(ChangePasswordRequestDto changePasswordRequestDto, String currentPassword){
if(passwordEncoder.matches(changePasswordRequestDto.getNewPassword(), currentPassword))
throw new PasswordNotChangedException();
}
기존에 있던 아이디, 닉네임, 이메일, 비밀번호 검증 로직을 그대로 가져왔다.
추가로, 회원가입 때 필요한 것들끼리 모아서 회원가입 요청 검증을 만들었다.
이후,
AuthService, MemberService 모두
@PostConstruct
private void setValidator(){
memberInstanceValidator = new MemberInstanceValidator(memberRepository, passwordEncoder);
}
이런 메서드를 만들어주었다.
이를 통해, Validator의 인스턴스를 초기화 시켜줄 수 있다.
AuthService의 내부 로직은
@Transactional
public void registerNewMember(RegisterRequestDto registerRequestDto){
memberInstanceValidator.validateRegisterRequest(registerRequestDto);
registerRequestDto.setPassword(passwordEncoder.encode(registerRequestDto.getPassword()));
Member member = new Member(registerRequestDto);
memberRepository.save(member);
}
@Transactional
public TokenResponseDto signIn(SignInRequestDto signInRequestDto){
Authentication authentication = getAuthenticationToSignIn(signInRequestDto);
return createTokenDtoByAuthentication(authentication);
}
@Transactional
public TokenResponseDto reissue(ReissueRequestDto req) {
validateRefreshToken(req);
RefreshToken refreshToken = refreshTokenRepository.findByKey(getAuthentication(req).getName())
.orElseThrow(LogOutMemberException::new);
validateTokenInfo(refreshToken, req);
TokenDto tokenDto = tokenProvider.generateTokenDto(getAuthentication(req));
refreshToken.updateValue(tokenDto.getRefreshToken());
return new TokenResponseDto(tokenDto);
}
이렇게 회원가입, 로그인, 토큰 재발행을 넣었다.
(부수적인 메서드들은 기존 게시글 중TokenDto, MemberService, JWT부분들을 참고하면 될 것 같다. )
이에 따라 테스트도 수정해주었다(이걸 다시 다 해보는게, 귀찮을 수 있지만 개인적으로는 노가다같더라도 해보는걸 추천한다. 나도 아직 테스트를 잘 한다곤 못하지만, 계속 쓰다보니, 다양한 기능들을 클래스를 하나씩 뜯어보며 쓸 수 있게 된다는 느낌이 든다.)
서비스 로직을 그대로 가지는 컨트롤러 로직도 만들고있다.
AuthController의 register, sign_in, reissue 순서로 게시글을 분리해서 올려야 할 것 같다.
컨트롤러의 로직 자체는 만드는 데에 문제가 없었지만, 테스트를 만들어보고, 테스트에 통과되게 문제를 하나씩 고치는 과정이 재미있다.
(그니까 테스트 만들자. 여러분들 테스트는 최고존엄이신거시다. )
'스프링 공부 > 게시판 프로젝트 만들기' 카테고리의 다른 글
[스프링] 35. AuthController.reissue 테스트부터 프로젝트 코드까지 (0) | 2023.02.20 |
---|---|
[스프링] 34. AuthController.signIn을 테스트해보자. (0) | 2023.02.20 |
[스프링] 32. MemberController.register 중복과 기타사유의 예외 테스트 (0) | 2023.02.12 |
[스프링] 31. MemberController-회원가입 기능 구현하기, Null/Success 테스트 (0) | 2023.02.12 |
[스프링] 30. MemberRepositoryTest_Search_Contains에서 검색조건이 서로 다른 객체를 향하는 거라면 잘될까 (0) | 2023.02.10 |