관리 메뉴

거니의 velog

(5) 로그인 페이지 > 코드 리뷰 본문

대덕인재개발원_최종 포트폴리오

(5) 로그인 페이지 > 코드 리뷰

Unlimited00 2024. 2. 15. 12:33

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set value="${pageContext.request.contextPath }" var="contextPath" />
<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="UTF-8" />
        <meta name="author" content="부루마불" />
        <meta name="description" content="대덕인재개발원 7월반 4조 부루마불의 여기갈래 프로젝트입니다." />
        <meta name="keywords" content="부루마불, 여기갈래, 여행, 통합, 플랫폼" />
        <meta name="copyright" content="대덕인재개발원" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>여기갈래 &gt; 로그인</title>
        <link href="${contextPath }/resources/images/favicon.ico" rel="shoutcut icon" />
        <!-- 공통 css -->
        <link href="${contextPath }/resources/css/login.css" rel="stylesheet" />
        <!-- 제이쿼리 -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
        <!-- 공통 js -->
        <script defer src="${contextPath }/resources/js/util.js"></script>
        <script defer src="${contextPath }/resources/js/login.js"></script>
        <!-- 부트스트랩 모듈 -->
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" />
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
        <!-- 스위트 얼럿 모듈 -->
    	<link href="${contextPath }/resources/css/sweetalert2.min.css" rel="stylesheet" />
    	<script defer src="${contextPath }/resources/js/sweetalert2.all.min.js"></script>
    	<!-- sockjs -->
		<script src="${contextPath }/resources/js/sockjs.min.js"></script>

        <c:if test="${not empty message }">
		    <script>
	        	//alert("${message}");
		        $(function(){
		        	// 성공시
		        	<c:if test="${msgflag eq 'su'}">
		        		Swal.fire({
		                    title: "성공",
		                    text: "${message}",
		                    icon: "success"
		                });
		        	</c:if>
		        	// 실패시
		        	<c:if test="${msgflag eq 'fa'}">
			        	Swal.fire({
		                    title: "실패",
		                    text: "${message}",
		                    icon: "error"
		                });
		        	</c:if>
		        	// 정보성 메시지
		        	<c:if test="${msgflag eq 'in'}">
			        	Swal.fire({
		                    title: "안내",
		                    text: "${message}",
		                    icon: "info"
		                });
		        	</c:if>
		        });
		        <c:remove var="message" scope="request" />
		        <c:remove var="message" scope="session" />
		    </script>
		</c:if>
		
		<c:if test="${not empty errors && msgflag eq 'in'}">
		    <script>
		        // alert("${errors}"); 
			    $(function(){
		        	Swal.fire({
	                    title: "서버오류",
	                    text: "${errors}",
	                    icon: "error"
	                });
			    });
		    	<c:remove var="errors" scope="request" />
		    	<c:remove var="errors" scope="session" />
		    </script>
		</c:if>

    </head>

    <body class="scroll">
        <section id="loginContainer">
            <article>
                <h1>
                    <a href="/index.do">
                        <img src="${contextPath }/resources/images/logo.png" alt="메인 로고" />
                    </a>
                </h1>
                <div class="loginBox">
                    <h2>여기갈래</h2>
                    <p>Travel Integration Platform System</p>
                    <form action="/login/loginCheck.do" id="loginForm" name="loginForm" method="post">
                        <input class="form-control" type="text" id="memId" name="memId" placeholder="아이디" autocomplete="off" value="${member.memId }" />
                        <input class="form-control" type="password" id="memPw" name="memPw" placeholder="비밀번호" autocomplete="off" value="${member.memPw }" />
                        <div>
                            <a href="/login/signup.do">회원가입</a>
                            <a href="/login/findIdPw.do">ID/비밀번호 찾기</a>
                        </div>
                        <button class="btn btn-success" type="button" id="loginBtn">로그인</button>
                    </form>
                    <p class="testBtnShow">
                        Copyright &copy; 2023. Burumabool. All right reserved.
                        <br />
                        YOgIGaLE v.2.1
                    </p>
                </div>
                <div class="testBtnGroup">
                 	<div>
	                	<button class="btn btn-primary" type="button" id="adminAccount">관리자 계정</button>
	                	<button class="btn btn-secondary" type="button" id="lgjAccount">테스트 계정</button>
                 	</div>
                 	<div>
                 		<button class="btn btn-success" type="button" id="iuAccount">아이유 계정</button>
                 		<button class="btn btn-info" type="button" id="wonAccount">장원영 계정</button>
                 	</div>
                 	<div>
                 		<button class="btn btn-warning" type="button" id="haAccount">하루토 계정</button>
                 		<button class="btn btn-danger" type="button" id="kiAccount">키이오 계정</button>
                 	</div>
                </div>
            </article>
            <div class="stylecomp_firstbar"></div>
            <div class="stylecomp_secondbar"></div>
            <div class="bg_video">
                <div class="donttouch"></div>
                <iframe src="https://www.youtube.com/embed/jX2t-FPDQ2g?autoplay=1&mute=1&controls=0&loop=1&playlist=jX2t-FPDQ2g" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
            </div>
        </section>
        <script>
            $(function(){

                var memId = $("#memId");
                var memPw = $("#memPw");
                var loginBtn = $("#loginBtn");
                var loginForm = $("#loginForm");

                $.loginMouseOverEvent();
                $.loginMouseOutEvent();
                $.enterKeyUpEvent();
                
                // 테스트 계정 함수
                $.testAccountFn();

                loginBtn.on("click", function(){
                    var idFlag = $.falsyCheckFn(memId, "아이디");
                    if(!idFlag) return;
                    var pwFlag = $.falsyCheckFn(memPw, "비밀번호");
                    if(!pwFlag) return;
                    
                 	// 실시간 알림 - 로그인 내용 저장 시작
           	        var realrecIdArr; // 모든 유저를 대상으로 알림
           	        $.ajaxMembersIdListGetFn(function(result){
           	        	
           	        	var loginMemVO = {
           	        		memId : memId.val(),
           	        		memPw : memPw.val()
           	        	};
           	        	console.log("loginMemVO : ", loginMemVO);
           	        	
           	        	$.ajax({
           	        		 type : "get",
	           	             url : "/loginMemInfoRtAlertSaveInfo.do",
	           	             data : loginMemVO,
	           	             dataType : "json",
	           	             success : function(res){
	           	                console.log("res : ", res);
	           	                
		           	        	realrecIdArr = result;
		           		        console.log("realrecIdArr : ", realrecIdArr);
		           		        
		           		        var realsenId = res.memId; // 발신자 아이디
		           		        var realsenName = res.memName; // 발신자 이름
		           		        var realsenTitle = "로그인"; // 실시간 알림 제목
		           		        var realsenContent = realsenName+"("+realsenId+")님이 로그인하였습니다."; // 실시간 알림 내용
		           		        var realsenType = "logininfo"; // 정보
		           		        var realsenReadyn = "N"; // 안 읽음
		           		        var realsenUrl = "empty"; // 갈데 없음
		           		        
		           		  		// db에 저장하고 1번만 읽고 바로 realsenReadyn = N을 realsenReadyn = Y로 처리한다.
		           		        // 로그아웃 시 해당 정보를 삭제해야 한다.
		           		        
		           		        var dbSaveFlag = true; // db에 저장
		    			        var userImgSrc = res.memProfileimg; // 유저 프로파일 이미지 정보
		    			        var realrecNo = "empty";
		           		        
		    			        var rtAlert = {
		       			        	"realrecIdArr": realrecIdArr,
		       			        	"realsenId": realsenId,
		       			        	"realsenName": realsenName,
		       			        	"realsenTitle": realsenTitle,
		       			        	"realsenContent": realsenContent,
		       			        	"realsenType": realsenType,
		       			        	"realsenReadyn": realsenReadyn,
		       			        	"realsenUrl": realsenUrl,
		       			        	"realsenPfimg": userImgSrc
		       			        };
		           		        console.log("login > rtAlert : ", rtAlert);
		           		        
		           		        $.realTimeAlertWebSocketFn(rtAlert, dbSaveFlag, userImgSrc, realrecNo);
		           		        
	           	             }
           	        	});
           	        	
           		        
           	        });
           	  		// 실시간 알림 - 로그인 내용 저장 끝
           	  		
           	  		// 로그인 처리
           	  		setTimeout(()=>{
                        loginForm.submit();           	  			
           	  		}, 2000);
                });

            });
        </script>
    </body>
