SpringBoot 프로젝트

Spring Boot로 회원가입 기능 구현

orin602 2024. 11. 18. 11:06

join.html

<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">

<head>

<meta charset="utf-8">

<title>join</title>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.2/css/all.min.css">

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11.4.10/dist/sweetalert2.min.css">

<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11.4.10/dist/sweetalert2.min.js"></script>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

<link rel="stylesheet" th:href="@{/css/login.css}">

<script th:src="@{js/login.js}"></script>

</head>

<body>

<div class="join-container">

     <h1>회원가입</h1>

      <form id="join-form" method="post">

            <span>ID는 영문자와 숫자로만 구성되어야 하고, 3자 이상 15자 이하여야 합니다.</span>

            <input type="text" name="id" id="id" placeholder="ID">

             <button class="check-btn" type="button" id="id-check-button">중복체크</button>

             <input type="email" name="email" id="email" placeholder="Email">

             <button class="check-btn" type="button" id="email-check-button">중복체크</button>

             <span>비밀번호는 최소 8자 이상이며, 대문자, 소문자, 숫자, 특수문자를 모두 포함해야 합니다.</span>

             <input type="password" name="pwd" id="pwd" placeholder="Password">

             <input type="password" name="pwdcheck" id="pwdcheck" placeholder="PasswordCheck">

             <input type="text" name="name" id="name" placeholder="Name">

             <button class="join-btn" type="button" id="join-button">회원가입</button>

     </form>

</div>

</body>

</html>

회원가입 페이지

ID 중복체크 및 제약조건

// ID 중복 체크

