[PHP, MySQL] 로그인 및 회원가입 폼 만들기 - 2

Tim·2022년 2월 7일
1

PHP

목록 보기
3/3
post-thumbnail

이번 포스팅에선 자바스크립트를 이용한 사용자 입력값 체크(유효성 검사 validation check)에 대해 알아보겠습니다.

회원가입을 진행 시 "아이디를 입력해주세요.", "비밀번호는 6자 이상 20자 이하로 입력해주세요.", "핸드폰 번호 형식이 맞지않습니다.", "중복된 아이디입니다." 등을 보셨을 겁니다. 이와 같은 체크를 간단한 방법으로 입력값 유효성 검사를 하는 방법을 알아보겠습니다.

1. 유효성 검사 - 입력값 체크

먼저 이전에 만든 regist.php의 form 태그에을 작성해 줍니다.

sendit 함수를 이용하여 각 input value를 체크하고 boolean값을 리턴하여 submit을 제어할 겁니다.

// regist.php
<form action="regist_ok.php" method="post" name="regiform" id="regist_form" class="form" onsubmit="return sendit()">

그 다음 sendit 함수를 작성할 자바스크립트 파일을 만들어 준 뒤 코드를 작성해 줍니다. (regist.js)

1. 제일 먼저 각각의 input들을 변수에 대입해준 뒤 해당 값(value)이 비어있는지('')를 확인하고 true라면 알림창을 띄운 뒤 해당 input 창으로 포커스를 맞추고 sendit에 false를 리턴하게 됩니다.

2. 각 입력창의 공백 체크를 확인했다면 다음으로는 아이디 및 비밀번호 문자열 길이 체크를 해주고 비밀번호와 비밀번호 확인이 같은 문자열인지 체크해 줍니다.

3. 이름, 핸드폰번호, 이메일은 형식에 따른 체크를 진행해야 합니다. 각각의 정규식들을 변수에 담고 test() 메소드를 사용하여 각각의 값(value)들과 정규식이 같은지 체크를 해줍니다.

4. userhobby와 같이 여러개의 체크를 해야하는 경우에는 1개 이상 체크가 되었을 시 상태 확인을 할 flag 변수를 만들어 줍니다. 반복문을 통하여 체크박스가 checked 된 값들이 1개라도 있다면 flag 변수에 true를 넣어준 뒤 반복문을 빠져나옵니다.

// regist.js
const sendit = () => {
	// Input들을 각각 변수에 대입
    const userid = document.regiform.userid;
	const userpw = document.regiform.userpw;
    const userpw_ch = document.regiform.userpw_ch;
    const username = document.regiform.username;
    const userphone = document.regiform.userphone;
    const useremail = document.regiform.useremail;
    const userhobby = document.regiform.hobby;
    
    // userid값이 비어있으면 실행.
    if(userid.value == '') {
        alert('아이디를 입력해주세요.');
        userid.focus();
        return false;
    }
    // userid값이 4자 이상 12자 이하를 벗어나면 실행.
    if(userid.value.length < 4 || userid.value.length > 12){
        alert("아이디는 4자 이상 12자 이하로 입력해주세요.");
        userid.focus();
        return false;
    }
    // userpw값이 비어있으면 실행.
    if(userpw.value == '') {
        alert('비밀번호를 입력해주세요.');
        userpw.focus();
        return false;
    }
    // userpw_ch값이 비어있으면 실행.
    if(userpw_ch.value == '') {
        alert('비밀번호 확인을 입력해주세요.');
        userpw_ch.focus();
        return false;
    }
    // userpw값이 6자 이상 20자 이하를 벗어나면 실행.
    if(userpw.value.length < 6 || userpw.value.length > 20){
        alert("비밀번호는 6자 이상 20자 이하로 입력해주세요.");
        userpw.focus();
        return false;
    }
	// userpw값과 userpw_ch값이 다르면 실행.
    if(userpw.value != userpw_ch.value) {
        alert('비밀번호가 다릅니다. 다시 입력해주세요.');
        userpw_ch.focus();
        return false;
    }
    // username값이 비어있으면 실행.
    if(username.value == '') {
        alert('이름을 입력해주세요.');
        username.focus();
        return false;
    }
    // 한글 이름 형식 정규식
    const expNameText = /[가-힣]+$/;
    // username값이 정규식에 부합한지 체크
    if(!expNameText.test(username.value)){
        alert("이름 형식이 맞지않습니다. 형식에 맞게 입력해주세요.");
        username.focus();
        return false;
    }
    // userphone값이 비어있으면 실행.
    if(userphone.value == '') {
        alert('핸드폰 번호를 입력해주세요.');
        userphone.focus();
        return false;
    }
    // 핸드폰 번호 형식 정규식
    const expHpText = /^\d{3}-\d{3,4}-\d{4}$/;
    // userphone값이 정규식에 부합한지 체크
    if(!expHpText.test(userphone.value)) {
        alert('핸드폰 번호 형식이 맞지않습니다. 형식에 맞게 입력해주세요.');
        hp.focus()
        return false;
    }
    // useremail값이 비어있으면 알림창을 띄우고 input에 포커스를 맞춘 뒤 False를 리턴한다.
    if(useremail.value == '') {
        alert('이메일을 입력해주세요.');
        useremail.focus();
        return false;
    }
	// 이메일 형식 정규식
    const expEmailText = /^[A-Za-z0-9\.\-]+@[A-Za-z0-9\.\-]+\.[A-Za-z0-9\.\-]+$/;
    // useremail값이 정규식에 부합한지 체크
    if(!expEmailText.test(useremail.value)) {
        alert('Please check the format your E-mail.');
        useremail.focus();
        return false;
    }
    // userhobby를 하나 이상 선택 시 체크할 flag 변수 지정
    let flag = false;
    // userhobby를 하나 이상 선택 시 flag값에 true 대입
    for(let i=0; i < userhobby.length; i++) {
        if(userhobby[i].checked) {
            flag = true;
            break;
        }
        
    }
    // flag값이 false일 때(userhobby를 체크하지 않았을 때) 실행.
    if(!flag){
		alert("취미는 1개 이상 선택해주세요.");
        return false;
    }
	// 유효성 검사 정상 통과 시 true 리턴 후 form 제출.
    return true;
}