</html>

@charset "utf-8";

@import url('https://fonts.googleapis.com/css2?family=Nanum+Pen+Script&family=Noto+Sans+KR:wght@100;300;500;700;900&display=swap');

/* css reset */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* 공통 스타일 */
body {
    color: #333!important;
    font-family: "Noto Sans KR", sans-serif!important;
}

a {
    color: #333!important;
    text-decoration: none!important;
}

nav ol,
nav ul {
    list-style: none;
}

/* 스크롤바 없애기 */
/* ( 크롬, 사파리, 오페라, 엣지 ) 동작 */
.scroll::-webkit-scrollbar {
  display: none;
}

.scroll {
  -ms-overflow-style: none; /* 인터넷 익스플로러 */
  scrollbar-width: none; /* 파이어폭스 */
}

.cen {
    max-width: 1200px;
    width: 100%;
    margin: auto;
}

/* 로그인 스타일 */
#loginContainer,
#idPwFindContainer,
#signContainer {
    width: 100vw;
    height: 100vh;
    background-color: #333;
    position: relative;
    overflow: hidden;
}

#loginContainer article {
    width: 400px;
    background-color: white;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border-radius: 20px;
    z-index: 100;
}

#loginContainer>article>h1 {
    position: absolute;
    top: -130px;
    left: 50%;
    transform: translateX(-50%);
    margin-bottom: 0px!important;
}

#loginContainer>article>h1>a {
	display: block;
	width: 250px;
	height: 250px;
    border-radius: 50%;
    transition: all 0.4s;
}

#loginContainer>article>h1>a:hover {
	box-shadow: 0px 0px 100px white;
}

#loginContainer>article>h1>a>img {
	display: block;
    width: 100%;
    height: 100%;
}

#loginContainer>article>div {
    padding: 20px;
    padding-top: 120px;
    padding-bottom: 30px;
}

#loginContainer h2 {
    text-align: center;
    font-weight: 900;
    font-size: 2.5rem;
    margin-bottom: 10px;
    letter-spacing: 1px;
}

#loginContainer>article>div>p:first-of-type {
    text-align: center;
}

#loginContainer>article>div>p:last-of-type {
    text-align: center;
    font-size: 0.8rem;
}

#loginForm input {
    margin-bottom: 15px;
    outline: none;
}

#loginForm>div {
    overflow: auto;
    margin-bottom: 15px;
}

#loginForm a {
    color: #0D6EFD!important;
    text-decoration: underline!important;
}

#loginForm a:first-of-type {
    display: block;
    float: left;
}

#loginForm a:last-of-type {
    display: block;
    float: right;
}

#loginBtn {
    width: 100%;
    margin-bottom: 15px;
}

.stylecomp_firstbar {
    width: 500px;
    height: 5000px;
    background-color: red;
    position: absolute;
    top: 50%;
    left: 50%;
    transition: all 0.4s;
    transform: translate(-50%, -50%) rotate(70deg);
    z-index: 90;
}

.stylecomp_secondbar {
    width: 500px;
    height: 5000px;
    background-color: #dc1c2c;
    position: absolute;
    top: 50%;
    left: 50%;
    transition: all 0.4s;
    transform: translate(-50%, -50%) rotate(70deg);
    top: 65%;
    z-index: 80;
}

.bg_video {
    width: 100vw;
    height: 100vh;
    position: relative;
}

.donttouch {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: #333;
    z-index: 20;
}

.bg_video iframe {
    display: block;
    position: absolute;
    width: 100vw;
    height: 100vh;
    transform: scale(1.3);
}

/* 아이디/비밀번호 스타일 */
#idPwFindContainer article {
    width: 500px;
    background-color: white;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border-radius: 20px;
    z-index: 100;
    padding: 25px;
    padding-top: 120px;
}

