최원종의 개발 블로그

V15-4 이메일 인증 후 회원가입 로직 변경 본문

Spring boot 입문/Spring boot 입문 -1

V15-4 이메일 인증 후 회원가입 로직 변경

chl6698 2026. 6. 23. 11:35

이메일 중복 가입 체크 로직 추가

user/User.java - email 에 unique 제약 추가

@Data
@NoArgsConstructor
@Table(name = "user_tb")
@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    // 사용자명 중복 방지를 위한 유니크 제약 조건 설정
    @Column(unique = true)
    private String username;

    private String password;
    // 물리적으로 중복 값 등록 방지
    @Column(unique = true)
    private String email;
    
   // ... 생략 
}

UserRepository(이메일 조회 쿼리 작성)

    // 이메일 조회 (중복 이메일 체크 확인 용)
    @Query("""
        SELECT u FROM User u WHERE u.email = :email
    """)
    Optional<User> findByEmail(@Param("email") String email);

UserService 코드

  • 이메일 인증 도장 확인 추가
  • 중복 이메일 체크 추가
  • 이메일 인증 도장 삭제 추가
/**
   * 회원 가입 처리
   * @param joinDTO (사용자 회원가입 요청 정보)
   * @return User (저장된 사용자 정보)
   */
  @Transactional
  public User 회원가입(UserRequest.JoinDTO joinDTO) {
      log.info("회원가입 서비스 시작");
      //[핵심] 이메일 인증 도장 확인
      String verifiedEmail = (String) session.getAttribute("verified_email");
      if(verifiedEmail == null || !verifiedEmail.equals(joinDTO.getEmail())) {
          // 이메일 위변조를 방지하기 위해 인증번호 검증시 넣었던 그 이메일 진행 시켜야 한다
          throw new Exception400("이메인 인증을 완료해주세요");
      }

      // 회원가입시 사용자 이름 중복 체크
      userRepository.findByUsername(joinDTO.getUsername()).ifPresent(user -> {
          log.warn("회원가입 실패 - 중복된 사용자명 : {}", user.getUsername());
          throw new Exception400("이미 존재하는 사용자 이름입니다");
      });

      // 중복 이메일 체크
      // ifPresent  -> 값이 존재하면 괄호안에 코드를 수행해!!
      userRepository.findByEmail(joinDTO.getEmail()).ifPresent(user -> {
          log.warn("회원가입 실패 - 중복된 이메일 : {}", user.getEmail());
          throw new Exception400("이미 존재하는 이메일 입니다");
      });

      // 프로필 이미지 저장 기능 구현 (선택 사항 임)
      String profileImageFilename = null;
      if(joinDTO.getProfileImage() != null && joinDTO.getProfileImage().isEmpty() == false) {
          try {
              // 이미지 파일이 맞는지 검증
              if(FileUtil.isImageFile(joinDTO.getProfileImage()) == false) {
                  throw new Exception400("이미지 파일만 업로드 가능합니다");
              }
              profileImageFilename = FileUtil.saveFile(joinDTO.getProfileImage(), FileUtil.IMAGES_DIR);
          } catch (Exception e) {
              // 디스크 공간 없거나, 권한 없음
              throw new Exception500("프로필 이미지 저장 실패");
          }
      }
      // 코드 수정
      User user = joinDTO.toEntity(profileImageFilename);
      String hashPwd = passwordEncoder.encode(joinDTO.getPassword());
      user.setPassword(hashPwd);

      //[핵심] 이메일 인증 도장 삭제
      session.removeAttribute("verified_email");
      return userRepository.save(user);
  }

GlobalExceptionHandler - 코드 수정

public class GlobalExceptionHandler {

    @ExceptionHandler(Exception400.class)
    @ResponseBody
    public String ex400(Exception400 e, HttpServletRequest request) {
        log.warn("=== 400 Bad Request 에러 발생 ===");
        log.warn("요청 URL: {}", request.getRequestURL());
        log.warn("에러메시지: {}", e.getMessage());

        String message = e.getMessage() != null ? e.getMessage() : "잘못된 요청입니다";
        String escapeMessage = message.replace("'", "\\'" );
        return """
                <script>
                    alert('%s');
                    history.back();
                </script>
                """.formatted(escapeMessage);
    }
    
    
    // ... 생략 
}