09009
[Spring] 예제 3 - 회원가입 유효성 검사 (AJAX) 본문
아이디 중복체크
중복확인 버튼을 눌렀을 때 경고창 띄우기
아이디 중복확인 시에는 자바스크립트로만 할 수 있는 것이 아니라
회원가입 시 입력한 아이디를 서버로 전송하는 작업이 필요하다.
(입력한 아이디가 DB에 저장된 아이디 중에 같은 것이 있는지 확인해야 하기 때문에)
자바스크립트로 request하는 API
:코드 내에서 페이지가 넘어가지 않고 자바스크립트로 request해서 응답하는 api
AJAX: 페이지가 넘어가지 않은 채로도 서버와 통신할 수 있는 API (비동기식 통신 방법)
호출 방식
function checkUserId() {
// AJAX api 활용
const xhr = new XMLHttpRequest();
xhr.open("get", "./loginPage"); // 무엇을 호출할 것인지..? requestmapping 된 loginPage 접속
xhr.send();
}
const a = 10;
// 많이 쓰이는 함수 작성법
function test() {
alert("ss");
return 10;
}
const b = test(); // test 함수 호출하고 return 값 받음
const c = test; // 변수가 함수 그 자체를 받아들일 수 있다. (변수 c가 test 함수 자체를 받아들임) 함수를 호출한 것이 아니다 !!!
c();
test(); // c(); == test();
// 많이 쓰이는 함수 작성법
const d = function() { // d라는 변수에 함수를 넣는다. (익명 함수 생성)
alert("ttt");
}
d(); // 함수 호출
// lo function
const e = () => alert("ttt");
const e1 = () => {
alert("ttt") // e라는 변수에 함수를 넣었다
};
e();
e1();
function checkUserId() {
// AJAX api 활용
const xhr = new XMLHttpRequest();
// 이 값에 function을 넣을 수 있다.
xhr.onreadystatechange = function () {
alert("안녕");
};
xhr.open("get", "./loginPage"); // 무엇을 호출할 것인지..? requestmapping 된 loginPage 접속
xhr.send();
}
4번째 반응 확인
onreadystatechange : 서버에서 응답이 도착하였을 때 특정한 자바스크립트 함수를 호출할 수 있는 것
XMLHTTP의 상태가 변경될 때마다라는 뜻
function checkUserId() {
// AJAX api 활용
const xhr = new XMLHttpRequest();
// 이 값에 function을 넣을 수 있다.
xhr.onreadystatechange = function () {
alert(xhr.responseText);
};
xhr.open("get", "./loginPage"); // 무엇을 호출할 것인지..? requestmapping 된 loginPage 접속
xhr.send();
}
중복확인 버튼을 클릭하면
ajax: 자바스크립트로 요청하고 응답받는다.
ajax가 호출된 쪽(받는 쪽)은 html 코드가 아닌 restapi를 만들어주어야 한다.
function checkUserId() {
// AJAX api 활용
// 코드 실행 흐름 순서 중요
const xhr = new XMLHttpRequest(); // (1)
// 이 값에 function을 넣을 수 있다. 콜백함수: 내가 만들었지만 내가 호출한 것이 아님.
xhr.onreadystatechange = function () { // (2)
if(xhr.readyState == 4 && xhr.status == 200) {
//(5)
alert(xhr.responseText);
}
};
xhr.open("get", "./existsUserId"); // (3) 무엇을 호출할 것인지..? requestmapping 된 loginPage 접속
xhr.send(); // 콜백함수를 총 네 번 호출한다. // (4)
}
RestMemberController
package com.ja.finalproject.member.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
// RestAPI용 controller (AJAX용)
@RestController
@RequestMapping("member/*")
public class RestMemberController {
@RequestMapping("existsUserId")
public String existsUserId() {
System.out.println("테스트!!!");
return "qwer";
}
}
중복확인 버튼을 누르면 페이지가 이동이 되지 않고 자바스크립트로 request한다.
서버 쪽은 웹 브라우저가 자바스크립트로 요청했는지 링크를 이용해서 요청했는지는 관심 없다.
* 중요 *
RestController는 html로 return하지 않는다 (forwarding 하지 않는다) = HTML 화면 리턴 X , 값(글자 그대로)을 리턴
주소 창에 아래 그대로 입력
function checkUserId() {
const userIdValue = document.getElementById("userId").value;
// AJAX api 활용
// 코드 실행 흐름 순서 중요
const xhr = new XMLHttpRequest(); // (1)
// 이 값에 function을 넣을 수 있다. 콜백함수: 내가 만들었지만 내가 호출한 것이 아님.
xhr.onreadystatechange = function () { // (2)
if(xhr.readyState == 4 && xhr.status == 200) {
//(5)
alert(xhr.responseText);
}
};
xhr.open("get", "./existsUserId?userId=" + userIdValue); // (3) 무엇을 호출할 것인지..? requestmapping 된 loginPage 접속
xhr.send(); // 콜백함수를 총 네 번 호출한다. // (4)
}
package com.ja.finalproject.member.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
// RestAPI용 controller (AJAX용)
@RestController
@RequestMapping("/member/*")
public class RestMemberController {
@RequestMapping("existsUserId")
public String existsUserId(String userId) {
System.out.println("테스트!!!");
return "qwer";
}
}
MemberSqlMapper
아래 코드 추가
public int countByUserId(String userId);
MemberSqlMapper.xml
<select id="countByUserId" resultType="int">
SELECT COUNT(*) FROM fp_member WHERE user_id = #{userId}
</select>
MemberServiceImpl
public boolean existsUserId(String userId) {
// return memberSqlMapper.countByUserId(userId) > 0 ? true : false; (삼항 연산자)
int count = memberSqlMapper.countByUserId(userId);
if(count > 0 ) {
return true;
} else {
return false;
}
}
RestController
package com.ja.finalproject.member.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ja.finalproject.member.service.MemberServiceImpl;
// RestAPI용 controller (AJAX용)
// 포워딩하지 않는다. (html 화면 리턴 x), 값을 리턴
// 리턴 타입은 꼭 String이 아니어도 된다.
@RestController
@RequestMapping("/member/*")
public class RestMemberController {
@Autowired
private MemberServiceImpl MemberService;
@RequestMapping("existsUserId")
public boolean existsUserId(String userId) {
System.out.println("테스트");
boolean exists = MemberService.existsUserId(userId);
return exists;
}
}
링크로 테스트할 줄 알아야 한다.
----
JSON 변환기 : Object를 JSON 문자열로 변환시켜준다,
Dto를 출력하면 아래와 같이 나온다.
Dto를 출력하면 아래와 같이JSON 형식으로 나온다.
배열
"aaa"라는 key에 배열
"bbb"라는 key에 Object가 들어있다.
package com.ja.finalproject.member.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ja.finalproject.member.service.MemberServiceImpl;
// RestAPI용 controller (AJAX용)
// 포워딩하지 않는다. (html 화면 리턴 x), 값을 리턴
// 리턴 타입은 꼭 String이 아니어도 된다.
// 일반적으로 리턴 타입은 객체 혹은 컬렉션을 리턴한다. => JSON 변환해서 리턴함
@RestController
@RequestMapping("/member/*")
public class RestMemberController {
@Autowired
private MemberServiceImpl MemberService;
@RequestMapping("existsUserId")
public Map<String, Object> existsUserId(String userId) {
System.out.println("테스트");
boolean exists = MemberService.existsUserId(userId);
Map<String, Object> map = new HashMap<>();
map.put("result", "success");
map.put("data", exists);
return map;
}
}
registerPage.jsp
function checkUserId() {
const userIdValue = document.getElementById("userId").value;
// AJAX api 활용
// 코드 실행 흐름 순서 중요
const xhr = new XMLHttpRequest(); // (1)
// 이 값에 function을 넣을 수 있다. 콜백함수: 내가 만들었지만 내가 호출한 것이 아님.
xhr.onreadystatechange = function () { // (2)
if(xhr.readyState == 4 && xhr.status == 200) {
//(5)
const response = JSON.parse(xhr.responseText);
// js로 논리 코드 및 DOM 조작
if(response.data == true) {
alert("이미 존재하는 아이디입니다.");
} else {
alert("사용 가능한 아이디입니다.");
}
}
};
xhr.open("get", "./existsUserId?userId=" + userIdValue); // (3) 무엇을 호출할 것인지..? requestmapping 된 loginPage 접속
xhr.send(); // 콜백함수를 총 네 번 호출한다. // (4)
}
아이디 중복체크 로직
registerPage.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script>
function checkValueAndSubmit() {
const userIdBox = document.getElementById("userId");
const idValue = userIdBox.value;
const idRegEx = /^[a-zA-Z][a-zA-Z0-9]{4,12}$/;
// idValue가 정규표현식에 적합하지 않으면
if (!idRegEx.test(idValue)) {
alert("아이디는 영소문자로 시작해야하고 영소문자, 대문자, 숫자로만 4~12글자이어야 합니다.");
userIdBox.focus();
return; // return;을 해줘야 submit이 발동되지 않는다. (주의!)
}
const userPwBox = document.getElementById("userPw");
const userPwConfirmBox = document.getElementById("userPwConfirm");
if(userPwBox.value != userPwConfirmBox.value) {
alert("입력한 비밀번호를 다시 확인해주세요.")
userPwBox.value = "";
userPwConfirmBox.value = "";
userPwBox.focus();
return;
}
const pwRegEx = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[!@#$%^&*()_+])[a-zA-Z\d!@#$%^&*()_+]{8,16}$/;
if(!pwRegEx.test(userPwBox.value)){
alert("비밀번호는.... 어쩌고 8-16 글짜.. 블라블라..");
userPwBox.value = "";
userPwConfirmBox.value = "";
userPwBox.focus();
return;
}
if(idChecked == false) {
alert("아이디 중복확인을 해주세요");
return;
}
const frm = document.getElementById("frm");
frm.submit();
}
// 값이 중간에 바뀔 것이므로 const로 선언하면 안된다.
let idChecked = false;
function checkUserId() {
const userIdValue = document.getElementById("userId").value;
// AJAX api 활용
// 코드 실행 흐름 순서 중요
const xhr = new XMLHttpRequest(); // (1)
// 이 값에 function을 넣을 수 있다. 콜백함수: 내가 만들었지만 내가 호출한 것이 아님.
xhr.onreadystatechange = function () { // (2)
if(xhr.readyState == 4 && xhr.status == 200) {
//(5)
const response = JSON.parse(xhr.responseText);
// js로 논리 코드 및 DOM 조작
if(response.data == true) {
alert("이미 존재하는 아이디입니다.");
idChecked = false;
} else {
alert("사용 가능한 아이디입니다.");
idChecked = true;
}
}
};
xhr.open("get", "./existsUserId?userId=" + userIdValue); // (3) 무엇을 호출할 것인지..? requestmapping 된 loginPage 접속
xhr.send(); // 콜백함수를 총 네 번 호출한다. // (4)
}
</script>
</head>
<body>
<h1>회원 가입</h1>
<form id="frm" action="./registerProcess" method="post">
ID: <input id="userId" type="text" name="user_id">
<input onclick="checkUserId()" type="button" value="중복확인">
<br>
PW: <input id="userPw" type="password" name="user_pw"><br>
PW 확인: <input id="userPwConfirm" type="password"><br>
nickname: <input type="text" name="nickname"><br>
gender:
<input type="radio" name="gender" value="M">남
<input type="radio" name="gender" value="F">여 <br>
취미:
<c:forEach items="${hobbyList}" var="hobby">
<input type="checkbox" name="hobby_id" value="${hobby.id}"> ${hobby.name}
</c:forEach>
<br>
email: <input type="text" name="email"><br>
생년월일: <input type="date" name="birth"><br>
전화번호: <input type="text" name="phone"><br>
<input type="button" value="회원가입" onclick="checkValueAndSubmit()">
</form>
<a href="./loginPage">로그인 페이지로 이동</a>
</body>
</html>
'Back-End > Spring' 카테고리의 다른 글
[Spring] 예제3 - AJAX를 이용한 게시글 좋아요 구현 (0) | 2023.05.25 |
---|---|
[Spring] 예제 3 - 렌더링 (0) | 2023.05.25 |
[Spring] 예제 3 - 회원가입 유효성 검사 (0) | 2023.05.25 |
[Spring] 예제 2 - resources 경로 이미지 (0) | 2023.05.24 |
[Spring] 예제 2 - Interceptor (0) | 2023.05.24 |