본문 바로가기
SpringBoot/Springboot Basic

Spring Boot 회원가입 페이지 + 아이디 중복기능

by Son 2023. 4. 6.
ㅊ​
 @GetMapping("/username")
    public ResponseEntity<?> duplicateUsername(@Valid UsernameDto usernameDto, BindingResult bindingResult) {
        userService.duplicateUsername(usernameDto.getUsername());

        return ResponseEntity.ok().body(new CMRespDto<>("가입 가능한 사용자이름", true));
    }

HTML CSS JS

Document

회원가입

1.싱글톤 패턴 

  class RegisterApi {
            static #instance = null;
            static getInstance() {
                if(this.#instance == null) {
                    this.#instance = new RegisterApi();
                }
                return this.#instance;
            }

static를 사용했기 때문에 객체 생성을 하지 않아도 자동으로 메모리에 할당됨

 

# private를 의미

 

 

       

            addEventToUsernameInput() {
                const usernameInput = document.querySelectorAll(".register-text")[0];
                usernameInput.onblur = () => {
                    RegisterApi.getInstance().duplicateUsername(usernameInput.value);
                }
            }

register-text(input 아이디 입력)들을 받아와서 그중 가장위에있는 [0]번째(아이디 입력)을 받아온후 onblur이벤트가 일어났을때 싱글톤 객체를 생성하고 아이디중복을 확인하기 위해서 duplicateUsername함수에 아이디 값(usernameInput.value)을 넘겨줌 

 

duplicateUsername(username) {
                const usernameInput = document.querySelectorAll(".register-text")[0];
                const usernameError = document.querySelectorAll(".error-msg")[0];

                $.ajax({
                    async: false,
                    type: "get",
                    url: "/api/account/username",
                    data: {
                        "username": username
                    },
                    dataType: "json",
                    success: (response) => {
                        usernameInput.classList.add("success");
                        usernameError.textContent = "";
                    },
                    error: (errorResponse) => {
                        console.log(errorResponse);
                        usernameInput.classList.remove("success");
                        usernameError.textContent = errorResponse.responseJSON.data.username;
                    }
                });

            }
        }

아이디를 매개변수로하여 get요청으로  /api/account/username에 username이름으로 넘겨주고 Response data는 json으로 받도록 설정함

 

Controller

 

1.Page Controller

package com.study.springboot202210junil.web.controller.account;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class AccountController {

    @GetMapping("/account/register")
    public String loadRegister() {
        return "account/register";
    }
}

 

회원가입 페이지를 보여주기 위한 AccountController

@GetMapping("/username")
    public ResponseEntity<?> duplicateUsername(String username) {
        userService.duplicateUsername(usernameDto.getUsername());

        return ResponseEntity.ok().body(new CMRespDto<>("가입 가능한 사용자이름", true));
    }

Ajax요청으로 Controler에 들어온 username를 서비스에 보내줌

 

Service

public void duplicateUsername(String username) {
        UserDto userDto = userRepository.findUserByUsername(username);
        if(userDto != null) {
            Map<String, String> errorMap = new HashMap<>();
            errorMap.put("username", "이미 존재하는 사용자이름 입니다.");
            throw new CustomValidException(errorMap);
        }

Controller에서 보내온 username를 Repositort에 보내줌

 

Repository

 public UserDto findUserByUsername(String username);

xml로 username을 보내줌

 

xml

 <select id="findUserByUserId" parameterType="integer" resultType="com.study.springboot202210junil.web.dto.UserDto">
        select
            user_id as userId,
            username,
            password,
            name,
            email
        from
            user_mst
        where
            user_id = #{userId}
    </select>

파라메터로 받은 username과 일치하는 테이블을 dto에 반환시킴

 

public void duplicateUsername(String username) {
        UserDto userDto = userRepository.findUserByUsername(username);
        if(userDto != null) {
            Map<String, String> errorMap = new HashMap<>();
            errorMap.put("username", "이미 존재하는 사용자이름 입니다.");
            throw new CustomValidException(errorMap);
        }
    }

 

그후 Service에서 userDto가 null이 아니라면 (null이면 사용가능한 아이디 임으로) 예외를 발생시키고 Map을 만들어 예외가 일어 났을 경우에 예외객체를 생성해줌

 

CustomDuplicateUsernameException

public class CustomDuplicateUsernameException extends RuntimeException {

    @Getter
    private Map<String, String> errorMap;

    public CustomDuplicateUsernameException(String message, Map<String, String> errorMap) {
        super(message);
        this.errorMap = errorMap;
    }
}

Service에서 생성된 예외를 받아 massage는 RuntimeException에 넣어주고 errorMap에 넣음

 

여기서

@Getter
    private Map<String, String> errorMap;

Map에 @Getter를 넣어줘야 하는 이유는 JS에서 응답을 Json형태로 줘야 하기 때문에 @Getter를 넣어줘야함 만일 넣어주지 않았을 경우에 @Json으로 응답불가

 

RestControllerAdvice

@RestControllerAdvice
public class AccountApiControllerAdvice {

    @ExceptionHandler(CustomDuplicateUsernameException.class)
    public ResponseEntity<?> duplicateError(CustomDuplicateUsernameException e) {
        return ResponseEntity.badRequest().body(new CMRespDto<>(e.getMessage(), e.getErrorMap()));
    }

@RestControllerAdvice는 예외처리가 발생했을경우(예외처리 객체가 생성됬을경우)에 생성된 예외처리 객체를 모두 가져와서 그 예외처리를 @ExceptionHandler에 등록시켜준다 여기에서는 CustomDuplicateUsernameException.class객체가 생성되었을경우에 그 생성된 객체를 가져오고 객체가 생성될경우 @RestControllerAdvice에 Controller를 만들어 return해준다

예외처리가 발생하였을때 try catch문이 일어나는데 예외처리가 발생한 부분을 try @RestControllerAdvice을 catch문이라고 생각하면 된다

@GetMapping("/username") public ResponseEntity duplicateUsername(@Valid UsernameDto usernameDto, BindingResult bindingResult) { userService.duplicateUsername(usernameDto.getUsername()); return ResponseEntity.ok().body(new CMRespDto<>("가입 가능한 사용자이름", true)); }
 @GetMapping("/username")
    public ResponseEntity<?> duplicateUsername(@Valid UsernameDto usernameDto, BindingResult bindingResult) {
        userService.duplicateUsername(usernameDto.getUsername());

        return ResponseEntity.ok().body(new CMRespDto<>("가입 가능한 사용자이름", true));
    }

아이디 중복체크가 성공적으로 이루어졌다면 return에 상태코드 200과 메시지를 준다

 duplicateUsername(username) {
                const usernameInput = document.querySelectorAll(".register-text")[0];
                const usernameError = document.querySelectorAll(".error-msg")[0];

                $.ajax({
                    async: false,
                    type: "get",
                    url: "/api/account/username",
                    data: {
                        "username": username
                    },
                    dataType: "json",
                    success: (response) => {
                        usernameInput.classList.add("success");
                        usernameError.textContent = "";
                    },
                    error: (errorResponse) => {
                        console.log(errorResponse);
                        usernameInput.classList.remove("success");
                        usernameError.textContent = errorResponse.responseJSON.data.username;
                    }
                });

            }
        }

json으로 성공적으로 응답이 온다면 success를 토글시켜 사용자에게 보여주고

실패했다면 오류메시지를 사용자에게 보여준다

 

아래는 구현이 되고 난 회원가입사이트의 모습이다

 

 

KakaoTalk_20230406_180341496.mp4
0.07MB