작성을 전부한 뒤 회원가입 폼에서 가입하기 버튼을 누르면 아래와 같이 알림창이 뜨며 해당 input으로 포커스가 맞춰지는걸 확인하실 수 있습니다.

2. 유효성 검사 - 아이디 중복 체크

아이디 중복 체크는 DB(MySQL)에 들어있는 유저 데이터들의 아이디값과 입력된 아이디값을 비교하여 체크하는 방식으로 Ajax를 사용하여 유효성 검사를 진행하겠습니다.

먼저 비교할 테스트용 데이터를 데이터베이스에 넣겠습니다.
(MySQLWorkbench를 사용하면 수월하게 쿼리문을 작성하여 데이터를 집어넣을 수 있습니다.)

insert into tb_user (userid, userpw, username, userphone,
useremail, userhobby) values('test', '12341234', '테스트', '01011111111', 'test@test.com',
'코딩');

insert 쿼리문을 실행시킨 뒤 select * from tb_user; 를 사용하여 테이블을 확인하면 아래와 같이 데이터가 잘 들어가는걸 확인할 수 있습니다.

테스트 데이터가 잘 들어간걸 확인했으면 아이디 중복체크를 위한 버튼과 내용이 표시되는 텍스트 영역을 아이디 input에 만들어 줍니다.(regist.php)

1. 아이디 input 바로 옆에 button input를 만들어준 뒤 id="checkIdBtn" value="check"를 입력해 줍니다.

2. 아이디를 감싼 p태그 바로 아래에 중복 아이디 체크 시 표시될 내용을 넣기 위한 p태그를 넣어줍니다. 태그를 빈 칸으로 놔둘 시 해당 영역이 레이아웃에 영향을 주기 때문에  (띄어쓰기 1칸)을 작성해줍니다. (작성하지 않아도 되는 레이아웃이라면 빈칸으로 놔둬도 무방합니다.)

<!-- regist.php -->
<p><input type="text" name="userid" id="userid" placeholder="ID"><input type="button" id="checkIdBtn" value="check" onclick="checkId()"></p>
<p id="result">&nbsp;</p>

태그를 작성하였다면 예쁘게 만들기 위해 css 파일(style.css)에 넣을 내용들을 작성해줍니다.

/* style.css */
/* 아이디 input 바로 옆에 붙이기 위해 너비 크기 조정 */
#regist_wrap #regist_form input#userid {
    width: 345px;
}
/* 체크 버튼 스타일 지정 */
#regist_wrap #regist_form input#checkIdBtn {
    position: relative;
    top: -2px;
    width: 50px;
    margin-left: 0;
    padding-left: 0;
    border: 0;
    box-sizing:content-box;
    background: linear-gradient(to left, #f857a6, #ff5858);
    font-size: 12px;
    font-weight: bold;
    color: #fff;
    cursor: pointer;
}
/* 체크 시 표시될 영역 비표시(자바스크립트로 제어) */
#regist_wrap #regist_form #result {
    display: none;
}

모든 준비가 끝났다면 자바스크립트 파일에서 Ajax를 사용하여 아이디 중복체크를 진행해 줍니다.(regist.js)