#idPwFindContainer>article>h1 {
    position: absolute;
    top: -75px;
    left: 50%;
    transform: translateX(-50%);
    margin-bottom: 0px!important;
}

#idPwFindContainer>article>h1>a {
	display: block;
	width: 200px;
	height: 200px;
	border-radius: 50%;
    transition: all 0.4s;
}

#idPwFindContainer>article>h1>a:hover {
	box-shadow: 0px 0px 100px white;
}

#idPwFindContainer>article>h1>a>img {
    display: block;
    width: 100%;
    height: 100%;
}

.findContents {
    margin-bottom: 10px;
}

.findContents h2 {
    text-align: center;
    font-weight: 700;
    font-size: 1.9rem;
    margin-bottom: 10px;
    letter-spacing: -1px;
}

.findContents input {
    margin-bottom: 15px
}

.loginPageGoBtn {
    position: absolute;
    right: 25px;
}

.searchTxt {
    color: red;
    font-size: 1.3rem;
}

/* 회원가입 스타일 */
#signContainer article {
    width: 500px;
    background-color: white;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border-radius: 20px;
    padding: 20px;
    z-index: 100;
}

.profileContents {
    position: relative;
}

.profileContents div {
    width: 200px;
    height: 200px;
    overflow: hidden;
    border-radius: 50%;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    top: -5px;
    right: -95px;
    background-color: white;
}

.profileContents img {
    width: 100%;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

.profileIcon {
    position: absolute;
    top: 60px;
    right: -75px;
    background-color: #eee;
    width: 50px;
    height: 50px;
    border-radius: 50%;
    text-align: center;
    cursor: pointer;
}

.genderTxt {
    margin-right: 10px;
}

#memPw {
    margin-bottom: 15px;
}

.profileIcon i {
    font-size: 2em;
    line-height: 50px;
}

.inputCont {
    margin-bottom: 5px;
    overflow: auto;
    height: 48px;
}

.inputCont:nth-of-type(3),
.inputCont:nth-of-type(12),
.inputCont:last-of-type {
    height: auto;
}

.inputCont label {
    display: block;
    width: 100px;
    float: left;
}

.inputCont input {
    display: block;
    width: calc(100% - 100px);
    float: left;
}

.inputNone label {
    display: inline;
    width: auto;
    float: none;
}

.inputNone input {
    display: inline;
    width: auto;
    float: none;
}

.inputCont:first-of-type {
    display: none;
}

/* 테스트 계정 스타일링 */
.testBtnGroup {
    padding: 0px 20px 20px!important;
    text-align: center;
    display: none;
}

.testBtnGroup button {
	margin-right: 10px;
}

.testBtnGroup button:last-of-type {
	margin-right: 0px;
}

.testBtnGroup>div {
	margin-bottom: 10px;
}

.testBtnShow {
	cursor: pointer;
	transition: all 0.4s;
	border-radius: 4px;
}

.testBtnShow:hover {
	background-color: #333;
	color: white;
	padding: 10px 0px;
}

/* 미디어 쿼리 (PC용) */
@media all and (max-width: 1410px) {
    
    .bg_video iframe {
        width: 1410px;
    }
    
}

/* 미디어 쿼리 (태블릿용) */
@media all and (max-width: 768px) {
    
    .stylecomp_firstbar {
        width: 300px;
        transform: translate(-50%, -50%) rotate(20deg);
    }
    
    .stylecomp_secondbar{
        width: 300px;
        transform: translate(-50%, -50%) rotate(20deg);
        left: 60%;
    }
    
}

@media all and (max-width: 670px) {
    
    #signContainer article {
        width: 300px;
    }
    
    .profileContents div {
        width: 100px;
        height: 100px;
        top: 15px;
        right: -45px;
    }
    
    .profileIcon {
        top: 50px;
        right: -30px;
    }
    
}

@media all and (max-width: 630px) {
    
    #idPwFindContainer h1 {
        display: none;
    }
    
    #idPwFindContainer article {
        padding-top: 25px;
        width: 300px;
    }
    
    .findContents {
        margin-bottom: 20px;
    }
    
    .findContents h2 {
        font-size: 1.5rem;
    }
    
    .findContents p {
        font-size: 0.9rem;
    }
    
}

@media all and (max-width: 510px) {
    
    #loginContainer article {
        width: 280px;
    }
    
    #loginContainer h2 {
        font-size: 2rem;
    }
    
    #loginContainer>article>div>p:first-of-type {
        font-size: 0.8rem;
    }
    
    #loginContainer>article>div>p:last-of-type {
        font-size: 0.6rem;
    }
    
    .stylecomp_firstbar {
        display: none;
    }
    
    .stylecomp_secondbar{
        display: none;
    }
    
    #loginForm a:first-of-type {
        font-size: 0.9rem;
    }

    #loginForm a:last-of-type {
        font-size: 0.9rem;
    }
    
}

// 공통 함수
// 마우스 오버/아웃 이벤트
$.findMouseOverEvent = function(cont){
    cont.mouseover(function(){
        donttouch.stop().fadeOut();
    });
};

$.findMouseOutEvent = function(cont){
    cont.mouseout(function(){
        donttouch.stop().fadeIn();
    });
};

// 로그인 화면 페이지 함수
var logCont = $("#loginContainer>article");
var comp_fir = $(".stylecomp_firstbar");
var comp_sec = $(".stylecomp_secondbar");
var donttouch = $(".donttouch");

$.loginMouseOverEvent = function(){
    logCont.mouseover(function(){
        comp_fir.css({
            transform : "translate(-50%, -80%) rotate(70deg)"
        });
        comp_sec.css({
            transform : "translate(-50%, -20%) rotate(70deg)"
        });
        donttouch.stop().fadeOut();
    });
};

$.loginMouseOutEvent = function(){
    logCont.mouseout(function(){
        comp_fir.css({
            transform : "translate(-50%, -50%) rotate(70deg)"
        });
        comp_sec.css({
            transform : "translate(-50%, -50%) rotate(70deg)"
        });
        donttouch.stop().fadeIn();
    });
};

$.enterKeyUpEvent = function(){
    $(window).keyup(function(e){
        //console.log(e.keyCode);
        // enter키 : 13
        if(e.keyCode == 13) {
            $("#loginBtn").trigger("click");
        }
    });
};