$("#id-check-button").click(function() {

      var idRegex = /^[a-zA-Z0-9]{3,15}$/;

      var id = $("#id").val();

      if(id == "") {

            swal.fire({

                  title: 'ID를 입력하세요.',

                  icon: 'error',

                  confirmButtonText: '확인'

            });

            $("#id").focus();

            return false;

      } else if(!idRegex.test(id)) {

            swal.fire({

                  title: '제약조건에 맞지 않습니다.',

                  text: 'ID는 영문자와 숫자로만 구성되어야 하고, 3자 이상 15자 이하여야 합니다.',

                  icon: 'warning'

            });

            $("#id").focus();

            return false;

      }

...

var idRegex = /^[a-zA-Z0-9]{3,15}$/; 사용자가 입력한 ID가 규격에 맞는지 확인하는 정규 표현식

  • [a-zA-Z0-9]: 영문 대소문자와 숫자만 허용합니다.
  • {3,15}: 길이는 최소 3자, 최대 15자이어야 합니다.

 

var id = $("#id").val(); 회원가입 페이지에서 입력한 ID

사용자가 ID를 입력하지 않거나, ID가 정해진 규칙을 위반하는 경우에는 폼 제출이 막히고, SweetAlert2로 경고 메시지를 띄운 후 사용자에게 입력을 다시 요청합니다.

ID를 입력하지 않았을 때
ID가 제약조건에 맞지 않을 떄

ID 중복체크 폼 제출 성공 시

$.ajax({

     type: "GET",

      url: "/id-check-form",

      data: { id : id },

      success: function(response) {

            if(response.result === 1) {

                  swal.fire({

                        title: '이미 사용중인 ID입니다.',

                        icon: 'error',

                        confirmButtonText: '확인'

                  });

                  isIdChecked = false;

            } else {

                  swal.fire({

                        title: '사용 가능한 ID입니다.',

                        icon: 'success',

                        confirmButtonText: '확인'

                  });

                  isIdChecked = true;

            }

      },

      error: function() {

            swal.fire({

                  title: '오류 발생',

                  text: '아이디 중복 확인 중 오류가 발생했습니다.',

                  icon: 'error',

                  confirmButtonText: '확인'

            });

            isIdChecked = false;

      }

});

  • type: "GET": 서버에 GET 요청을 보냅니다. 요청 방식은 POST도 가능하지만, 여기서는 단순히 아이디 중복 여부만 확인하기 때문에 GET을 사용합니다.
  • data: { id: id }: 사용자가 입력한 아이디(id)를 data 속성을 통해 서버로 전달합니다.
  • success: 서버에서 응답이 돌아오면 실행되는 콜백 함수입니다. response.result에 따라 ID가 사용 가능한지 아닌지 판단하고, 그에 맞는 알림을 표시합니다.
  • error: 요청이 실패하면 오류 메시지를 표시합니다.

 

MemberRepository

@Query(value="SELECT * FROM member WHERE id =:id", nativeQuery=true)

Member findByLoginId(String id);

 

  • 입력한 ID가 DB에 존재하면, 이 메서드는 해당 ID를 가진 Member 객체를 반환합니다. 즉, 해당 ID는 이미 다른 사용자가 사용 중임을 의미합니다.
  • 입력한 ID가 DB에 존재하지 않으면, 이 메서드는 null을 반환하며, 이는 사용자가 입력한 ID가 아직 사용되지 않은 ID라는 뜻입니다.

MemberServiceImpl (중복체크 메서드 구현)

@Override

public int confirmId(String id) {

     int result = 0;

 

      Member member = memberRepo.findByLoginId(id);

 

      if (member != null) {

            result = 1;

      } else {

            result = -1;

      }

      return result;

}

 

  • result = 1: ID가 이미 존재한다는 뜻으로, 중복된 ID임을 나타냅니다.
  • result = -1: ID가 존재하지 않으면, 사용자가 입력한 ID가 사용 가능하다는 뜻입니다.

MemberController

// 아이디 중복확인 처리

@GetMapping("/id-check-form")

@ResponseBody

public Map<String, Object> idCheckAction(@RequestParam("id") String id) {

     // 회원 서비스에서 ID 중복 확인을 위한 메서드 호출

     int result = memberService.confirmId(id);

 

      // 결과를 담을 Map 객체 생성

      Map<String, Object> response = new HashMap<>();

      response.put("result", result);    // 중복 체크 결과를 'result' 키로 Map에 저장

 

      return response;    // 결과를 클라이언트로 반환

}

 

 

  • @GetMapping("/id-check-form"): 클라이언트가 GET 방식으로 요청한 /id-check-form URL을 처리하는 메서드입니다.
  • @RequestParam("id"): html에서 전송한 id 값을 파라미터로 받아옵니다.
  • memberService.confirmId(id): 아이디가 중복되는지 확인하는 서비스 메서드입니다.
  • Map<String, Object> response: 중복 여부를 담은 응답 데이터를 Map 형식으로 반환합니다.

이미 사용중인 ID일 경우

 

사용 가능한 ID일 경우

 

// email 중복 체크

$("#email-check-button").click(function() {

     var email = $("#email").val();

      if(email == "") {

            swal.fire({

                  title: 'Email을 입력하세요.',

                  icon: 'error',

                  confirmButtonText: '확인'

            });

            return false;

      }

 

      $.ajax({

            type: 'GET',

            url: "/email-check-form",

            data: { email : email },

            success: function(response) {

                  if(response.result == 1) {

                        swal.fire({

                              title: '이미 사용중인 Email입니다.',

                              icon: 'warning',

                              confirmButtonText: '확인'

                        });

                        isEmailChecked = false;

                  }else {

                        swal.fire({

                              title: '사용 가능한 Email입니다.',

                              icon: 'success',

                              confirmButtonText: '확인'

                        });

                        isEmailChecked = true;

                  }

            },

            error: function() {

                  swal.fire({

                        title: '오류 발생',

                        text: 'Email 중복 확인 중 오류가 발생했습니다.',

                        icon: 'error',

                        confirmButtonText: '확인'

                  });

                  isEmailChecked = false;

            }

 

      });

});

이메일 중복 체크 역시 아이디 중복 체크와 비슷한 방식으로 처리됩니다. 서버 측에서는 이메일을 확인하는 메서드를 작성하고, 클라이언트 측에서는 AJAX를 통해 중복 여부를 확인합니다. 자세한 구현 방법은 아이디 중복 체크와 동일하므로, 이전 설명을 참고해 주세요.

 

회원가입 버튼 제약조건(

// 회원가입 버튼 클릭 시

$("#join-button").click(function() {

 

     var idRegex = /^[a-zA-Z0-9]{3,15}$/;

      var pwdRegex = /^(?=.*[!@#$%^&*()-_=+`~{}[\]|;:'",<.>/?])(?=.*[A-Z])(?=.*[a-z])(?=.*\d).{8,}$/;

 

      if ($("#id").val() == "") {

            swal.fire({

                  title: 'ID를 입력해 주세요',

                  icon: 'warning'

            });

            $("#id").focus();

            return false;

      } else if ($("#email").val() == "") {

            swal.fire({

                  title: 'Email을 입력해 주세요',

                  icon: 'warning'

            });

            $("#email").focus();

            return false;

      } else if ($("#pwd").val() == "") {

            swal.fire({

                  title: 'Password를 입력해 주세요',

                  icon: 'warning'

            });

            $("#pwd").focus();

            return false;

      } else if ($("#name").val() == "") {

            swal.fire({

                  title: 'Name을 입력해 주세요',

                  icon: 'warning'

            });

            $("#name").focus();

            return false;

      } else if (!isIdChecked) {

            swal.fire({

                  title: 'ID 중복 체크를 해주세요.',

                  icon: 'error',

                  confirmButtonText: '확인'

            });

            return false;

      } else if (!isEmailChecked) {

            swal.fire({

                  title: 'Email 중복 체크를 해주세요.',

                  icon: 'error',

                  confirmButtonText: '확인'

            });

            return false;

      } else if ($("#pwd").val() != $("#pwdcheck").val()) {

            swal.fire({

                  title: '비밀번호가 일치하지 않습니다.',

                  text: '비밀번호를 다시 입력해 주세요.',

                  icon: 'error'

            });

            $("#pwd").focus();

            return false;

      } else if(!idRegex.test($("#id").val())) {

            swal.fire({

                  title: '제약조건에 맞지 않습니다.',

                  text: 'ID는 영문자와 숫자로만 구성되어야 하고, 3자 이상 15자 이하여야 합니다.',

                  icon: 'warning'

            });

            $("#id").focus();

            return false;

      } else if(!pwdRegex.test($("#pwd").val())) {

            swal.fire({

                  title: '제약조건에 맞지 않습니다.',

                  text: '비밀번호는 최소 8자 이상이며, 대문자, 소문자, 숫자, 특수문자를 모두 포함해야 합니다.',

                  icon: 'warning'

            });

            $("#pwd").focus();

            return false;

      }

회원가입 제약조건을 모두 통과하면

// AJAX를 사용하여 회원가입 폼 데이터를 서버로 전송

$.ajax({

     type: "POST",

      url: "/join", // 서버 측의 컨트롤러 경로

      data: $("#join-form").serialize(), // 폼 데이터 직렬화하여 전송

      success: function(response) {

            Swal.fire({

                  icon: 'success',

                  title: '회원가입 성공',

                  text: response, // 서버에서 전달한 메시지

                  confirmButtonText: '확인'

            }).then((result) => {

                  window.location.href = '/login'; // 로그인 페이지로 이동

            });

      },

      error: function(xhr, status, error) {

            Swal.fire({

                  icon: 'error',

                  title: '회원가입 실패',

                  text: xhr.responseText, // 서버에서 전달한 에러 메시지

                  confirmButtonText: '확인'

            });

      }

});

});

ServiceImpl ( 회원가입 메서드 )

@Override

public void insertMember(Member vo) {

     memberRepo.save(vo);

}

Controller(메서드를 이용한 회원가입 처리)

// 회원가입 처리

@PostMapping("/join")

public ResponseEntity<String> joinAction(Member vo) {

      try {

            memberService.insertMember(vo);

            return new ResponseEntity<>("회원가입이 성공적으로 완료되었습니다.", HttpStatus.OK);

      } catch (Exception e) {

            return new ResponseEntity<>("회원가입에 실패하였습니다.", HttpStatus.INTERNAL_SERVER_ERROR);

      }

}

 

각 제약조건

비밀번호 제약조건이 맞지 않을 때
1차, 2차 비밀번호가 일치하지 않을 때

회원가입 성공

회원가입 성공

 

Oracle DB에 반영