본문 바로가기
스프링부트

[스프링부트] 홈페이지 만들기[1] - 로그인, 회원가입

by CodeMango 2023. 3. 27.

1. 백앤드

Member.xml

<?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">
	
	<!--  스프링과 다른점 -> namespace -> dao가 mapper를 흡수하게함. -->
<mapper namespace="mul.cam.a.dao.MemberDao">

<select id="idcheck" parameterType="String" resultType="Integer">
	select count(*)
	from member
	where id=#{id}
</select>

<insert id="addmember" parameterType="mul.cam.a.dto.MemberDto">
	insert into member(id, pwd, name, email, auth)
	values(#{id}, #{pwd}, #{name}, #{email}, 3)
</insert>

<select id="login" parameterType="mul.cam.a.dto.MemberDto"
	resultType="mul.cam.a.dto.MemberDto">
	select id, name, email
	from member
	where id=#{id} and pwd=#{pwd}
</select>

</mapper>

MemberDao.java

package mul.cam.a.dao;

import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import mul.cam.a.dto.MemberDto;

@Mapper
@Repository
public interface MemberDao {

	int idcheck(String id);		//mapper의 id와 함수이름이 똑같아야 한다
	
	int addmember(MemberDto dto);
	
	MemberDto login(MemberDto dto);
}

MemberService.java

package mul.cam.a.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import mul.cam.a.dao.MemberDao;
import mul.cam.a.dto.MemberDto;

@Service
@Transactional
public class MemberService {
	
	@Autowired
	MemberDao dao;
	
	public boolean idcheck(String id) {
		int n = dao.idcheck(id);
		return n>0?true:false;
	}
	
	public boolean addmember(MemberDto dto) {	//dao와 함수이름이 똑같을 필요는 없다.
		int n = dao.addmember(dto);
		return n>0?true:false;
	}
	
	//반환되는 MemberDto 값이 null일 경우 로그인에 실패한 것으로 보면됨. 
	public MemberDto login(MemberDto dto) {
		return dao.login(dto);		
	}
		
}

MemberController.java

package mul.cam.a.controller;

import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import mul.cam.a.dto.MemberDto;
import mul.cam.a.service.MemberService;

@RestController
public class MemberController {

	@Autowired
	MemberService service;
	
	//id중복확인
	@PostMapping(value = "/idcheck")
	public String idcheck(String id) {
		System.out.println("MemberController idcheck " + new Date());
		
		boolean b = service.idcheck(id);
		if(b == true) {
			return "NO";
		}		
		return "YES";
	}
	//회원가입	
	@PostMapping(value = "/addmember")	//url:"http://localhost:3000/addmember" 이므로
	public String addmember(MemberDto dto) {
		System.out.println("MemberController addmember " + new Date());
		
		boolean b = service.addmember(dto);
		if(b == false) {
			return "NO";
		}
		return "YES";
	}
	
	//로그인 - 로그인이 null값이든 아니든 일단 넘겨줌 판단은 프론트엔드에서 하기!
	@PostMapping(value = "/login")
	public MemberDto login(MemberDto dto) {
		System.out.println("MemberController login " + new Date());
		
		MemberDto mem = service.login(dto);		
		return mem;
	}
}

 

2. 프론트앤드

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

<script type="text/javascript">
location.href = "login.html";
</script>

</body>
</html>

login.html  로그인페이지

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>login</title>
<meta name="viewport" content="width=device-width, initial-scale=1">

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.3/dist/jquery.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>

<script src="http://lab.alexcican.com/set_cookies/cookie.js" type="text/javascript" ></script>

<style type="text/css">
.divider:after, .divider:before {	content: "";  flex: 1;  height: 1px;  background: #eee; }
.h-custom {  height: calc(100% - 73px); }
@media (max-width: 450px) {  .h-custom {    height: 100%;  } }
</style>

</head>
<body>
<!--  form으로 데이터 날려주는게 아니라 form aciton도 쓰지 않는다  
      프앤에서는 세션에 접근할 수 없다. jsp가 아니니까 자스니까 접근할 수가 없다 -->
<section class="vh-100">
  <div class="container-fluid h-custom">
    <div class="row d-flex justify-content-center align-items-center h-100">
    
      <div class="col-md-9 col-lg-6 col-xl-5">
        <img src="https://www.multicampus.com/kr/images/main/2021/tab-image3.jpg" class="img-fluid"
          alt="Sample image">
      </div>
      
      <div class="col-md-8 col-lg-6 col-xl-4 offset-xl-1">
      	<!-- <form action="loginAf.do" method="post">  form으로 데이터 날려주는게 아니라 form aciton도 쓰지 않는다  -->
      	  <div class="d-flex flex-row align-items-center justify-content-center justify-content-lg-start">
            <p class="lead fw-normal mb-0 me-3">Sign in with</p>            
          </div>

          <div class="divider d-flex align-items-center my-4">
            <p class="text-center fw-bold mx-3 mb-0">Or</p>
          </div>
          
          <!-- id input -->
          <div class="form-outline mb-4">
            <input type="text" id="id" name="id" class="form-control form-control-lg"
              placeholder="Enter a valid id" />
            <label class="form-label" for="form3Example3">Id</label>
          </div>
          
          <!-- Password input -->
          <div class="form-outline mb-3">
            <input type="password" id="pwd" name="pwd" class="form-control form-control-lg"
              placeholder="Enter password" />
            <label class="form-label" for="form3Example4">Password</label>
          </div>
          
          <div class="d-flex justify-content-between align-items-center">
            <!-- Checkbox -->
            <div class="form-check mb-0">
              <input class="form-check-input me-2" type="checkbox" value="" id="chk_save_id" />
              <label class="form-check-label" for="form2Example3">
                Remember me
              </label>
            </div>
            <a href="#!" class="text-body">Forgot password?</a>
          </div>
          
          <div class="text-center text-lg-start mt-4 pt-2">
          <!--  submit -> button으로 바꾸고 id="Login" 추가/ 아래에 함수 추가-->
            <button type="button" id="login" class="btn btn-primary btn-lg"
              style="padding-left: 2.5rem; padding-right: 2.5rem;">Login</button>
            <p class="small fw-bold mt-2 pt-1 mb-0">Don't have an account? 
            	<a href="#" onclick="account()" class="link-danger">Register</a>
            </p>
          </div>         
          
      	<!-- </form> -->
      	
      </div>      
    </div>    
  </div>
  
  <div class="d-flex flex-column flex-md-row text-center text-md-start justify-content-between py-4 px-4 px-xl-5 bg-primary">
    <!-- Copyright -->
    <div class="text-white mb-3 mb-md-0">
      Copyright © 2023. MultiCampus.
    </div>
    <!-- Copyright -->

    <!-- Right -->
    <div>
      <a href="#!" class="text-white me-4">
        <i class="fab fa-facebook-f"></i>
      </a>
      <a href="#!" class="text-white me-4">
        <i class="fab fa-twitter"></i>
      </a>
      <a href="#!" class="text-white me-4">
        <i class="fab fa-google"></i>
      </a>
      <a href="#!" class="text-white">
        <i class="fab fa-linkedin-in"></i>
      </a>
    </div>
    <!-- Right -->
  </div>  
  
</section>

<script type="text/javascript">

//login 버튼 누르면 이 함수 실행
$("#login").click(function () {
	
	$.ajax({
		url:"http://192.168.35.130 :3000/login",	// 내 아이피
		type:"post",
		data:{ id:$("#id").val(), pwd:$("#pwd").val() },
		
		success:function(mem){  //controller에서 mem으로 return 해줌
			// alert("mem:" + JSON.stringify(mem));	
			//{"id":"abc","pwd":null,"name":"홍길동","email":"abc@naver.com","auth":0}"
			//비밀번호는 안넘어옴! 애시당초 mapper에 없었음
			if(mem == ""){	//로그인 안 넘어왔을 때 빈문자로 넘어옴/ mem은 object
				alert('id 또는 password를 확인하세요');
				$("#id").val("");
				$("#pwd").val("");
				$("#id").focus();
			}else{	//로그인 넘어왔을 때 
				// session 저장 		1) localStorage  2) sessionStorage를 사용한다.
				// sessionStorage에는 무조건 문자열로 저장할 수 있다.
				//(스프링에서는 가져가서 controller에서 세션에 넣어줬다)
				//sessionStorage는 setAttribute 와 동일하다고 생각하면됨
				sessionStorage.setItem("login", JSON.stringify(mem));  // == setAttribute
									//문자열만 저장 가능해서 stringify를 통해 문자열로 바꿔줌.
				alert(mem.name + "님의 로그인을 환영합니다");
				
				location.href = "bbslist.html";
			}			
		},
		error:function(){
			alert('error');
		}		
	});	
});

function account() {	
	location.href = "regi.html";
}

let user_id = $.cookie("user_id");

if(user_id != null){	// 저장한 id가 있음
	$("#id").val(user_id);
	$("#chk_save_id").prop("checked", true);
}

$("#chk_save_id").click(function () {
	
	if( $("#chk_save_id").is(":checked") == true ){
		
		if( $("#id").val().trim() == "" ){
			alert('id를 입력해 주십시오');
			$("#chk_save_id").prop("checked", false);
		}else{
			// cookie를 저장 
			$.cookie("user_id", $("#id").val().trim(), { expires:7, path:'./' });
		}
		
	}else{
		$.removeCookie("user_id", { path:'./' });
	}	
});
</script>



</body>
</html>

*스프링부트에서는 form으로 데이터 날려주는게 아니라 aciton도 쓰지 않습니다.

*스프링부트의 뷰에서는 세션에 접근할 수 없습니다.(jsp가 아니니까 자바스크립트니까)
따라서 세션 넘겨받는 방법은 두가지로 나뉩니다.
  1) 컨트롤러를 통해서 에이젝스로 넘겨받는 방법
  2) sessionStorage 를 통해 넘기는 방법
    이때, sessionStorage에는 무조건 문자열로 저장할 수 있습니다.

 