// 아이디/비밀번호 찾기 페이지 함수
var loginPageGoBtn = $(".loginPageGoBtn");

var profileIcon = $(".profileIcon");
var imgFile = $("#imgFile");

$.loginPageGoFn = function(){
    loginPageGoBtn.click(function(){
        location.href = "/login/signin.do";
    });
};

// 회원가입 페이지 함수
$.fileChangeEvent = function(){
    profileIcon.click(function(){
        imgFile.trigger("click");
        imgFile.change(function() {
            console.log("Selected file: " + this.files[0].name); // 이슈 확인
        });
    });
};

// 아이디, 비밀번호 찾기 함수
// 객체 비구조화 할당 사용
$.findChkFn = function(findOutObj, {url, msgEl, msg}){
	console.log(findOutObj);
	$.ajax({
        type: "post",
        url: url,
        data: JSON.stringify(findOutObj),
        contentType: "application/json;charset=utf-8",
        success: function(res){
        	console.log("결과 : " + res);
            if(!res) {
                $(msgEl).html("회원님의 "+msg+" 정보를 찾을 수 없습니다.");
            }else {
                if(msg == "아이디"){
                    var id = res.memId;
                    $(msgEl).html("회원님의 "+msg+"는 [<span class='searchTxt'>"+id+"</span>] 입니다.");
                }else if(msg == "비밀번호"){
                    //var pw = res.memPw;
                    //$(msgEl).html("회원님의 "+msg+"는 [<span class='searchTxt'>"+pw+"</span>] 입니다.");
                    $(msgEl).html("회원님의 "+msg+"를 재설정합니다.");
                    
                    // 비밀번호 재설정 팝업창
                    var modalHtmlTxt = `
                    <div class="modal fade" id="chgPwModal">
                        <div class="modal-dialog modal-dialog-centered modal-lg">
                            <div class="modal-content">
                                <div class="modal-header">
                                    <h4 class="modal-title">비밀번호 재설정</h4>
                                </div>
                                <div class="modal-body">
                                    <div>
                                        <p>새로 등록할 비밀번호를 입력해 주세요.</p>
                                        <div class="chgPwChkBadge">
                                            <span class="badge bg-danger">비밀번호 불일치</span>
                                        </div>
                                    </div>
                                    <form action="/login/changePw.do" method="post" id="chgPwForm" name="chgPwForm">
                                        <input type="hidden" id="memId2" name="memId" />
                                        <div>
                                            <label for="memPw">비밀번호 입력</label>
                                            <input style="margin-bottom: 0px;" class="form-control" type="password" id="memPw" name="memPw" placeholder="새로 변경할 비밀번호 입력" />
                                        </div>
                                        <div>
                                            <label for="memPwChk">비밀번호 확인</label>
                                            <input class="form-control" type="password" id="memPwChk" name="memPwChk" placeholder="새로 변경할 비밀번호 입력" />
                                        </div>
                                        <button class="btn btn-primary" type="button" id="chgPwBtn">비밀번호 재설정</button>
                                    </form>
                                </div>
                                <div class="modal-footer">
                                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">취소</button>
                                </div>
                            </div>
                        </div>
                    </div>
                    `;

					$("#chgPwModal").remove();

                    $("body").append(modalHtmlTxt);

                    var chgPwModal = new bootstrap.Modal(document.getElementById('chgPwModal'));
                    chgPwModal.show();
                    
                    // 회원 아이디 보내기
                    var memIdVal = $("#memId");
                    var chgMemid = $("#memId2");
                    chgMemid.val(memIdVal.val());
                    
                    // 비밀번호 재설정 > 비밀번호 확인 메서드
                    var memPw = $("#memPw");
                    var memPwChk = $("#memPwChk");
                    
	                var pwChkFlag = false;
	             	var pwObj = {
	             		el1: memPw,
	             		el2: memPwChk,
	             		msgEl: ".chgPwChkBadge",
	             		msg: "비밀번호"
	             	};

	             	$.inputValMismatchChkFn(pwObj, function(result){
	                	pwChkFlag = result;
	             	});

                    var chgPwForm = $("#chgPwForm");
					var chgPwBtn = $("#chgPwBtn");
					chgPwBtn.click(function(){
	                    if(pwChkFlag) {
	                        chgPwForm.submit();
	                    }else {
	                        //alert("비밀번호가 일치하는지 확인해주세요.");
	                        Swal.fire({
					            title: "안내",
					            text: "비밀번호가 일치하는지 확인해주세요.",
					            icon: "info"
					        });
	                    }
					});
                }
            }
        }
    });
};

// 쓸데없이 하는 거에 비해서 복잡, 매개변수는 많으면 {} 처리 -> 넹 센세...
// 객체 비구조화 할당 사용
$.matchKeyupEvent = function({el, msgEl, msg, col, url}, callback){
    el.keyup(function(){
        var valTxt = $(this).val();
        //console.log("valTxt : ",valTxt);
        if(!valTxt) {
        	$(msgEl).html("<span class='badge bg-danger'>"+msg+" 사용불가</span>");
        	callback(false);
        }else {
            var data = {
                [col] : valTxt
            };
            //console.log("data : ", data);
            $.ajax({
                type: "post",
                url: url,
                data: JSON.stringify(data),
                contentType: "application/json;charset=utf-8",
                success: function(res){
                    if(res === "NOTEXIST") {
                        $(msgEl).html("<span class='badge bg-success'>"+msg+" 사용가능</span>");
                        callback(true);
                    }else {
                        $(msgEl).html("<span class='badge bg-danger'>"+msg+" 사용불가</span>");
                        callback(false);
                    }
                }
            });
        }
    });
};

