Spring

27. 쿠키(cookie) - 패스트캠퍼스 백엔드 부트캠프 3기

gkss2tpt 2025. 2. 9. 19:28

1. loginForm.jsp

<%@ page contentType="text/html;charset=utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page import="java.net.URLDecoder" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css" />
    <style>
        * { box-sizing:border-box; }
        a { text-decoration: none; }
        form {
            width:400px;
            height:500px;
            display : flex;
            flex-direction: column;
            align-items:center;
            position : absolute;
            top:50%;
            left:50%;
            transform: translate(-50%, -50%) ;
            border: 1px solid rgb(89,117,196);
            border-radius: 10px;
        }
        input[type='text'], input[type='password'] {
            width: 300px;
            height: 40px;
            border : 1px solid rgb(89,117,196);
            border-radius:5px;
            padding: 0 10px;
            margin-bottom: 10px;
        }
        button {
            background-color: rgb(89,117,196);
            color : white;
            width:300px;
            height:50px;
            font-size: 17px;
            border : none;
            border-radius: 5px;
            margin : 20px 0 30px 0;
        }
        #title {
            font-size : 50px;
            margin: 40px 0 30px 0;
        }
        #msg {
            height: 30px;
            text-align:center;
            font-size:16px;
            color:red;
            margin-bottom: 20px;
        }
    </style>
</head>
<body>
<form action="<c:url value='/login/login'/>" method="post" onsubmit="return formCheck(this);">
    <h3 id="title">Login</h3>
    <div id="msg">
        <c:if test="${not empty param.msg}">
            <i class="fa fa-exclamation-circle"> ${URLDecoder.decode(param.msg)}</i>
        </c:if>
    </div>
    <input type="text" name="id" placeholder="이메일 입력" autofocus>
    <input type="password" name="pwd" placeholder="비밀번호">
    <button>로그인</button>
    <div>
        <label><input type="checkbox" name="rememberId"> 아이디 기억</label> |
        <a href="">비밀번호 찾기</a> |
        <a href="">회원가입</a>
    </div>
    <script>
        function formCheck(frm) {
            let msg ='';

            if(frm.id.value.length==0) {
                setMessage('id를 입력해주세요.', frm.id);
                return false;
            }

            if(frm.pwd.value.length==0) {
                setMessage('password를 입력해주세요.', frm.pwd);
                return false;
            }

            return true;
        }

        function setMessage(msg, element){
            document.getElementById("msg").innerHTML = ` ${'${msg}'}`;

            if(element) {
                element.select();
            }
        }
    </script>
</form>
</body>
</html>
  • LoginController
@Controller
@RequestMapping("/login")
public class LoginController {
    @RequestMapping("/login")
    public String loginForm(){
        return "loginForm";
    }
}

  • 소스 파일 분석

  • 전송하기 버튼을 누르면 post버튼을 누르면 login/login으로 가게 된다.

  • 2개의 필드 id, pwd

  • 체크박스 rememberId

  • form체크 아이디와 패스워드를 체크해준다.
  • loginForm을 수정
@Controller
@RequestMapping("/login")
public class LoginController {
    @GetMapping("/login")
    public String loginForm(){
        return "loginForm";
    }

    @PostMapping("/login")
    public String login(String id, String pwd, String rememberId) throws Exception{
        // 1. id와 pwd를 확인
        if(!loginCheck(id, pwd)) {
            String msg = URLEncoder.encode("id 또는 pwd가 일치하지 않습니다.", "UTF-8");
            // 3. 일치하지 않으면, loginForm으로 이동
            return "redirect:/login/login?msg="+msg;
        }
        // 2. id와 pwd가 일치하면, 홈으로 이동
        return "loginForm";
    }

    private boolean loginCheck(String id, String pwd) {
        return "asdf".equals(id) && "1234".equals(pwd);
    }
}

  • 로그인 성공시 돌아갈 곳을 만들어준다.
  • HomeController
@Controller
public class HomeController {
    @RequestMapping(value = "/", method= RequestMethod.GET)
    public String home() {
        return "index";
    }
}
  • index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>fastcampus</title>
	<link rel="stylesheet" href="<c:url value='/resources/css/menu.css'/>">
	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css"/>
</head>
<body>
<div id="menu">
	<ul>
		<li id="logo">fastcampus</li>
		<li><a href="<c:url value='/'/>">Home</a></li>
		<li><a href="<c:url value='/board/list'/>">Board</a></li>
		<li><a href="<c:url value='/login/login'/>">login</a></li>
		<li><a href="<c:url value='/register/add'/>">Sign in</a></li>
		<li><a href=""><i class="fas fa-search small"></i></a></li>
	</ul>
</div>
<div style="text-align:center">
	<h1>This is HOME</h1>
	<h1>This is HOME</h1>
	<h1>This is HOME</h1>
</div>

  • 정적 리소스 menu.css 

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

a { text-decoration: none;  }

ul {
    list-style-type: none;
    height: 48px;
    width: 100%;
    background-color: #30426E;
    display: flex;
}

ul > li {
    color: lightgray;
    height : 100%;
    width:90px;
    display:flex;
    align-items: center;
}

ul > li > a {
    color: lightgray;
    margin:auto;
    padding: 10px;
    font-size:20px;
    align-items: center;
}

ul > li > a:hover {
    color :white;
    border-bottom: 3px solid rgb(209, 209, 209);
}

#logo {
    color:white;
    font-size: 18px;
    padding-left:40px;
    margin-right:auto;
    display: flex;
}

  • 기본적인 뼈대가 완성되었다.

2. 쿠키란?

  • 이름과 값의 쌍으로 구성된 정보. 아스키 문자만 가능
  • 서버에서 생성 후 전송, 브라우저에 저장. 유효기간 이후 자동 삭제
  • 서버에 요청시 domain, path가 일치(하위 경로포함)하는 경우에만 자동 전송
