본문 바로가기
스프링과 JPA 기반 웹 어플리케이션 개발/1부 (개발환경, 회원가입, 로그인, 계정설정)

05. 회원 가입: 폼 서브밋

by Backchus 2020. 4. 17.

회원 가입 폼 검증

  • JSR 303 애노테이션 검증
    • 값의 길이, 필수 값
  • 커스텀 검증
    • 중복이메일, 닉네임 여부 확인
  • 폼 에러 있을 시, 폼 다시 보여주기

 

회원 가입 처리

  • 회원 정보 저장
  • 인증 이메일 발송
  • 처리 후 첫 페이지로 리다이렉트 (Post-Redirect-Get 패턴)

회원가입 정보를 전달할 SignUpForm 생성(여기서 JSR 303 애노테이션 검증)

package me.weekbelt.studyolle.account;

@Data
public class SignUpForm {

   @NotBlank
   @Length(min = 3, max = 20)
   @Pattern(regexp = "^[ㄱ-ㅎ가-힣a-z0-9_-]{3,20}$")
   private String nickname;

   @Email
   @NotBlank
   private String email;

   @NotBlank
   @Length(min = 8, max = 50)
   private String password;
}

 

커스텀 검증(중복이메일, 닉네임 여부 확인)을 위해 Validator를 상속받는 SignUpFormValidator 작성

package me.weekbelt.studyolle.account;

@RequiredArgsConstructor
@Component
public class SignUpFormValidator implements Validator {

   private final AccountRepository accountRepository;

   // 어떠한 도메인 클래스에 대한 검증인지 설정
   @Override
   public boolean supports(Class<?> aClass) {
       return aClass.isAssignableFrom(SignUpForm.class);
   }

   @Override
   public void validate(Object object, Errors errors) {
       SignUpForm signUpForm = (SignUpForm) object;
       if (accountRepository.existsByEmail(signUpForm.getEmail())) {
           errors.rejectValue("email", "invalid.email", new Object[]{signUpForm.getEmail()}, "이미 사용중인 이메일 입니다.");
       }

       if (accountRepository.existsByNickname(signUpForm.getNickname())) {
           errors.rejectValue("nickname", "invalid.nickname", new Object[]{signUpForm.getNickname()}, "이미 사용중인 닉네임 입니다.");
       }
   }
}

 

AccountRepository 작성

package me.weekbelt.studyolle.account;

@Transactional(readOnly = true)
public interface AccountRepository extends JpaRepository<Account, Long> {

   boolean existsByEmail(String email);

   boolean existsByNickname(String nickname);
}

 

AccountController에 유효성 검증과 회원 저장을 위한 회원가입 POST 요청 추가

package me.weekbelt.studyolle.account;

@RequiredArgsConstructor
@Controller
public class AccountController {

   private final SignUpFormValidator signUpFormValidator;
   private final AccountRepository accountRepository;

   @InitBinder("signUpForm")
   public void initBinder(WebDataBinder webDataBinder){
       webDataBinder.addValidators(signUpFormValidator);
   }

   @GetMapping("/sign-up")
   public String signUpForm(Model model){
       model.addAttribute("signUpForm", new SignUpForm());
       return "account/sign-up";
   }

   @PostMapping("/sign-up")
   public String signUpSubmit(@Valid SignUpForm signUpForm, Errors errors){
       if(errors.hasErrors()){
           return "account/sign-up";
       }

       Account account = Account.builder()
               .email(signUpForm.getEmail())
               .nickname(signUpForm.getNickname())
               .password(signUpForm.getPassword())     // TODO encoding 해야함
               .emailVerified(false)
               .studyEnrollmentResultByWeb(true)
               .studyUpdatedByWeb(true)
               .build();
       return "redirect:/";
   }
}

 

이메일 전송을 위해 ConsoleMailSender 작성(일단은 콘솔로 보내서 메시지가 제대로 전달되는지만 확인)

package me.weekbelt.studyolle.mail;

@Slf4j
@Profile("local")
@Component
public class ConsoleMailSender implements JavaMailSender {
    @Override
    public MimeMessage createMimeMessage() {
        return null;
    }

    @Override
    public MimeMessage createMimeMessage(InputStream inputStream) throws MailException {
        return null;
    }

    @Override
    public void send(MimeMessage mimeMessage) throws MailException {

    }

    @Override
    public void send(MimeMessage... mimeMessages) throws MailException {

    }

    @Override
    public void send(MimeMessagePreparator mimeMessagePreparator) throws MailException {

    }

    @Override
    public void send(MimeMessagePreparator... mimeMessagePreparators) throws MailException {

    }

    @Override
    public void send(SimpleMailMessage simpleMailMessage) throws MailException {
        // 회원가입을 요청하면 출력
        log.info(simpleMailMessage.getText());
    }

    @Override
    public void send(SimpleMailMessage... simpleMailMessages) throws MailException {

    }
}

 

Test용과 application.preperties를 분리 시키기 위해 application.properties 설정

spring.profiles.active=local

 

AccountController에 메일 관련 코드 추가

package me.weekbelt.studyolle.account;

@RequiredArgsConstructor
@Controller
public class AccountController {

   // 기존코드...
   private final JavaMailSender javaMailSender;

   @PostMapping("/sign-up")
   public String signUpSubmit(@Valid SignUpForm signUpForm, Errors errors){
        
       // 기존코드…..

       Account newAccount = accountRepository.save(account);
       newAccount.generateEmailCheckToken();
       SimpleMailMessage mailMessage = new SimpleMailMessage();
       mailMessage.setTo(newAccount.getEmail());
       mailMessage.setSubject("스터디올래, 회원 가입 인증");
       mailMessage.setText("/check-email-token?token=" + newAccount.getEmailCheckToken() + "&email=" + newAccount.getEmail());
       javaMailSender.send(mailMessage);
       return "redirect:/";
   }
}

 

 

참고: https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-JPA-%EC%9B%B9%EC%95%B1#

 

스프링과 JPA 기반 웹 애플리케이션 개발 - 인프런

이 강좌에서 여러분은 실제로 운영 중인 서비스를 스프링, JPA 그리고 타임리프를 비롯한 여러 자바 기반의 여러 오픈 소스 기술을 사용하여 웹 애플리케이션을 개발하는 과정을 학습할 수 있습니다. 이 강좌를 충분히 학습한다면 여러분 만의 웹 서비스를 만들거나 취직에 도움이 될만한 포트폴리오를 만들 수 있을 겁니다. 활용 웹 개발 프레임워크 및 라이브러리 Java Spring Spring Boot Spring Data JPA Thymeleaf 온라인 강의 스

www.inflearn.com