본문 바로가기

개발/프로젝트

[스프링부트 게시판] 16. 로그인 기능 구현

이번 게시글에서는 로그인 기능 구현에 대해 설명드리겠습니다.

 

이전에 만들었던 loginForm.html 을 사용하도록 하겠습니다.

 

[loginForm.html]

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
		xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
		layout:decorate="~{layouts/layout}">
<th:block layout:fragment="content">
<div class="container" style="margin-top:30px">
  	<form>
	  <div class="form-group">
	    <label for="username">Username:</label>
	    <input type="text" class="form-control" placeholder="Enter email" id="username">
	  </div>
	  <div class="form-group">
	    <label for="password">Password:</label>
	    <input type="password" class="form-control" placeholder="Enter password" id="password">
	  </div>
	  <div class="form-group form-check">
	    <label class="form-check-label">
	      <input class="form-check-input" type="checkbox"> Remember me
	    </label>
	  </div>
	  <button id="loginBtn" type="button" class="btn btn-primary">Login</button>
	</form>
</div>
</th:block>
</html>

 

joinForm.html처럼 form의 action 속성을 지우고 button의 type 속성을 button으로 변경, id 속성으로 'loginBtn'을 추가합니다.

 

이전 join.js처럼 이번엔 login.js를 생성하도록 하겠습니다.

 

UserController
login.js

 

login.js를 불러오기 위해 UserController에서 addScript에 login을 집어넣어 작동하는지 확인합니다.

 

크롬 관리자창

 

정상적으로 login.js를 불러오는 것을 확인할 수 있습니다.

 

[login.js]

window.addEventListener("DOMContentLoaded", function() {
	const loginBtn = document.getElementById("loginBtn");
	
	if(loginBtn) {
		loginBtn.addEventListener("click", () => {
			
			let data = {
				username : document.getElementById("username").value,
				password : document.getElementById("password").value,
			}
			
			// console.log(data); // 주석처리
			
			// ajax를 위한 XMLHttpRequest
			const xhr = new XMLHttpRequest();
			xhr.open('POST', "/toy/api/login"); // 요청방식과 URL
			xhr.responseType='json'; // 응답한 데이터를 Json으로 받도록 설정
			xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8'); // 보내는 데이터가 어떤 방식인지 설정
			xhr.send(JSON.stringify(data)); // 데이터를 보내기(여기서 JSON으로 변환)
			
			// 응답하여 갖고온 데이터 확인
			xhr.onload = () => {
				const data = xhr.response;
				if(data.success == true) {
					alert(data.message);
					location.href = "/toy/main";
				} else {
					alert(data.message);
				}
 			}
		});
	}
});

 

이전 join.js와 거의 동일하지만 로그인 메세지와 에러 관련으로 분기 처리를 위해 작업을 진행하도록 하겠습니다.

 

먼저 login을 하면서 username과 password를 비교하여 존재하는지에 대한 작업을 진행하겠습니다.

UserRepository
UserService

 

UserApiController
ExceptionController

 

Optional을 통해 orElseThrow로 에러를 출력한다면 에러에 설정한 메세지를 출력하여 나타나도록 ExceptionController를 수정하였습니다. 로그인이 성공한다면 User에 대한 정보를 session에 저장하여 로그아웃과 마이페이지를 출력하는 헤더 글씨를 생성합니다.

 

[header.html]

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
	<header th:fragment="header">
		<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
		  <a class="navbar-brand" href="#">메인페이지</a>
		  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavbar">
		    <span class="navbar-toggler-icon"></span>
		  </button>
		  <th:block th:if="${session.principal == null}">
		  <div class="collapse navbar-collapse" id="collapsibleNavbar">
		    <ul class="navbar-nav">
		      <li class="nav-item">
		        <a class="nav-link" th:href="@{/user/loginForm}">로그인</a>
		      </li>
		      <li class="nav-item">
		        <a class="nav-link" th:href="@{/user/joinForm}">회원가입</a>
		      </li>
		    </ul>
		  </div>  
		  </th:block>
		  <th:block th:unless="${session.principal == null}">
		  <div class="collapse navbar-collapse" id="collapsibleNavbar">
		    <ul class="navbar-nav">
		      <li class="nav-item">
		        <a class="nav-link" href="#">로그아웃</a>
		      </li>
		      <li class="nav-item">
		        <a class="nav-link" href="#">마이페이지</a>
		      </li>
		    </ul>
		  </div>  
		  </th:block>
		</nav>
	</header>
</html>

 

th:block으로 묶어 th:if, th:unless 속성으로 페이지를 출력합니다.

th:if는 기본으로 알고 있는 if문과 동일하며 unless는 else와 동일한 기능입니다. 로그인을 시도하도록 하겠습니다.

 

페이지
Console

 

헤더 변경 완료!

 

헤더의 변경이 된 것을 확인하실 수 있습니다.