// 두 input 사이 간의 값 비교
$.inputValMismatchChkFn = function({el1, el2, msgEl, msg}, callback){
	el1.keyup(function(){
        var el1Val = el1.val();
        var el2Val = el2.val();
        if(!el1Val){
        	$(msgEl).html("<span class='badge bg-danger'>"+msg+" 불일치</span>");
	        callback(false);
        }else {
	        if(el1Val === el2Val){
	            $(msgEl).html("<span class='badge bg-success'>"+msg+" 일치</span>");
	            callback(true);
	        }else {
	            $(msgEl).html("<span class='badge bg-danger'>"+msg+" 불일치</span>");
	            callback(false);
	        }
        }
    });
	el2.keyup(function(){
        var el1Val = el1.val();
        var el2Val = el2.val();
        if(!el2Val){
        	$(msgEl).html("<span class='badge bg-danger'>"+msg+" 불일치</span>");
	        callback(false);
        }else {
	        if(el1Val === el2Val){
	            $(msgEl).html("<span class='badge bg-success'>"+msg+" 일치</span>");
	            callback(true);
	        }else {
	            $(msgEl).html("<span class='badge bg-danger'>"+msg+" 불일치</span>");
	            callback(false);
	        }
        }
    });
};

// 관리자, 테스트 계정 버튼 기능
$.testAccountFn = function(){
	var testBtnShow = $(".testBtnShow");
	var testBtnGroup = $(".testBtnGroup");
	var loginBox = $(".loginBox");
	
	var token = false; // 현재 테스트 박스가 눈에 보이지 않는 상태
	testBtnShow.click(function(){
		if(!token) { // 눈에 보이게 한다!
			loginBox.css({
				paddingBottom: "0px"
			});
			testBtnGroup.show();
			token = true; // 눈에 보이는 상태임을 표시
		}else {
			loginBox.css({
				paddingBottom: "30px"
			});
			testBtnGroup.hide();
			token = false; // 눈에 보이지 않는 상태임을 표시
		}
	});
	
	var loginIdEl = $("#loginForm #memId");
	var loginPwEl = $("#loginForm #memPw");
	var loginBtn = $("#loginBtn")
	
	var adminAccount = $("#adminAccount");
	var lgjAccount = $("#lgjAccount");
	var iuAccount = $("#iuAccount");
	var wonAccount = $("#wonAccount");
	var haAccount = $("#haAccount");
	var kiAccount = $("#kiAccount");
	
	// 관리자 계정 로그인 처리 함수
	adminAccount.click(function(){
		var adminId = "admin";
		var adminPw = "admin1234";
		loginIdEl.val(adminId);
		loginPwEl.val(adminPw);
		loginBtn.trigger("click");
	});
	
	// 테스트 계정 로그인 처리 함수
	lgjAccount.click(function(){
		var testId = "chantest1";
		var testPw = "1234";
		loginIdEl.val(testId);
		loginPwEl.val(testPw);
		loginBtn.trigger("click");
	});
	
	// 아이유 계정 로그인 처리 함수
	iuAccount.click(function(){
		var testId = "iuforever9802";
		var testPw = "dkdldb9802";
		loginIdEl.val(testId);
		loginPwEl.val(testPw);
		loginBtn.trigger("click");
	});
	
	// 장원영 계정 로그인 처리 함수
	wonAccount.click(function(){
		var testId = "wonyoung0408";
		var testPw = "dnjsdud0408";
		loginIdEl.val(testId);
		loginPwEl.val(testPw);
		loginBtn.trigger("click");
	});
	
	// 하루토 계정 로그인 처리 함수
	haAccount.click(function(){
		var testId = "haru0404";
		var testPw = "gkfnxh0404";
		loginIdEl.val(testId);
		loginPwEl.val(testPw);
		loginBtn.trigger("click");
	});
	
	// 키이오 계정 로그인 처리 함수
	kiAccount.click(function(){
		var testId = "kio0411";
		var testPw = "zldh0411";
		loginIdEl.val(testId);
		loginPwEl.val(testPw);
		loginBtn.trigger("click");
	});
};

// daum 주소 API(주소 찾기)
function DaumPostcode() {
    new daum.Postcode({
        oncomplete: function(data) {
            // 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.

            // 각 주소의 노출 규칙에 따라 주소를 조합한다.
            // 내려오는 변수가 값이 없는 경우엔 공백('')값을 가지므로, 이를 참고하여 분기 한다.
            var addr = ''; // 주소 변수
            var extraAddr = ''; // 참고항목 변수

            //사용자가 선택한 주소 타입에 따라 해당 주소 값을 가져온다.
            if (data.userSelectedType === 'R') { // 사용자가 도로명 주소를 선택했을 경우
                addr = data.roadAddress;
            } else { // 사용자가 지번 주소를 선택했을 경우(J)
                addr = data.jibunAddress;
            }

            // 사용자가 선택한 주소가 도로명 타입일때 참고항목을 조합한다.
            if (data.userSelectedType === 'R') {
                // 법정동명이 있을 경우 추가한다. (법정리는 제외)
                // 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
                if (data.bname !== '' && /[동|로|가]$/g.test(data.bname)) {
                    extraAddr += data.bname;
                }
                // 건물명이 있고, 공동주택일 경우 추가한다.
                if (data.buildingName !== '' && data.apartment === 'Y') {
                    extraAddr += (extraAddr !== '' ? ', ' + data.buildingName : data.buildingName);
                }
            }

            // 우편번호와 주소 정보를 해당 필드에 넣는다.
            document.getElementById('memPostcode').value = data.zonecode;
            document.getElementById("memAddress1").value = addr;
            // 커서를 상세주소 필드로 이동한다.
            document.getElementById("memAddress2").focus();
        }
    }).open();
};

// 윈도우 가로 길이 변경 이벤트
$(window).resize(function(){
    //console.log("화면길이 조정중이유");
    var winW = $(this).outerWidth();
    
    // 로그인 페이지 컴포넌트 스타일 초기화
    comp_fir.removeAttr("style");
    comp_sec.removeAttr("style");
    
    // 아이디/비밀번호 찾기 버튼 크기 조정
    var findContentsBtns = $(".findContents button");
    if(winW > 630) {
        findContentsBtns.removeClass("btn-sm");
    }else {
        findContentsBtns.addClass("btn-sm");
    }
    
    // 종횡비 함수
    var profileBox = $(".profileContents>div");
    var profileImg = $(".profileContents img");
    $.ratioBoxH(profileBox, profileImg);
});

package kr.or.ddit.users.login.vo;

import org.springframework.web.multipart.MultipartFile;