Cookie cookie = new Cookie("id", "asdf");	// 쿠키 생성
cookie.setMaxAge(60*60*24);			// 유효기간 설정(초)
response.addCookie(cookie);			// 응답에 쿠키 추가

 

3. 쿠키의 삭제와 변경

  • 삭제
Cookie cookie = new Cookie("id", "");	// 변경할 쿠키와 같은 이름 쿠키 생성
cookie.setMaxAge(0);			// 유효기간을 0으로 설정(삭제)
response.addCookie(cookie);		// 응답에 쿠키 추가
  • 변경
Cookie cookie = new Cookie("id", "");		// 변경할 쿠키와 같은 이름 쿠키 생성.
cookie.setValue(URLEncoder.encode("남궁성"));	// 값의 변경
cookie.setDomain("www.fastcampus.co.kr");	// 도메인의 변경
cookie.setPath("/ch2");				// 경로의 변경
cookie.setMaxAge(60*60*24*7);			// 유효기간의 변경
response.addCookie(cookie);			// 응답에 쿠키 추가

 

4. 쿠키 읽어 오기

Cookie[] cookies = request.getCookies();	// 쿠키 읽기

for(Cookie cookie : cookies) {
    String name = cookie.getName();
    String value = cookie.getValue();
    
    System.out.printf("[cookie]name=%s, value=%s%n", name, value);
}
  • 쿠키가 있으면 아이디를 불러오고, 체크박스를 체크해줘야한다.
<input type="text" name="id" value="${cookie.id.value}" placeholder="이메일 입력" autofocus>
<input type="password" name="pwd" placeholder="비밀번호">
<button>로그인</button>
<div>
    <label><input type="checkbox" name="rememberId" ${empty cookie.id.value ? "" : "checked"}> 아이디 기억</label> |
    <a href="">비밀번호 찾기</a> |
    <a href="">회원가입</a>
</div>

  • Aplication의 Cookies를 직접 만들어줬다.

  • 새로고침 하면 쿠키의 id.value와 체크박스가 잘 되어 나온다.

5. 컨트롤러에서 쿠키 생성하기

@PostMapping("/login")
public String login(String id, String pwd, String rememberId) throws Exception{
    System.out.println("id="+id);
    System.out.println("pwd="+pwd);
    System.out.println("rememberId="+rememberId);
    // 1. id와 pwd를 확인
    if(!loginCheck(id, pwd)) {
        String msg = URLEncoder.encode("id 또는 pwd가 일치하지 않습니다.", "UTF-8");
        // 2-1. 일치하지 않으면, loginForm으로 이동
        return "redirect:/login/login?msg="+msg;
    }
    // 2-2. id와 pwd가 일치하면, 홈으로 이동
    return "redirect:/";
}
  • rememberId(체크박스)가 String이라서 on으로 나온다.

@PostMapping("/login")
public String login(String id, String pwd, boolean rememberId) throws Exception{
    System.out.println("id="+id);
    System.out.println("pwd="+pwd);
    System.out.println("rememberId="+rememberId);
    // 1. id와 pwd를 확인
    if(!loginCheck(id, pwd)) {
        String msg = URLEncoder.encode("id 또는 pwd가 일치하지 않습니다.", "UTF-8");
        // 2-1. 일치하지 않으면, loginForm으로 이동
        return "redirect:/login/login?msg="+msg;
    }
    // 2-2. id와 pwd가 일치하면, 홈으로 이동
    return "redirect:/";
}

  • 쿠키 저장 작성
@PostMapping("/login")
public String login(String id, String pwd, boolean rememberId, HttpServletResponse response) throws Exception{
    System.out.println("id="+id);
    System.out.println("pwd="+pwd);
    System.out.println("rememberId="+rememberId);
    // 1. id와 pwd를 확인 
    if(!loginCheck(id, pwd)) {
        String msg = URLEncoder.encode("id 또는 pwd가 일치하지 않습니다.", "UTF-8");
        // 2-1. 일치하지 않으면, loginForm으로 이동
        return "redirect:/login/login?msg="+msg;
    }
    // 2-2. id와 pwd가 일치하면
    // 1. 쿠키를 생성
    Cookie cookie = new Cookie("id", id);
    // 2. 응답에 저장
    response.addCookie(cookie);
    // 3. 홈으로 이동
    return "redirect:/";
    }

  • 로그인 해주고 다시 돌아오면...

  • 쿠기가 잘 저장되어있다.
  • 체크박스가 활성화되어있으면 쿠키 생성, 아닐 경우 쿠키가 삭제 되어야한다.
@PostMapping("/login")
public String login(String id, String pwd, boolean rememberId, HttpServletResponse response) throws Exception{
    System.out.println("id="+id);
    System.out.println("pwd="+pwd);
    System.out.println("rememberId="+rememberId);
    // 1. id와 pwd를 확인
    if(!loginCheck(id, pwd)) {
        String msg = URLEncoder.encode("id 또는 pwd가 일치하지 않습니다.", "UTF-8");
        // 2-1. 일치하지 않으면, loginForm으로 이동
        return "redirect:/login/login?msg="+msg;
    }
    // 2-2. id와 pwd가 일치하면
    // 체크박스가 true이면
    if(rememberId){
        // 쿠키를 생성
        // 1. 쿠키를 생성
        Cookie cookie = new Cookie("id", id);
        // 2. 응답에 저장 
        response.addCookie(cookie);
    } else{
        // 쿠키를 삭제
        Cookie cookie = new Cookie("id", id);
        cookie.setMaxAge(0);
        response.addCookie(cookie);
    }

    // 3. 홈으로 이동
    return "redirect:/";
}