[JPA Self Study] AccountController Refactoring
SpringBootJpa 개발 | 5 DAY - 1
하다가 막히는 부분이나 알아야 할 사항, 혹은 버전의 문제 등을 적기 위한 간단한 노트이며
이는 공부용 소스이기 때문에 소스에 주석을 달아가며 설명을 적어뒀습니다.
따라서 해당 날짜의 소스를 보며 노트를 참고하는 식으로 봐야합니다.
소스는 깃헙에 올려놓았습니다.
1. AccountEmailAthenticate
- About Repository
repository를 도메인 계층으로 보느냐 ayer계층(controller,service,dao..)으로 보느냐에 따라 repository를 controller에서 쓰는 것에 대한 논의가 많은데 여기선 도메인게층으로 보고 controller에서 사용하겠습니다.
- Token is NPE ( Transaction Issue )
Email을 통해 Token을 인증하는 과정에서 DB에 저장된 내 정보에 Token이 없어서 문제가 생겼습니다.
문제가 생긴 로직입니다.
1. processNewAccount
public void processNewAccount(SignUpForm signUpForm) {
Account newAccount = saveNewAccount(signUpForm);
newAccount.generateEmailCheckToken();
sendSignUpConfirmEmail(newAccount);
}
2. saveNewAccount
private Account saveNewAccount(SignUpForm signUpForm) {
Account account = Account.builder()
.email(signUpForm.getEmail())
.nickname(signUpForm.getNickname())
.password(passwordEncoder.encode(signUpForm.getPassword()))
.studyCreatedByWeb(true)
.studyEnrollmentResultByWeb(true)
.studyUpdatedByWeb(true)
.build();
return accountRepository.save(account);
}
3. sendSignUpConfirmEmail
private void sendSignUpConfirmEmail(Account newAccount) {
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setTo(newAccount.getEmail());
mailMessage.setSubject("스터디올래, 회원 가입 인증");
mailMessage.setText("/check-email-token?token="+ newAccount.getEmailCheckToken()+"&email="+ newAccount.getEmail());
javaMailSender.send(mailMessage);
}
saveNewAccount(signUpForm)
으로 저장 후newAccount.generateEmailCheckToken();
으로 토큰을 생성sendSignUpConfirmEmail(newAccount);
회원가입 인증 메일 전송
결론 : 계정 저장하고 나서 토큰을 생성해서 저장된 계정엔 토큰이 없음
이에 대해 강의에서는 ” Detached Object라 DB에 Synch되지 않았다. “ 라고 말했습니다.
( 멋지고.. 하나도 못 알아들었다.. 🤗 Jpa 건너뛰고 들었더니.. Jpa에 대해 기본적으로 공부할 것이 있는것 같네요.. 😅 )
1번 processNewAccount에서 토큰을 생성했음에도 토큰이 저장이 되지 않는 이유는 1번에서의 newAccount 객체는 Detached Object라서 DB에 synch가 되지 않은 겁니다. 생성했음에도 null인 이유는 2번 saveNewAccount에서 이미 트랜잭션 처리를 했기 때문에 이 안에서 해당하는 entity가 JPA entity life cycle에 해당하는 Persistent 상태입니다. 2번을 나온 1번에선 Detached 상태입니다.
1번에서도 Persistent 상태를 유지하려면 @Transactional 을 붙이면 됩니다.
@Transactional
public void processNewAccount(SignUpForm signUpForm) {
Account newAccount = saveNewAccount(signUpForm);
newAccount.generateEmailCheckToken();
sendSignUpConfirmEmail(newAccount);
}
이런 문제를 조기에 발견해서 다행이지만.. TestCode에서 미처 확인하지 못했습니다.
TestCode 보완해서 다시 테스트했습니다.
@DisplayName("회원 가입 처리 - 입력값 정상")
@Test
void signUpSubmit_with_correct_input() throws Exception {
mockMvc.perform(post("/sign-up")
.param("nickname","oomi")
.param("email","whdudal1217@naver.com")
.param("password","1234578910")
.with(csrf()))
.andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:/"));
Account account = accountRepository.findByEmail("whdudal1217@naver.com");
assertThat(account).isNotNull();
assertThat(account.getPassword()).isNotEqualTo("1234578910");
assertThat(account.getEmailCheckToken()).isNotNull();
then(javaMailSender).should().send(any(SimpleMailMessage.class));
}
Git Revision Number : 09933326161c696067b1040bdba985e11f472246
2. Account Email Athenticate Test and Refactoring
Git Revision Number : 7cfd0e4fc4293e7836a3aa29cc32e0b312c230ca
댓글남기기