import lombok.Data;

@Data
public class MemberVO {

	private int memNo;
	private String memId;
	private String memPw;
	private String memName;
	private String memGender;
	private String memEmail;
	private String memPhone;
	private String memPostcode;
	private String memAddress1;
	private String memAddress2;
	private String gradeCode;
	private String enabled;
	private int memCategory;
	private String memRegdate;
	private String memAgedate;
	
	private MultipartFile imgFile;
	private String memProfileimg;
	private int memPoint;
	
}

package kr.or.ddit.users.login.controller;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import kr.or.ddit.users.login.service.LoginService;
import kr.or.ddit.users.login.vo.MemberVO;
import kr.or.ddit.utils.ServiceResult;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequestMapping("/login")
public class LoginController {
	
	@Resource(name = "uploadPath")
	private String resourcePath;
	
	@Inject
	private LoginService loginService;

	// 로그인 페이지 이동
	@CrossOrigin(origins = "http://localhost")
	@RequestMapping(value = "/signin.do", method = RequestMethod.GET)
	public String signin(String message, Model model) {
		if(StringUtils.isNotBlank(message)) {
			// 성공, 실패, 정보
			// 성공 : su
			// 실패 : fa
			// 정보 : in
			model.addAttribute("message", message);
			model.addAttribute("msgflag", "in");
		}
		return "login/signin";
	}
	
	// 회원 가입 페이지 이동
	@CrossOrigin(origins = "http://localhost")
	@RequestMapping(value = "/signup.do", method = RequestMethod.GET)
	public String signup() {
		return "login/signup";
	}
	
	// Ajax > 아이디 중복체크 메서드
	@RequestMapping(value = "/idCheck.do", method = RequestMethod.POST)
	public ResponseEntity<String> idCheck(@RequestBody Map<String, String> map){
		ServiceResult result = loginService.idCheck(map.get("memId"));
		return new ResponseEntity<String>(result.toString(), HttpStatus.OK);
	}
	
	// Ajax > 이메일 중복체크 메서드
	@RequestMapping(value = "/emailCheck.do", method = RequestMethod.POST)
	public ResponseEntity<String> emailCheck(@RequestBody Map<String, String> map){
		ServiceResult result = loginService.emailCheck(map.get("memEmail"));
		return new ResponseEntity<String>(result.toString(), HttpStatus.OK);
	}
	
	// 회원 가입 메서드
	@RequestMapping(value = "/signup.do", method = RequestMethod.POST)
	public String signup(
			HttpServletRequest req, 
			MemberVO memberVO, 
			Model model, 
			RedirectAttributes ra,
			@RequestParam("imgFile") MultipartFile imgFile
			) {
		
		log.info("imgFile : " + imgFile.getOriginalFilename());
		log.info("memberVO : " + memberVO.toString());
		
		// 이미지 파일이 없는 경우 예외 처리
		if(imgFile.isEmpty()) {
			model.addAttribute("message", "이미지 파일을 업로드해 주세요.");
			model.addAttribute("msgflag", "in");
			return "login/signup";
		}
		
		String goPage = "";
		
		Map<String, String> errors = new HashMap<String, String>();
		if(StringUtils.isBlank(memberVO.getMemId())) {
			errors.put("memId", "아이디를 입력해 주세요.");
		}
		if(StringUtils.isBlank(memberVO.getMemPw())) {
			errors.put("memPw", "비밀번호를 입력해 주세요.");
		}
		if(StringUtils.isBlank(memberVO.getMemName())) {
			errors.put("memName", "이름을 입력해 주세요.");
		}
		
		if(errors.size() > 0) { // 에러 정보가 존재
			model.addAttribute("errors", errors);
			model.addAttribute("msgflag", "in");
			model.addAttribute("member", memberVO);
			goPage = "login/signup"; // 회원 가입 페이지로 이동
		}else { // 정상적인 데이터
			ServiceResult result = loginService.signup(req, memberVO);
			if(result.equals(ServiceResult.OK)) { // 가입 성공
				ra.addFlashAttribute("message", "회원가입을 완료하였습니다!");
				ra.addFlashAttribute("msgflag", "su");
				goPage = "redirect:/login/signin.do"; // 로그인 페이지로 이동
			}else { // 가입 실패
				model.addAttribute("message", "서버에러, 다시 시도해 주세요!");
				model.addAttribute("msgflag", "fa");
				model.addAttribute("member", memberVO);
				goPage = "login/signup"; // 회원 가입 페이지로 이동
			}
		}
		
		return goPage;
	}
	
	// 아이디/비밀번호 페이지 이동
	@CrossOrigin(origins = "http://localhost")
	@RequestMapping(value = "/findIdPw.do", method = RequestMethod.GET)
	public String findIdPw() {
		return "login/findIdPw";
	}
	
	// Ajax > 아이디 찾기 메서드
	@RequestMapping(value = "/findId.do", method = RequestMethod.POST)
	public ResponseEntity<MemberVO> findId(
			@RequestBody Map<String, String> map
			){
		
		MemberVO result = loginService.findId(map);
		return new ResponseEntity<MemberVO>(result, HttpStatus.OK);
		
	}
	
	// Ajax > 비밀번호 찾기 메서드
	@RequestMapping(value = "/findPw.do", method = RequestMethod.POST)
	public ResponseEntity<MemberVO> findPw(
			@RequestBody Map<String, String> map
			){
		
		MemberVO result = loginService.findPw(map);
		return new ResponseEntity<MemberVO>(result, HttpStatus.OK);
		
	}
	
	// 비밀번호 변경 처리 메서드
	@PostMapping("/changePw.do")
	public String changePw(
			MemberVO memberVO,
			Model model,
			RedirectAttributes ra
			) {
		
		/** 자료 수집 및 정의 */
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("memId", memberVO.getMemId());
		param.put("memPw", memberVO.getMemPw());
		
		/** 서비스 호출 */
		loginService.changePw(param);
		
		/** 반환 자료 */
		ServiceResult result = (ServiceResult) param.get("result");
		String message = (String) param.get("message");
		String goPage = (String) param.get("goPage");
		
		/** 자료 검증 */
	    log.info("result : " + result);
	    log.info("message : " + message);
	    log.info("goPage : " + goPage);

	    if(result.equals(ServiceResult.OK)) { // 업데이트 성공
	        ra.addFlashAttribute("message", message);
	        ra.addFlashAttribute("msgflag", "su");
	    }else { // 업데이트 실패
	        model.addAttribute("message", message);
	        model.addAttribute("msgflag", "fa");
	    }
		
		/** 자료 반환 */
	    return goPage;
		
	}
	
