MyBatis + MVC 실습 (3) : 회원가입

이제 회원가입이다!

아래와 같은 폼을 구성한 후 기능을 만들어 보자.

 

 

 

 

우선 데이터를 받아주고 관리하기 위해 아래와 같은 MemberVO를 생성한다.

동일한 형태로 Oracle 데이터테이블도 생성한다.

 

MemberVO

package doodoo.vo;
public class MemberVO {
  private String id, pwd, name, sex, birthday, email, post, addr1, addr2, tel, content, admin, login;
  private String tel1, tel2; //받을 때는 tel1, tel2 따로 받고 묶어서 한번에 처리할것임
  private String msg;
}

폼에서 보이듯 010은 고정되어 있고 이후 뒷자리를 입력받도록 만들어져 있다.

따라서 tel1 에는 010을 고정적으로 넣고, tel2에 사용자가 입력한 값을 넣은 뒤,

데이터베이스에는 tel1과 tel2를 묶어 하나의 tel로 처리하여 입력할 것이다.

 

 

중복 체크 기능

 

회원 가입에서는 아이디와 이메일, 휴대전화번호의 중복 체크 기능이 가장 중요하다.

이후 아이디나 비밀번호 찾기 기능에서도 이런 고유한 값을 사용할 것이다!

 

사실 아이디, 이메일, 휴대전화번호 모두 중복 체크 로직은 동일하므로

하나의 흐름을 파악하면 다른 입력값을 체크하는 것도 비슷하게 처리할 수 있다.

 

전체적인 흐름은 아래처럼 나타낼 수 있다.

 

 

참고로, 아이디 중복체크의 경우 별도의 jsp 페이지를 만들고,

이를 ajax 팝업 라이브러리 중 하나인 shadow-box 로 띄워 처리해 줄 것이다!

 

 

나머지도 다 반복이므로 설명 생략~

 

 