regi.html 회원가입페이지

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.3/dist/jquery.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.8/css/all.css">
</head>
<body>

<!-- 수정해야할 것 : name -> id로 바꾸기
 id, name, email, pwd 
 빈칸, 글자수비교 등등은 백앤드가 아니라 프론트앤드에서 다 하는것-->
<article class="card-body mx-auto" style="max-width: 400px;">

	<h4 class="card-title mt-3 text-center">회원가입</h4>	
	
	<!-- <form action="regiAf.do" method="post">  이제 controller로 보내면 안됨. -->
	<form id="frm">
	
	<div class="form-group input-group">
		<div class="input-group-prepend">
		    <span class="input-group-text"> <i class="fa fa-user"></i> </span>
		 </div>
        <input id="id" name="id" class="form-control" placeholder="id" type="text">   
           
    </div> <!-- form-group// -->
    
    <div class="form-group input-group">
    	<button type="button" id="idChkBtn" class="btn btn-danger">id check</button> 
    	<p id="idcheck" style="margin-left:10px;"></p> 
    </div>    
    	
	<div class="form-group input-group">
		<div class="input-group-prepend">
		    <span class="input-group-text"> <i class="fa fa-user"></i> </span>
		 </div>
        <input id="name" name="name" class="form-control" placeholder="Full name" type="text">
    </div> <!-- form-group// -->
    
    <div class="form-group input-group">
    	<div class="input-group-prepend">
		    <span class="input-group-text"> <i class="fa fa-envelope"></i> </span>
		 </div>
        <input id="email" name="email" class="form-control" placeholder="Email address" type="email">
    </div> <!-- form-group// -->
    
    <div class="form-group input-group">
    	<div class="input-group-prepend">
		    <span class="input-group-text"> <i class="fa fa-phone"></i> </span>
		</div>
		<select class="custom-select" style="max-width: 120px;">
		    <option selected="selected">+02</option>
		    <option value="1">+032</option>
		    <option value="2">+041</option>
		    <option value="3">+053</option>
		</select>
    	<input name="" class="form-control" placeholder="Phone number" type="text">
    </div> <!-- form-group// -->
    <div class="form-group input-group">
    	<div class="input-group-prepend">
		    <span class="input-group-text"> <i class="fa fa-building"></i> </span>
		</div>
		<select class="form-control">
			<option selected="selected">직업</option>
			<option>디자이너</option>
			<option>프로그래머</option>
			<option>자영업</option>
		</select>
	</div> <!-- form-group end.// -->
    <div class="form-group input-group">
    	<div class="input-group-prepend">
		    <span class="input-group-text"> <i class="fa fa-lock"></i> </span>
		</div>
        <input id="pwd" name="pwd" class="form-control" placeholder="Create password" type="password">
    </div> <!-- form-group// -->
    
    <div class="form-group input-group">
    	<div class="input-group-prepend">
		    <span class="input-group-text"> <i class="fa fa-lock"></i> </span>
		</div>
        <input class="form-control" placeholder="Repeat password" type="password">
    </div> <!-- form-group// --> 
                                         
    <div class="form-group">
    	<!-- 수정: type="submit"(서버로 전송) -> type="button" 
    			  regiBtn id 추가 (회원가입 등록 버튼)-> 밑에서 버튼 함수처리 할 것임.
    	-->
        <button type="button" id="regiBtn" class="btn btn-primary btn-block"> Create Account  </button>
    </div> <!-- form-group// -->      
    <p class="text-center">Have an account? <a href="login.do">Log In</a> </p> 
    
    </form>
   
                                                                 