	// 로그인 처리 메서드
	@RequestMapping(value = "/loginCheck.do", method = RequestMethod.POST)
	public String loginCheck(
			HttpSession session,
			MemberVO memberVO,
			Model model,
			RedirectAttributes ra
			) {
		
		String goPage = "";
		
		Map<String, String> errors = new HashMap<String, String>();
		if(StringUtils.isBlank(memberVO.getMemId())) {
			errors.put("memId", "아이디를 입력해 주세요");
		}
		if(StringUtils.isBlank(memberVO.getMemPw())) {
			errors.put("memPw", "비밀번호를 입력해 주세요");
		}
		
		if(errors.size() > 0) { // 에러가 있음
			model.addAttribute("errors", errors);
			model.addAttribute("msgflag", "fa");
			model.addAttribute("member", memberVO);
			goPage = "login/signin";
		}else {
			MemberVO member = loginService.loginCheck(memberVO);
			if(member != null) {
				if(member.getEnabled().equals("0")) { // 탈퇴한 회원
					ra.addFlashAttribute("message", "탈퇴한 회원 계정입니다.");
					ra.addFlashAttribute("msgflag", "in");
					goPage = "redirect:/login/signin.do";
				}else {
					session.setAttribute("sessionInfo", member);
					int intervalInSeconds = 60 * 60; // 1시간을 초로 계산합니다
					session.setMaxInactiveInterval(intervalInSeconds);
					ra.addFlashAttribute("message", member.getMemName() + "님, 환영합니다!");
					ra.addFlashAttribute("msgflag", "su");
					goPage = "redirect:/index.do";
				}
			}else {
				model.addAttribute("message", "존재하지 않는 회원입니다.");
				model.addAttribute("msgflag", "in");
				model.addAttribute("member", memberVO);
				goPage = "login/signin";
			}
		}
		
		return goPage;
		
	}
	
	// 로그아웃 메서드
	@RequestMapping(value = "/logout.do", method = RequestMethod.GET)
	public String logout(
			HttpSession session,
			RedirectAttributes ra
			) {
		
		session.invalidate();
		ra.addFlashAttribute("message", "로그아웃 되었습니다.");
		ra.addFlashAttribute("msgflag", "in");
		return "redirect:/login/signin.do";
		
	}
	
}

package kr.or.ddit.users.login.service;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import kr.or.ddit.users.login.vo.MemberVO;
import kr.or.ddit.utils.ServiceResult;

public interface LoginService {

	public ServiceResult idCheck(String memId);
	public ServiceResult emailCheck(String memEmail);
	public ServiceResult signup(HttpServletRequest req, MemberVO memberVO);
	public MemberVO findId(Map<String, String> map);
	public MemberVO findPw(Map<String, String> map);
	public MemberVO loginCheck(MemberVO memberVO);
	public void changePw(Map<String, Object> param);

}

package kr.or.ddit.users.login.service.impl;

import java.io.File;
import java.util.Map;
import java.util.UUID;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import kr.or.ddit.mapper.LoginMapper;
import kr.or.ddit.users.login.service.LoginService;
import kr.or.ddit.users.login.vo.MemberVO;
import kr.or.ddit.utils.ServiceResult;

@Service
@Transactional(rollbackFor = Exception.class)
public class LoginServiceImpl implements LoginService {

	@Inject
	private LoginMapper loginMapper;
	
	@Override
	public ServiceResult idCheck(String memId) {
		ServiceResult result = null;
		
		MemberVO memberVO = loginMapper.idCheck(memId);
		if(memberVO != null) {
			result = ServiceResult.EXIST;
		}else {
			result = ServiceResult.NOTEXIST;
		}
		
		return result;
	}

	@Override
	public ServiceResult emailCheck(String memEmail) {
		ServiceResult result = null;
		
		MemberVO memberVO = loginMapper.emailCheck(memEmail);
		if(memberVO != null) {
			result = ServiceResult.EXIST;
		}else {
			result = ServiceResult.NOTEXIST;
		}
		
		return result;
	}
	
	@Override
	public ServiceResult signup(HttpServletRequest req, MemberVO memberVO) {
		ServiceResult result = null;
		
		// 회원가입 시, 프로필 이미지로 파일 업로드 할 서버 경로 지정
		String uploadPath = req.getServletContext().getRealPath("/resources/profile");
		File file = new File(uploadPath);
		if (!file.exists()) {
			file.mkdirs();
		}
		
		String profileImg = ""; // 회원정보에 추가될 프로필 이미지 경로
		try {
			// 넘겨받은 회원정보에서 파일 데이터 가져오기
			MultipartFile profileImgFile = memberVO.getImgFile();
			
			// 넘겨받은 파일 데이터가 존재할 때
			if(profileImgFile.getOriginalFilename() != null && !profileImgFile.getOriginalFilename().equals("")) {
				String fileName = UUID.randomUUID().toString(); // UUID 파일명 생성
				fileName += "_" + profileImgFile.getOriginalFilename(); // UUID_원본파일명으로 생성
				uploadPath += "/" + fileName; // /resources/profile/UUID_원본파일명
				
				profileImgFile.transferTo(new File(uploadPath)); // 해당 위치에 파일 복사
				profileImg = "/resources/profile/" + fileName; // 파일 복사가 일어난 파일의 위치로 접근하기 위한 URI 설정
			}
			
			memberVO.setMemProfileimg(profileImg);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		int status = loginMapper.signup(memberVO);
		
		if(status > 0) { // 등록 성공
			result = ServiceResult.OK;
		}else { // 등록 실패
			result = ServiceResult.FAILED;
		}
		
		return result;
	}

	@Override
	public MemberVO findId(Map<String, String> map) {
		MemberVO member = loginMapper.findId(map);
		return member;
	}

	@Override
	public MemberVO findPw(Map<String, String> map) {
		MemberVO member = loginMapper.findPw(map);
		return member;
	}

	@Override
	public MemberVO loginCheck(MemberVO memberVO) {
		return loginMapper.loginCheck(memberVO);
	}

	@Override
	public void changePw(Map<String, Object> param) {
		/** 파라미터 조회 */
		String memId = (String) param.get("memId");
		String memPw = (String) param.get("memPw");
		
		/** 파라미터 정의 */
		MemberVO memberVO = new MemberVO();
		int status = 0;
		ServiceResult result = null;
		String message = "";
		String goPage = "";
		
		/** 메인로직 처리 */
		// 해당 회원의 비밀번호를 변경
		memberVO.setMemId(memId);
		memberVO.setMemPw(memPw);
		
		status = loginMapper.changePw(memberVO);
		
		if(status > 0) { // 비밀번호 변경 성공
			result = ServiceResult.OK;
			message = memId + " 회원의 비밀번호 변경에 성공했습니다. 로그인 페이지로 이동합니다.";
			goPage = "redirect:/login/signin.do"; // 로그인 페이지로 이동
		}else { // 비밀번호 변경 실패
			result = ServiceResult.FAILED;
			message = "서버 오류, 다시 시도해 주세요.";
			goPage = "login/findIdPw"; // 아이디/비밀번호 페이지로 이동
		}
		
		/** 반환자료 저장 */
	    param.put("result", result);
	    param.put("message", message);
	    param.put("goPage", goPage);
	}

}

package kr.or.ddit.mapper;

import java.util.Map;

import kr.or.ddit.users.login.vo.MemberVO;

public interface LoginMapper {

