Spring 숙련주차/1주차

4. 쿠키와 세션이란 무엇일까?

note994 2024. 8. 21. 22:46

쿠키와 세션

쿠키와 세션 모두 HTTP에 상태 정보를 유지(Stateful)하기 위해 사용된다. 즉, 쿠키와 세션을 통해 서버에서는 클라이언트 별로 인증 및 인가를 할 수 있게 된다.


쿠키

클라이언트에 저장될 목적으로 생성한 작은 정보를 담은 파일이다.

클라이언트인 웹 브라우저에 저장된 '쿠키'를 확인해보자

크롬 브라우저 기준으로 '개발자도구'를 열어보자

개발자 도구의 Application - Cookies

구성요소

Name(이름) : 쿠키를 구별하는 데 사용되는 키 (중복될 수 없음)

Value(값) : 쿠키의 값

Domain(도메인) : 쿠키가 저장된 도메인

Path(경로) : 쿠키가 사용되는 경로

Expires(만료기한) : 쿠키의 만료기한(만료기한 지나면 삭제된다)


세션

서버에서 일정시간 동안 클라이언트 상태를 유지하기 위해 사용된다.

서버에서 클라이언트 별로 유일무이한 '세션 ID'를 부여한 후 클라이언트 별 필요한 정보를 서버에 저장한다.

서버에서 생성한 '세션ID'는 클라이언트의 쿠키값('세션 쿠키'라고 부름)으로 저장되어 클라이언트 식별에 사용된다.

세션 동작 방식

위 그림에서와 같이 서버는 세션ID를 사용하여 세션을 유지한다.

1. 클라이언트가 서버에 1번 요청

2. 서버가 세션ID를 생성하고, 쿠키에 담아 응답 헤더에 전달
a. 세션 ID 형태 : "SESSIONID = 12A345"

3. 클라이언트가 쿠키에 세션ID를 저장 (세션쿠키)

4. 클라이언트가 서버에 2번 요청 (쿠키값(세션ID)을 포함하여 요청)

5. 서버가 세션ID를 확인하고, 1번 요청과 같은 클라이언트임을 인지

쿠키와 세션 비교


쿠키 다루기

spring-auth 프로젝트를 열기

 

auth 패키지 만들고 AuthController 클래스 생성

package com.sparta.springauth.auth;

import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

@RestController
@RequestMapping("/api")
public class AuthController {

    public static final String AUTHORIZATION_HEADER = "Authorization";

    @GetMapping("/create-cookie")
    public String createCookie(HttpServletResponse res) {
        addCookie("Robbie Auth", res);

        return "createCookie";
    }

    @GetMapping("/get-cookie")
    public String getCookie(@CookieValue(AUTHORIZATION_HEADER) String value) {
        System.out.println("value = " + value);

        return "getCookie : " + value;
    }

    public static void addCookie(String cookieValue, HttpServletResponse res) {
        try {
            cookieValue = URLEncoder.encode(cookieValue, "utf-8").replaceAll("\\+", "%20"); // Cookie Value 에는 공백이 불가능해서 encoding 진행

            Cookie cookie = new Cookie(AUTHORIZATION_HEADER, cookieValue); // Name-Value
            cookie.setPath("/");
            cookie.setMaxAge(30 * 60);

            // Response 객체에 Cookie 추가
            res.addCookie(cookie);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e.getMessage());
        }
    }
}

이 코드를 하나씩 살펴보자

먼저 이 코드는 쿠키를 생성하는 코드이다. addCookie를 살펴보자

addCookie의 첫번째 인자는 쿠키의 값을 받는다. 잘 보면 여기에 대입되는 값이 "Robbie Auth"인데 띄어쓰기가 되어있다.

 

공백이 있으면 쿠키에서 저장을 할 수 없다고 오류가 발생한다. 그래서 인코딩을 하고 공백부분을 모두 %20으로 처리되서 cookieValue에 담긴다.

 

인코딩된 cookie를 이용해 Cookie 객체를 생성한다. 첫 번째 인수는 Name, 두 번째 인수는 Value이다.

 

Cookie 클래스는 Spring에서 쿠키를 만들 수 있도록 제공하는 클래스이다.

 

그리고 setPath를 이용해 path를 설정하고, setMaxAge로 만료 기한을 정한다.

 

Servlet에서 만든 HttpServletResponse 객체에 만들어진 쿠키를 담는다. HttpServletResponse에 담긴 데이터는 자연스럽게 클라이언트로 반환된다.

쿠키를 가져오는 법

@CookieValue("쿠키의 name")

 

이걸 하면 value의 값으로 그 쿠키의 이름을 가진 쿠키의 값이 담긴다.

 

현재 예제에서의 쿠키 값은 "Robbie Auth"이다.

 

이제 이 서버를 실행시키고 url로 접속해 쿠키를 확인해볼 수 있다.


세션 다루기

AuthController 클래스

AuthController 클래스에 이 코드를 추가한다.

 

클라이언트에서 서버로 요청이 들어올 때 HttpServletRequest가 생성된다. 이걸 함수 인자로 선언해주면 받아올 수 있다.

 

38줄은 현재 받아온 Request 객체에 세션이 이미 존재한다면 그 세션을 session 변수에 담고 아니라면 새로운 세션을 담는코드이다.

 

AuthController 클래스
개발자 도구에서 본 Session

현재 세션의 Value의 값은 우리의 눈에는 이상한 값으로 보이지만 저 안에 createSession함수의 setAttribute 메서드를 통해 담은 정보가 들어있다.