1. 아이디를 입력하지 않은 채 중복체크 버튼을 클릭하는 상황을 막기 위해 다시한번 입력값 체크를 진행해 줍니다.

2. Ajax를 사용한 아이디 중복 체크를 진행해줍니다. XMLHttpRequest의 메소드 중 open() 메소드의 형식을 지정해 줍니다.
open("전달방식", "URL 주소", 동기여부);
저는 url 주소에 데이터를 따로 처리할 checkId_ok.php페이지에 파라미터로 userid의 값을 넣어주도록 "checkId_ok.php?userid="+userid.value"를 입력해 주겠습니다.

3. checkId_ok.php에서 리턴받은 값("O" or "X")을 txt 변수에 담아줍니다.(xhr.responseText.trim();)
혹시 모를 공백을 제거하기 위해 trim() 메소드를 사용해 줍니다.
txt가 "O"면 아이디가 존재하지 않기 때문에 "사용할 수 있는 아이디입니다."를 출력해 주고, "X"면 아이디가 존재하기 때문에 "중복된 아이디입니다."를 출력해 줍니다.

// regist.js
const checkId = () => {
	// userid, result 변수에 대입
    const userid = document.regiform.userid;
    const result = document.querySelector('#result');
    
    // 중복체크 시에 한번 더 userid 입력값 체크
    if(userid.value == '') {
        alert('아이디를 입력해주세요.');
        userid.focus();
        return false;
    }
    if(userid.value.length < 4 || userid.value.length > 12){
        alert("아이디는 4자 이상 12자 이하로 입력해주세요.");
        userid.focus();
        return false;
    }
    
    // Ajax를 사용한 아이디 중복 체크
    const xhr = new XMLHttpRequest();
    xhr.onreadystatechange = () => {
        if(xhr.readyState == XMLHttpRequest.DONE) {
            if(xhr.status == 200) {
                let txt = xhr.responseText.trim();
                if(txt == "O") {
                    result.style.display = "block";
                    result.style.color = "green";
                    result.innerHTML = "사용할 수 있는 아이디입니다.";
                } else {
                    result.style.display = "block";
                    result.style.color = "red";
                    result.innerHTML = "중복된 아이디입니다.";
                    userid.focus();
                    // 키 입력 시 result 숨김 이벤트
                    userid.addEventListener("keydown", function(){
                        result.style.display = "none";
                    });
                }
            }
        }
    }
    xhr.open("GET", "checkId_ok.php?userid="+userid.value, true);
    xhr.send();
}

Ajax로 보낸 데이터를 처리하기 위한 checkId_ok.php와 mysql과 연결을 위한 sql_conn.php를 만들어 줍니다.

1. mysqli_connect에 들어갈 아이디와 비밀번호, 데이터베이스명을 적어 줍니다.(꼭 설정하신 아이디와 비밀번호를 입력해줍니다!) 그리고 php의 명령어인 or를 사용하여 데이터베이스에 접속이 실패할 시 띄워줄 명령어를 작성해 줍니다.

2. sql_conn.php 설정이 완료되었다면 checkId_ok.php에서 sql_conn.php를 include 해줍니다.

3. Ajax에서 파라미터로 보낸 userid를 GET방식으로 받아와서 변수에 담아주고 쿼리문을 작성해 줍니다.
데이터베이스에서 검색을 해야하기 때문에 select문으로 받아온 $userid 변수와 비교하여 존재하는 유저의 인덱스번호를 가져오도록 작성해 줍니다.
작성한 쿼리문을 mysqli_query에 담아주어 실행시킵니다. 실행 후 리턴받은 데이터를 mysqli_fetch_array 함수에 담아줍니다. (mysqli_fetch_array 함수는 mysqli_query 를 통해 얻은 리절트 셋(result set)에서 레코드를 1개씩 리턴해주는 함수입니다.)
isset 메소드를 사용하여 유저의 인덱스번호가 존재하는지 검사 후 있으면 "X", 없으면 "O"를 리턴해 줍니다.

<!-- sql_conn.php -->
<?php
    $conn = mysqli_connect('127.0.0.1', '아이디', '비밀번호', '데이터베이스명') or die('데이터베이스가 없습니다.');
?>


<!-- checkId_ok.php -->
<?php
    include './lib/include/sql_conn.php';

    $userid = $_GET['userid'];
    $sql = "select useridx from tb_user where userid='$userid'";
    $result = mysqli_query($conn, $sql);
    $data = mysqli_fetch_array($result);

    echo isset($data['useridx']) ? "X" : "O";
?>

정상적으로 코드를 작성했다면 아래와 같이 나오는 것을 확인하실 수 있습니다^^ 수고하셨습니다~!

profile
HTML5, CSS3, JavaScript, Typescript, React 프론트엔드 개발자입니다.

0개의 댓글