<!-- </form> -->
</article>

<script type="text/javascript">
$(document).ready(function() {
	
	$("#idChkBtn").click(function() {	
		$.ajax({
			type:"post",
			url:"http://localhost:3000/idcheck",	// 달라지는 부분 (원래 idcheck.do)
			data:{ "id":$("#id").val() },	//id가 넘어감.
			success:function(msg){				
				if(msg == "YES"){
					$("#idcheck").css("color", "#0000ff");
					$("#idcheck").text("사용할 수 있는 아이디입니다");
				}else{
					$("#idcheck").css("color", "#ff0000");
					$("#idcheck").text("사용중인 아이디입니다");
					$("#id").val("");
				}
			},
			error:function(){
				alert('error');
			}
		});
	});
	
//컨트롤러로 안 가고 내부에서 해결해야되기 때문에 regiBtn 클릭 함수 추가
	$("#regiBtn").click(function() {	
		// alert('regiBtn');
		/*
			//	스프링에서 name이라고 했던것을 스프링부트에서 id형태로 바꿔준 이유!
		let params = { 
						id:$("#id").val(), 
						pwd:$("#pwd").val(), 
						name:$("#name").val(), 
						email:$("#email").val() 
					};*/
			
	//보낼 데이터가 많을 때는 이렇게
		let params = $("#frm").serialize();  //name(id가 아니라 name) 값을 json형태로 넣어줌.
	//	alert(params);
	
/*
let params = $("#frm").serialize();
->  jQuery를 사용하여 HTML 폼(form)의 입력된 데이터를 가져오는 방법

.serialize()의 역할 : name에 있는 값을 json으로 넣어준다.
(이론)선택한 폼의 모든 입력 필드의 이름과 값을 URL 인코딩된 문자열로 직렬화한다.
예를 들어, 입력 필드 "name"의 값이 "John Doe"이고 "email"의 값이 "johndoe@example.com"이면 
결과는 "name=John+Doe&email=johndoe%40example.com"과 같다.
따라서, params 변수에는 선택한 폼의 입력 필드의 이름과 값이 URL 인코딩된 문자열 형식으로 저장됨.
이렇게 직렬화된 데이터는 일반적으로 웹 애플리케이션에서 서버에 데이터를 전송할 때 사용됨
*/

		$.ajax({
			url:"http://localhost:3000/addmember",
			type:"post",
	
		//	data:{ id:$("#id").val(), pwd:$("#pwd").val(), name:$("#name").val(), email:$("#email").val() },
			data:params,
			success:function(msg){
			//	alert(msg);
				if(msg == "YES"){
					alert($("#id").val() + "님 환영합니다");
					location.href = "login.html";
				}else{
					alert("가입되지 않았습니다. 다시 가입해 주세요");
				}			
			},
			error:function(){
				alert("error");
			}			
		});		
		
	});
	
});
</script>

</body>
</html>

댓글