member-mapper

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sist.mapper.member-mapper">
  <!-- 회원 가입(아이디 중복체크) 1이면 중복, 0이면 OK -->
  <select id="memberIdCheck" resultType="int" parameterType="String">
  	SELECT COUNT(*) FROM project_member
	WHERE id=#{id}
  </select>
  <!-- 회원 가입(이메일 중복체크) -->
  <select id="memberEmailCheck" resultType="int" parameterType="String">
	SELECT COUNT(*) FROM project_member
	WHERE email=#{email}
  </select>
  <!-- 회원 가입(전화번호 중복체크) -->
  <select id="memberTelCheck" resultType="int" parameterType="String">
 	SELECT COUNT(*) FROM project_member
	WHERE tel=#{tel}
  </select>
  <!-- 회원 가입 -->
  <insert id="memberInsert" parameterType="MemberVO">
	INSERT INTO project_member(id,pwd,name,sex,birthday,email,post,addr1,addr2,tel,content) 
	VALUES(#{id},#{pwd},#{name},#{sex},#{birthday},#{email},#{post},#{addr1},#{addr2},#{tel},#{content})
  </insert>
</mapper>

 

DAO

package doodoo.dao;
import doodoo.vo.*;

import java.io.*;
import java.util.*;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MemberDAO {
  private static SqlSessionFactory ssf;
  static {
    try {
      Reader reader = Resources.getResourceAsReader("Config.xml");
      ssf = new SqlSessionFactoryBuilder().build(reader);
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
  //회원가입-아이디 중복체크
  public static int memberIdCheck(String id) {
    int count = 0;
    SqlSession session = null;
    try {
      session = ssf.openSession();
      count = session.selectOne("memberIdCheck", id);
    } catch (Exception ex) {
      ex.printStackTrace();
      System.out.println("MemberDAO: memberIdCheck(String id) ERROR");
    } finally {
      if (session != null)
        session.close();
    }
    return count;
  }
  //회원가입-이메일 중복체크
  public static int memberEmailCheck(String email) {
    int count = 0;
    SqlSession session = null;
    try {
      session = ssf.openSession();
      count = session.selectOne("memberEmailCheck", email);
    } catch (Exception ex) {
      ex.printStackTrace();
      System.out.println("MemberDAO: memberEmailCheck(String email) ERROR");
    } finally {
      if (session != null)
        session.close();
    }
    return count;
  }
  //회원가입-전화번호 중복체크
  public static int memberTelCheck(String tel) {
    int count = 0;
    SqlSession session = null;
    try {
      session = ssf.openSession();
      count = session.selectOne("memberTelCheck", tel);
    } catch (Exception ex) {
      ex.printStackTrace();
      System.out.println("MemberDAO: memberTelCheck(String tel) ERROR");
    } finally {
      if (session != null)
        session.close();
    }
    return count;
  }
  //회원가입 INSERT
  public static void memberInsert(MemberVO vo) {
    SqlSession session = null;
    try {
      session = ssf.openSession(true); //AutoCommit
      session.insert("memberInsert", vo);
    } catch (Exception ex) {
      ex.printStackTrace();
      System.out.println("MemberDAO: memberInsert(MemberVO vo) ERROR");
    } finally {
      if (session != null)
        session.close();
    }
  }
}

 

 

Model

package doodoo.model;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import controller.Controller;
import controller.RequestMapping;

import doodoo.dao.*;
import doodoo.vo.MemberVO;

@Controller
public class MemberModel {
  //회원가입-아이디 중복체크
  @RequestMapping("member/idcheck.do")
  public String member_idcheck(HttpServletRequest request, HttpServletResponse response) {
    //화면 출력만 해줌
    return "../member/idcheck.jsp";
  }
  @RequestMapping("member/idcheck_ok.do")
  public String member_idcheck_ok(HttpServletRequest request, HttpServletResponse response) {
    String id = request.getParameter("id");
    int count = MemberDAO.memberIdCheck(id);
    request.setAttribute("count", count);
    return "../member/idcheck_ok.jsp";
  }
  @RequestMapping("member/emailcheck_ok.do")
  public String member_emailcheck_ok(HttpServletRequest request, HttpServletResponse response) {
    String email = request.getParameter("email");
    int count = MemberDAO.memberEmailCheck(email);
    request.setAttribute("count", count);
    return "../member/idcheck_ok.jsp";
  }
  @RequestMapping("member/tel_check.do")
  public String member_telcheck(HttpServletRequest request, HttpServletResponse response) {
    String tel = request.getParameter("tel");
    int count = MemberDAO.memberTelCheck(tel);
    request.setAttribute("count", count);
    return "../member/idcheck_ok.jsp";
  }
  //화면 출력만 해줌
  @RequestMapping("member/login.do")
  public String member_login(HttpServletRequest request, HttpServletResponse response) {
    return "../member/login.jsp"; //main에 출력하는거 아님! shadowBox에 올릴것임. -> shadowBox 안에서 처리를 해야 한다.
  }
  @RequestMapping("member/join.do")
  public String member_join(HttpServletRequest request, HttpServletResponse response) {
    request.setAttribute("main_jsp", "../member/join.jsp");
    return "../main/main.jsp";
  }

  @RequestMapping("member/join_ok.do")
  public String member_join_ok(HttpServletRequest request, HttpServletResponse response) {
    //사용자 전송값 받기
    try {
      request.setCharacterEncoding("UTF-8");
    } catch (Exception ex) {
      ex.printStackTrace();
    }
    String id = request.getParameter("id");
    String pwd = request.getParameter("pwd");
    String name = request.getParameter("name");
    String sex = request.getParameter("sex");
    String birthday = request.getParameter("birthday");
    String email = request.getParameter("email");
    String post = request.getParameter("post");
    String addr1 = request.getParameter("addr1");
    String addr2 = request.getParameter("addr2");
    String tel1 = request.getParameter("tel1");
    String tel2 = request.getParameter("tel2");
    String content = request.getParameter("content");

    MemberVO vo = new MemberVO();
    vo.setId(id);
    vo.setPwd(pwd);
    vo.setName(name);
    vo.setSex(sex);
    vo.setBirthday(birthday);
    vo.setEmail(email);
    vo.setPost(post);
    vo.setAddr1(addr1);
    vo.setAddr2(addr2);
    vo.setTel(tel1 + "-" + tel2);
    vo.setContent(content);
    //데이터베이스 연결+요청 처리
    MemberDAO.memberInsert(vo);
    //화면 이동
    return "redirect:../main/main.do"; //redirect는 .do로 보낸다. 
    //이 처리로 인해 보여줄 게 없고 새로운 request를 받아 와야 할 때...(자바를 거쳐야 할 때) 화면만 이동할 때.
    //insert나 update는 redirect로 보낸다. 왜? -> 화면 출력이 필요 없음 -> request 보존할 필요 없음 
    //forward 화면 안에 출력할 내용이 있음 -> request 보존해야함
  }
  }
}

request를 보존할 필요 없이 화면 이동만 해야할 경우에는 redirect:..을 붙여 리턴한다.

이 약속은.. 여기서 한 약속이므로 얼마든지 다르게 구현할 수 있는 부분이다.

 

 

 

idcheck_ok.jsp, email_check.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
${count}

 

 

idcheck.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<style type="text/css">
  .container{
  margin-top:30px;
  width:350px;
  }
  .row{
  margin: 0px auto;
  width: 100%;
  }
</style>
<script type="text/javascript" src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript">
$(function(){ //main 메서드
  $('#cBtn').click(function(){
    let id=$('#id').val();
    if(id.trim()==""){
      $('#id').focus();
      return;
    }
    //전송해서 결과값 받아오기~
    $.ajax({
      type: 'post',
      url: '../member/idcheck_ok.do',
      data: {"id":id}, //?id=id 랑 같은것임
      success:function(result){
      /*let res = httpRequest.responseText, responseXML 이런거랑 같은것임 */
        console.log(result);
        let count = parseInt(result.trim());//정수형으로 변경
        console.log(count);
        if(count===0){
          $('#print').html("<span style='color:blue'>"+id+"는(은) 사용가능한 ID입니다.</span>");
          $('#okTr').show();
          $('#id').attr("disabled",true);
        }else{
          $('#print').html("<span style='color:red'>"+id+"는(은) 이미 사용중입니다.</span>");
          $('#id').val("");
          $('#id').focus();
          //text를 주게 되면 문자열로 그냥 출력해 버림
        }
      }
    })
  })
  $('#okBtn').on("click",function(){
    parent.join_frm.id.value=$('#id').val();
    parent.Shadowbox.close();
  })
})
</script>
</head>
<body>
  <div class="container">
    <div class="row">
      <table class="table">
        <tr>
          <td>
           입력:<input type=text name=id id=id size=15 class="input-sm">
           <input type=button value="중복체크" class="btn btn-sm btn-primary" id="cBtn">
          </td>
        </tr>
        <tr>
          <td class="text-center">
            <span id="print"></span>
          </td>
        </tr>
        <tr id="okTr" style="display:none">
          <td class="text-center" >
            <input type=button class="btn btn-sm btn-primary" value="확인" id="okBtn">
          </td>
        </tr>
      </table>
    </div>
  </div>
</body>
</html>

 

 

join.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>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
</head>
<body>
<div class="wrapper row3">
  <div id="breadcrumb" class="clear"> 
    <ul>
      <li>회원 가입</li>
    </ul>
   </div>
  </div>
  <div class="wrapper row3 row">
   <main class="container clear">
   <h2 class="sectiontitle">회원가입</h2>
   <form method="post" action="../member/join_ok.do" name="join_frm" id="join_frm">
    <table class="table">
      <tr>
       <th class="text-right" width=15%>아이디</th>
       <td width=85% class="inline">
         <input type=text name=id id="join_id" size=30 class="input-sm" readonly>
         <input type=button id="checkBtn" value="아이디중복체크" class="btn btn-sm btn-primary">
       </td>
      </tr>
      <tr>
       <th class="text-right" width=15%>비밀번호</th>
       <td width=85% class="inline">
         <input type=password name=pwd id=join_pwd size=30 class="input-sm">
         &nbsp;&nbsp;재입력:
         <input type=password name=pwd1 id=pwd1 size=30 class="input-sm">
       </td>
      </tr>
      <tr>
       <th class="text-right" width=15%>이름</th>
       <td width=85%>
         <input type=text name=name id=name size=30 class="input-sm">
       </td>
      </tr>
      <tr>
       <th class="text-right" width=15%>성별</th>
       <td width=85% class="inline">
         <input type=radio value="남자" name=sex checked="checked">남자
         <input type=radio value="남자" name=sex>여자
       </td>
      </tr>
      <tr>
       <th class="text-right" width=15%>생년월일</th>
       <td width=85%>
         <input type=date size=30 name=birthday class="input-sm" id="day">
       </td>
      </tr>
      <tr>
       <th class="text-right" width=15%>이메일</th>
       <td width=85% class="inline">
         <input type=text name=email id=email size=70 class="input-sm">
         <input type=button id="eBtn" class="btn btn-sm btn-success" value="이메일 확인">
         &nbsp;<span style="color:blue;" id="ePrint"></span>
       </td>
      </tr>
      <tr>
       <th class="text-right" width=15%>우편번호</th>
       <td width=85% class='inline'>
         <input type=text name=post id=post size=30 class="input-sm" readonly>
         <input type=button id="postBtn" value="우편번호찾기"
          class="btn btn-sm btn-danger">
       </td>
      </tr>
      <tr>
       <th class="text-right" width=15%>주소</th>
       <td width=85%>
         <input type=text name=addr1 id=addr1 size=95 class="input-sm" readonly>
       </td>
      </tr>
      <tr>
       <th class="text-right" width=15%>상세주소</th>
       <td width=85%>
         <input type=text name=addr2 id=addr2 size=95 class="input-sm">
       </td>
      </tr>
      <tr>
       <th class="text-right" width=15%>전화번호</th>
       <td width=85% class="inline">
         <input type=text name=tel1 id=tel1 size=15 class="input-sm" value="010">
         <input type=text name=tel2 id=tel2 size=30 class="input-sm">
         <input type=button id="tBtn" class="btn btn-sm btn-info" value="전화 확인">
         &nbsp;<span style="color:blue;" id="tPrint"></span>
       </td>
      </tr>
      <tr>
       <th class="text-right" width=15%>소개</th>
       <td width=85%>
         <textarea rows="10" cols="100" id="content" name="content"></textarea>
       </td>
      </tr>
      <tr>
        <td colspan="2" class="text-center">
         <input type=button class="btn btn-sm btn-primary" value="회원가입" id="joinBtn">
         <input type=button class="btn btn-sm btn-danger" value="취소" onclick="javascript:history.back()">
        </td>
      </tr>
    </table>
    </form>
   </main>
  </div>
</body>
</html>

 

 

*join.jsp의 <script> 내의 javascript 코드

<script type="text/javascript" src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
<script type="text/javascript">
Shadowbox.init({
  players:['iframe']
})
$(function(){
  $('#checkBtn').click(function(){
    Shadowbox.open({
      content: '../member/idcheck.do',
      player: 'iframe', //전체파일 위에 띄워주는것
      title: '아이디 중복체크',
      width: 360,
      height: 200
    })
  })
  $('#postBtn').click(function(){
    // 우편번호 검색 처리 
    new daum.Postcode({
      oncomplete:function(data)
      {
        $('#post').val(data.zonecode)
        $('#addr1').val(data.address)
      }
    }).open()
  })
  //유효성 검사!
  /*$('#joinBtn').click(function(){
    
  })*/
  $('#eBtn').click(function(){
    let email=$('#email').val();
    if(email.trim()==""){
      $('#email').focus();
      $('#ePrint').text("이메일을 입력하세요~");
      return;
    }
    $.ajax({
      type:'post',
      url:'../member/emailcheck_ok.do',
      data:{"email":email},
      success:function(result){
        console.log(result);
        let count=parseInt(result.trim());
        if(count==0){
          $('#ePrint').text("사용가능한 이메일입니다.");
          $('#email').attr('disable','true');
        }else{
          $('#ePrint').text("사용중인 이메일입니다.");
          $('#email').val("");
          $('#email').focus();
        }
      }
    })
  })
  $('#tBtn').click(function(){
    let tel=$('#tel2').val();
    if(tel.trim()==""){
      $('#tel2').focus();
      $('#tPrint').text("전화번호를 입력하세요.");
      return;
    }
    $.ajax({
      type:'post',
      url:'../member/tel_check.do',
      data:{"tel":"010-"+tel},
      success:function(result){
        console.log(result);
        let count=parseInt(result.trim());
        if(count==0){
          $('#tPrint').text("사용가능한 전화번호입니다.");
          $('#tel').attr('disable','true');
        }else{
          $('#tPrint').text("사용중인 전화번호입니다.");
          $('#tel').val("");
          $('#tel').focus();
        }
      }
    })
  })
  $('#joinBtn').click(function(){
    //체크는 끝났다는 가정 하에 진행
    $('#join_frm').submit();
  })
})
</script>

댓글()