	public MemberVO idCheck(String memId);
	public MemberVO emailCheck(String memEmail);
	public int signup(MemberVO memberVO);
	public MemberVO findId(Map<String, String> map);
	public MemberVO findPw(Map<String, String> map);
	public MemberVO loginCheck(MemberVO memberVO);
	public int changePw(MemberVO memberVO);

}

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.or.ddit.mapper.LoginMapper">

	<select id="idCheck" parameterType="string" resultType="memberVO">
		SELECT
		    mem_no,
		    mem_id,
		    mem_pw,
		    mem_name,
		    mem_gender,
		    mem_email,
		    mem_phone,
		    mem_postcode,
		    mem_address1,
		    mem_address2,
		    mem_profileimg,
		    grade_code,
		    enabled,
		    mem_category,
		    mem_regdate,
		    mem_agedate
		FROM
		    members
		WHERE 1=1 
		  AND mem_id = #{memId}
	</select>
	
	<select id="emailCheck" parameterType="string" resultType="memberVO">
		SELECT
		    mem_no,
		    mem_id,
		    mem_pw,
		    mem_name,
		    mem_gender,
		    mem_email,
		    mem_phone,
		    mem_postcode,
		    mem_address1,
		    mem_address2,
		    mem_profileimg,
		    grade_code,
		    enabled,
		    mem_category,
		    mem_regdate,
		    mem_agedate
		FROM
		    members
		WHERE 1=1 
		  AND mem_email = #{memEmail}
	</select>
	
	<insert id="signup" parameterType="memberVO">
		<selectKey keyProperty="memNo" order="BEFORE" resultType="int">
			select seq_members.nextval from dual
		</selectKey>
		INSERT INTO members (
		    mem_no,
		    mem_id,
		    mem_pw,
		    mem_name,
		    mem_gender,
		    mem_email,
		    mem_phone,
		    mem_postcode,
		    mem_address1,
		    mem_address2,
		    mem_profileimg,
		    grade_code,
		    enabled,
		    mem_category,
		    mem_regdate,
		    mem_agedate
		) VALUES (
		    #{memNo},
		    #{memId},
		    #{memPw},
		    #{memName},
		    #{memGender},
		    #{memEmail},
		    #{memPhone},
		    #{memPostcode},
		    #{memAddress1},
		    #{memAddress2},
		    #{memProfileimg},
		    'NOR01',
		    '1',
		    '01',
		    sysdate,
		    #{memAgedate}
		)
	</insert>
	
	<select id="findId" parameterType="java.util.HashMap" resultType="memberVO">
		SELECT
		    mem_no,
		    mem_id,
		    mem_pw,
		    mem_name,
		    mem_gender,
		    mem_email,
		    mem_phone,
		    mem_postcode,
		    mem_address1,
		    mem_address2,
		    mem_profileimg,
		    grade_code,
		    enabled,
		    mem_category,
		    mem_regdate,
		    mem_agedate
		FROM
		    members
		WHERE 1=1 
		  AND mem_email = #{memEmail}
		  AND mem_name = #{memName}
	</select>
	
	<select id="findPw" parameterType="java.util.HashMap" resultType="memberVO">
		SELECT
		    mem_no,
		    mem_id,
		    mem_pw,
		    mem_name,
		    mem_gender,
		    mem_email,
		    mem_phone,
		    mem_postcode,
		    mem_address1,
		    mem_address2,
		    mem_profileimg,
		    grade_code,
		    enabled,
		    mem_category,
		    mem_regdate,
		    mem_agedate
		FROM
		    members
		WHERE 1=1 
		  AND mem_id = #{memId}
		  AND mem_email = #{memEmail}
		  AND mem_name = #{memName}
	</select>
	
	<select id="loginCheck" parameterType="string" resultType="memberVO">
		SELECT
		    mem_no,
		    mem_id,
		    mem_pw,
		    mem_name,
		    mem_gender,
		    mem_email,
		    mem_phone,
		    mem_postcode,
		    mem_address1,
		    mem_address2,
		    mem_profileimg,
		    grade_code,
		    enabled,
		    mem_category,
		    mem_regdate,
		    mem_agedate
		FROM
		    members
		WHERE 1=1 
		  AND mem_id = #{memId}
		  AND mem_pw = #{memPw}
	</select>
	
	<update id="changePw" parameterType="memberVO">
		UPDATE members
		SET
		    mem_pw = #{memPw}
		WHERE
		    mem_id = #{memId}
	</update>

</mapper>