spring boot 게시판 - 2 <회원 중복 체크 및 유효성 검사>

2022. 11. 11. 15:26·Java/Spring Boot 게시판
목차
  1. 🛑build.gradle
  2. 🛑MemberSaveRequestDTO
  3. 🛑MemberRepository
  4. 🛑AbstractValidator
  5. 🛑CheckEmailValidator
  6. 🛑MemberService
  7. 🛑MemberServiceImpl
  8. 🛑MemberController
728x90

https://magicmk.tistory.com/25

 

Spring boot 게시판 - 1 < 간단 회원 가입 구현>

시스템 구성 Spring boot 2.7.5 Gradle Java 11 Intellij Ultimate 라이브러리 thymeleaf jpa web lombok h2 DB 프로젝트 구조 프로젝트 구조는 위와 같은 구조를 따라갈 것이며 각 내용이 무엇을 하는지는 https://magicmk.t

magicmk.tistory.com

전편에 이은 회원 이메일 중복 체크 및 유효성 검사 편이다.

 

프로젝트를 완성하고 글을 작성하는 게 아니라 만들면서 까먹지 않도록 작성하는 거라

이전 편에 작성했던 코드들이 변경되는 것도 있고 밑에 코드를 추가할 때 너무 길어지지 않도록 기존에 작성한

코드는 제거할 거고 순서가 뒤죽박죽이지만 기록용이니 이해를 바란다. 😊


우선 유효성 검사를 위해 build.gradle에 라이브러리를 하나 추가한다.

🛑build.gradle

implementation 'org.springframework.boot:spring-boot-starter-validation'

spring boot 2.3 버전 이전까지는 spring-boot-starer-web 의존성 내부에 있던 녀석이 사라져 버려서

이제는 따로 추가해줘야 한다. 본인 spring boot 버전이 2.3 밑이라면 추가하지 않아도 된다.

 

 

그리고 유효성 검사를 위해 이전 시간에 작성했던 DTO를 변경했다.

🛑MemberSaveRequestDTO

package com.practice.board.dto;

import lombok.*;

import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class MemberSaveRequestDTO {

    @NotBlank(message="이메일을 입력해주세요.")
    @Email(message = "올바른 이메일 주소를 입력해주세요.")
    private String email;

    @NotBlank(message = "닉네임을 입력해주세요.")
    @Size(min = 2, max = 15, message = "닉네임은 2 ~ 15자 사이로 입력해주세요")
    private String username;

    @NotBlank(message = "비밀번호를 입력해주세요.")
    private String password;
}

DTO 이름도 변경됐다.

validation을 이용하면 패턴을 등록하거나 다양한 설정을 할 수 있다.

 

 

그리고 repository에서 email의 존재 여부를 확인할 수 있도록

🛑MemberRepository

package com.practice.board.repository;

import com.practice.board.domain.Member;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface MemberRepository extends JpaRepository<Member, Long> {

    /**
     * 유효성 검사 - 중복 체크
     * @param email 회원 이메일
     * @return
     */
    boolean existsByEmail(String email);
}

existsByEmail을 추가해주었다.

 

 

여기까지 진행했다면 이제 Validator를 직접 작성해야 한다.

🛑AbstractValidator

package com.practice.board.validator;

import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

@Slf4j
public abstract class AbstractValidator<T> implements Validator {

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }

    @SuppressWarnings("unchecked")
    @Override
    public void validate(Object target, Errors errors) {
        try {
            doValidate((T) target, errors);
        } catch(RuntimeException e) {
            log.error("중복 검증 에러", e);
            throw e;
        }
    }

    protected abstract void doValidate(final T dto, final Errors errors);
}

 

위 내용을 상속받는 CheckEmailValidator를 작성한다.

 

🛑CheckEmailValidator

package com.practice.board.validator;

import com.practice.board.dto.MemberSaveRequestDTO;
import com.practice.board.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;

@Component
@RequiredArgsConstructor
public class CheckEmailValidator extends AbstractValidator<MemberSaveRequestDTO> {

    private final MemberRepository memberRepository;

    @Override
    protected void doValidate(MemberSaveRequestDTO dto, Errors errors) {
        if(memberRepository.existsByEmail(dto.getEmail())) {
            errors.rejectValue("email", "이메일 중복 오류", "이미 사용중인 이메일 입니다.");
        }
    }
}

나는 이메일 중복 여부만 따질 것이기 때문에 이메일만 적용하였지만 원하는 분들은 다른 것들을 더 설정하면 좋다.

 

이제 Service와 Controller만 추가해주면 된다.

🛑MemberService

package com.practice.board.service;


import com.practice.board.dto.MemberSaveRequestDTO;
import com.practice.board.dto.MemberResponseDTO;
import org.springframework.validation.Errors;

import java.util.List;
import java.util.Map;

public interface MemberService {

    /**
     * 회원가입 시, 유효성 및 중복 검사
     * @param errors
     * @return
     */
    Map<String, String> validateHandling(Errors errors);
}

