STS3 쇼핑몰 프로젝트[2] 로그인 페이지, 회원 가입 페이지
순서
1. 로그인, 회원 가입 페이지 제작
2. 로그인, 회원 가입 페이지 Controller 설정
로그인, 회원 가입 페이지 제작
로그인과 회원 가입 페이지의 이름은 각각 login.jsp, join.jsp로 정했습니다. 회원과 관련된 페이지를 체계적으로 관리하기 위해 src/main/webapp/WEB-INF/views 경로에 member 폴더를 추가한 후 해당 경로에 login.jsp, join.jsp를 생성합니다.
css 또한 src/main/webapp/resources/css 경로에 login 폴더를 추가한 후 login.css, signup.css를 추가하였습니다.
다음은 jsp, css 파일 코드입니다.
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="path" value="${pageContext.request.contextPath}" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>로그인</title>
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="${path}/resources/css/login/login.css" rel="stylesheet"/>
</head>
<body>
<header>
<jsp:include page="../common/header.jsp"/>
</header>
<main>
<div class="container">
<form id="login_form" method="post">
<div class="title">
<a href="/swan">SWAN</a>
</div>
<div class="input-box underline">
<input type="text" name="id" placeholder="아이디" required>
<div class="underline"></div>
</div>
<div class="input-box">
<input type="password" name="pwd" placeholder="비밀번호" required>
<div class="underline"></div>
</div>
<div class="input-box button">
<input type="button" class="login_button" value="로그인">
</div>
</form>
<div class="sign_up">
<a href="find_pwd_form">비밀번호 찾기</a> |
<a href="find_id_form">아이디 찾기</a> |
<a href="join">회원가입</a>
</div>
</div>
</main>
</body>
</html>
login.css
@charset "UTF-8";
@import url('https://fonts.googleapis.com/css2?family=Gowun+Dodum&family=IBM+Plex+Sans+KR:wght@200;300;400&family=Noto+Serif+KR:wght@500&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Gowun Dodum', sans-serif;
}
.container {
background: #fff;
max-width: 365px;
padding: 25px 30px;
border-radius: 5px;
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.15);
}
.container form .title {
font-size: 30px;
font-weight: 600;
margin: 20px 0 10px 0;
position: relative;
}
.container form .title:before {
content: '';
position: absolute;
height: 4px;
width: 33px;
left: 0px;
bottom: 3px;
border-radius: 5px;
}
.container form .input-box {
width: 100%;
height: 45px;
margin-top: 25px;
position: relative;
}
.container form .input-box input {
width: 100%;
height: 100%;
outline: none;
font-size: 16px;
border: none;
}
.container form .underline::before {
content: '';
position: absolute;
height: 2px;
width: 100%;
background: #ccc;
left: 0;
bottom: 0;
}
.container form .underline::after {
content: '';
position: absolute;
height: 2px;
width: 100%;
left: 0;
bottom: 0;
transform: scaleX(0);
transform-origin: left;
transition: all 0.3s ease;
background: linear-gradient(to left, #99004d 0%, #ff0080 100%);
}
.container form .input-box input:focus ~ .underline::after, .container form .input-box input:valid
~ .underline::after {
transform: scaleX(1);
transform-origin: left;
}
.container form .button {
margin: 40px 0 20px 0;
}
.container .input-box input[type="button"] {
background: linear-gradient(to right, #99004d 0%, #ff0080 100%);
font-size: 17px;
color: #fff;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s ease;
}
.container .input-box input[type="submit"]:hover {
letter-spacing: 1px;
background: linear-gradient(to left, #99004d 0%, #ff0080 100%);
}
.container .option {
font-size: 14px;
text-align: center;
}
a {
text-decoration: none;
text-color: #black;
}
.sign_up a:hover{
text-decoration: underline;
}
/* 로그인 실패시 경고글 */
.login_warn{
margin-top: 30px;
text-align: center;
color : red;
}
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" %>
<c:set var="path" value="${pageContext.request.contextPath}"/>
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="UTF-8">
<title>회원가입</title>
<link href="${path}/resources/css/login/signup.css" rel="stylesheet"/>
</head>
<body>
<header>
<jsp:include page="../common/header.jsp"/>
</header>
<main>
<div class="container">
<div class="title">
<a href="/swan">SWAN</a>
</div>
<div class="content">
<form id="join_form" method="post">
<div class="user-details">
<div class="input-box">
<span class="details">아이디</span>
<input type="text" name="id" id="userId" placeholder=" 6~16자 영문, 숫자" class="id_input" required>
</div>
<div class="input-box">
<span class="details">이름</span>
<input type="text" name="name" required class="user_input">
<span class="final_name_ck" style="color: red;">이름을 입력해주세요.</span>
</div>
<div class="input-box mail_wrap">
<span class="details mail_name">이메일</span>
<input type="text" name="email" class="mail_input" placeholder="이메일 입력" required style="width: 70%;">
<div class="mail_check_button" style="float: right;">
<span>인증번호 전송</span>
</div>
<span class="final_mail_ck" style="color: red;">이메일을 입력해주세요.</span>
</div>
<div class="input-box mail_check_input_box" id="mail_check_input_box_false">
<span class="details">인증번호 확인</span>
<input class="mail_check_input" disabled="disabled" placeholder="인증번호 입력">
<div class="clearfix"></div>
<span id="mail_check_input_box_warn"></span>
</div>
<div class="input-box">
<span class="details">전화번호</span>
<input type="tel" name="phone" placeholder=" Phone" required class="phone_input">
</div>
<div class="input-box">
<span class="details">비밀번호</span>
<input type="password" name="pwd" placeholder=" 영문, 숫자, 특수문자 8~16자" class="pwd" id="password_1" required style="width: 47%; margin-right: 4%;">
<input type="password" name="pwd2" placeholder=" 비밀번호 재확인" class="pwd" id="password_2" required style="width: 47%;">
</div>
<div class="input-box">
<span class="details">주소</span>
<input id="colFormLabelLg3" name="address" placeholder="주소를 입력하세요." required class="address_input1">
<span class="final_addr_ck" style="color: red;">주소를 입력해주세요.</span>
</div>
<div class="input-box">
<span class="details">상세 주소</span>
<input required name="address2" class="address_input2" placeholder="상세 주소를 입력하세요.">
</div>
</div>
<div class="gender-details">
<input type="radio" name="gender" id="dot-1" value="M">
<input type="radio" name="gender" id="dot-2" value="F">
<input type="radio" name="gender" id="dot-3" value="N">
<span class="gender-title">성별</span>
<div class="category">
<label for="dot-1">
<span class="dot one"></span>
<span class="gender">남자</span>
</label>
<label for="dot-2">
<span class="dot two"></span>
<span class="gender">여자</span>
</label>
<label for="dot-3">
<span class="dot three"></span>
<span class="gender">선택X</span>
</label>
</div>
</div>
<div class="button">
<input type="button" value="회원가입" class="join_button">
</div>
</form>
</div>
</div>
</main>
</body>
</html>
signup.css
@charset "UTF-8";
@import url('https://fonts.googleapis.com/css2?family=Gowun+Dodum&family=IBM+Plex+Sans+KR:wght@200;300;400&family=Noto+Serif+KR:wght@500&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Gowun Dodum', sans-serif;
}
main{
margin-top:10%;
width: 80%;
}
.container .title {
font-size: 25px;
font-weight: bold;
position: relative;
}
.container .title::before {
content: "";
position: absolute;
left: 0;
bottom: 0;
height: 3px;
width: 30px;
border-radius: 5px;
background: linear-gradient(to left, #99004d 0%, #ff0080 100%);
}
.content form .user-details {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin: 20px 0 12px 0;
}
form .user-details .input-box {
margin-bottom: 15px;
width: calc(100%/ 2 - 20px);
}
form .input-box span.details {
display: block;
font-weight: 500;
margin-bottom: 5px;
}
.user-details .input-box input {
height: 45px;
width: 100%;
outline: none;
font-size: 16px;
border-radius: 5px;
padding-left: 15px;
border: 1px solid #ccc;
border-bottom-width: 2px;
transition: all 0.3s ease;
}
.user-details .input-box input:focus, .user-details .input-box input:valid
{
border-color: #99004d;
}
form .gender-details .gender-title {
font-size: 20px;
font-weight: 500;
}
form .category {
display: flex;
width: 80%;
margin: 14px 0;
justify-content: space-between;
}
form .category label {
display: flex;
align-items: center;
cursor: pointer;
}
form .category label .dot {
height: 18px;
width: 18px;
border-radius: 50%;
margin-right: 10px;
background: #d9d9d9;
border: 5px solid transparent;
transition: all 0.3s ease;
}
#dot-1:checked ~ .category label .one, #dot-2:checked ~ .category label .two,
#dot-3:checked ~ .category label .three {
background: #99004d;
border-color: #d9d9d9;
}
form input[type="radio"] {
display: none;
}
form .button {
height: 45px;
margin: 35px 0
}
form .button input {
height: 100%;
padding:1%;
border-radius: 5px;
border: none;
color: #fff;
font-size: 18px;
font-weight: 500;
letter-spacing: 1px;
cursor: pointer;
transition: all 0.3s ease;
background: linear-gradient(135deg, #99004d 0%, #ff0080 100%);
float: right;
}
form .button input:hover {
/* transform: scale(0.99); */
background: linear-gradient(-135deg, #99004d 0%, #ff0080 100%);
}
@media ( max-width : 584px) {
.container {
max-width: 100%;
}
form .user-details .input-box {
margin-bottom: 15px;
width: 100%;
}
form .category {
width: 100%;
}
.content form .user-details {
max-height: 300px;
overflow-y: scroll;
}
.user-details::-webkit-scrollbar {
width: 5px;
}
}
@media ( max-width : 459px) {
.container .content .category {
flex-direction: column;
}
}
a{
text-decoration: none;
text-color: #black;
}
/* 중복아이디 존재하지 않는경우 */
.id_input_re_1 {
color: green;
display: none;
}
/* 중복아이디 존재하는 경우 */
.id_input_re_2 {
color: red;
display: none;
}
/* 비밀번호 확인 일치 유효성검사 */
.pwck_input_re_1{
color : green;
display : none;
}
.pwck_input_re_2{
color : red;
display : none;
}
/* 유효성 검사 문구 */
.final_id_ck{
display: none;
}
.final_pw_ck{
display: none;
}
.final_pwck_ck{
display: none;
}
.final_name_ck{
display: none;
}
.final_mail_ck{
display: none;
}
.final_addr_ck{
display: none;
}
.final_addr2_ck{
display: none;
}
.final_phone_ck{
display: none;
}
#mail_check_input_box_true{
background-color:white;
}
.correct{
color : green;
}
.incorrect{
color : red;
}
로그인, 회원 가입 페이지 Controller 설정
기존 SWANController 클래스가 있지만 회원과 관련된 요청을 따로 관리하기 위해 src/main/java/com.swan.controller 경로에 MemberController 클래스를 만들어줍니다.
MemberController.java 클래스에도 동일하게 @Controller 어노테이션과 Logger 변수를 선언해줍니다. MemberController에는 더불어 클래스 선언부에 @RequestMapping(value="/member") 어노테이션도 추가해줍니다. MemberController 사용을 명확하게 구분하기 위해 회원과 관련된 호출은 url 경로에 member를 타도록 설계했습니다.
package com.swan.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping(value = "/member")
public class MemberController {
private static final Logger logger = LoggerFactory.getLogger(MemberController.class);
// 회원가입 페이지 이동
@RequestMapping(value = "/join", method = RequestMethod.GET)
public void loginGET() {
logger.info("회원가입 페이지 진입");
}
// 로그인 페이지 이동
@RequestMapping(value = "/login", method = RequestMethod.GET)
public void joinGET() {
logger.info("로그인 페이지 진입");
}
}
MemberController.java 클래스에 로그인과 회원 가입 페이지를 호출하는 메서드 loginGET(), joinGET()를 추가해줍니다.
Controller를 설정했기 때문에 Tomcat 서버를 통해 테스트를 해봅니다.