🛑MemberServiceImpl

package com.practice.board.service.Impl;

import com.practice.board.domain.Member;
import com.practice.board.dto.MemberSaveRequestDTO;
import com.practice.board.dto.MemberResponseDTO;
import com.practice.board.repository.MemberRepository;
import com.practice.board.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService {

    private final MemberRepository memberRepository;
    private final PasswordEncoder passwordEncoder;

    /* 회원가입 시, 유효성 및 중복 검사 */
    @Transactional(readOnly = true)
    @Override
    public Map<String, String> validateHandling(Errors errors) {
        Map<String, String> validatorResult = new HashMap<>();

        /* 유효성 및 중복 검사에 실패한 필드 목록을 받음 */
        for (FieldError error : errors.getFieldErrors()) {
            String validKeyName = String.format("valid_%s", error.getField());
            validatorResult.put(validKeyName, error.getDefaultMessage());
        }

        return validatorResult;
    }
}

 

🛑MemberController

package com.practice.board.controller;

import com.practice.board.dto.MemberResponseDTO;
import com.practice.board.dto.MemberSaveRequestDTO;
import com.practice.board.service.MemberService;
import com.practice.board.validator.CheckEmailValidator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PostMapping;

import javax.validation.Valid;
import java.util.List;
import java.util.Map;

@Controller
@RequiredArgsConstructor
@Slf4j
public class MemberController {

    private final MemberService memberService;
    private final CheckEmailValidator checkEmailValidator;

    /* 유효성 검증 */
    @InitBinder
    public void validatorBinder(WebDataBinder binder) {
        binder.addValidators(checkEmailValidator);
    }

   
    /**
     * 회원 가입 post
     * @param memberSaveRequestDTO 회원 정보
     * @return 홈페이지
     */
    @PostMapping("/members/new")
    public String createMember(@Valid MemberSaveRequestDTO memberSaveRequestDTO, Errors errors, Model model) {
        /* 검증 */
        if (errors.hasErrors()) {
            /* 회원가입 실패 시 입력 데이터 유지 */
            model.addAttribute("dto", memberSaveRequestDTO);

            /* 유효성 검사를 통과하지 못한 필드와 메세지 핸들링 */
            Map<String, String> validatorResult = memberService.validateHandling(errors);
            for (String key : validatorResult.keySet()) {
                model.addAttribute(key, validatorResult.get(key));
            }

            /* 회원가입 페이지로 리턴 */
            return "/members/createMemberForm";
        }

        Long memberId = memberService.join(memberSaveRequestDTO);

        return "home";
    }
}

 

현재 controller에 model.addAttribute를 통해 데이터를 전달하는데 HTML은 mustache나 thymeleaf나

원하는 템플릿을 사용해서 멋있게 출력하면 된다.

 

끝.

저작자표시 비영리

'Java > Spring Boot 게시판' 카테고리의 다른 글

spring boot 게시판 - 6 <bootstrap 적용하기>  (0) 2022.11.22
spring boot 게시판 - 5 <thymeleaf layout 적용>  (0) 2022.11.21
spring boot 게시판 - 4 <spring security form login 구현>  (0) 2022.11.18
spring boot 게시판 - 3 <패스워드 암호화, 회원 목록 조회>  (0) 2022.11.11
Spring boot 게시판 - 1 < 간단 회원 가입 구현>  (8) 2022.11.10
  1. 🛑build.gradle
  2. 🛑MemberSaveRequestDTO
  3. 🛑MemberRepository
  4. 🛑AbstractValidator
  5. 🛑CheckEmailValidator
  6. 🛑MemberService
  7. 🛑MemberServiceImpl
  8. 🛑MemberController
'Java/Spring Boot 게시판' 카테고리의 다른 글
  • spring boot 게시판 - 5 <thymeleaf layout 적용>
  • spring boot 게시판 - 4 <spring security form login 구현>
  • spring boot 게시판 - 3 <패스워드 암호화, 회원 목록 조회>
  • Spring boot 게시판 - 1 < 간단 회원 가입 구현>
요술공주밍키
요술공주밍키
조금씩이라도 꾸준히..
  • 요술공주밍키
    삽질의흔적
    요술공주밍키
  • 전체
    오늘
    어제
    • 분류 전체보기 (127)
      • Java (42)
        • Spring Boot (14)
        • Spring Boot 게시판 (14)
        • 공중화장실 찾기 (4)
        • 쇼핑몰 (8)
      • JavaScript (8)
        • NodeJS (2)
      • Python (5)
        • Django (4)
      • Server (10)
        • Docker (4)
        • K8S (0)
        • Jenkins (1)
      • 알고리즘 (20)
        • 프로그래머스 (17)
        • 백준 (3)
      • Etc (21)
        • 개발 팁 (1)
      • 일상 (19)
        • 독서 포스트 (17)
        • 회고록 (2)
  • 인기 글

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
요술공주밍키
spring boot 게시판 - 2 <회원 중복 체크 및 유효성 검사>

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.