쿠키(Cookie), 세션(Session)

박영준·2023년 9월 6일
0

CS

목록 보기
10/16

쿠키 vs 세션 은 개발자 면접에서 자주 나오는 질문 중의 하나!

1. 등장 배경

1) stateful(상태 유지) VS stateless(무상태)

stateful (상태 유지)

  • 정의

    • 클라이언트와 서버 관계에서 서버가 클라이언트의 상태를 보존함을 의미

    • 클라이언트의 이전 요청이 서버에 전달되었을 때,
      클라이언트의 다음 요청이 이전 요청과 관계가 이어지는 것을 의미

    • Stateful 프로토콜

      • Stateless 프로토콜과 반대되는 개념
      • 서버의 내부 상태 유지를 요구하는 프로토콜
  • 예시

    • 클라이언트 : 딸기 한박스 나중에 주문할게요
      서버 : ok

      (3일 뒤)
      클라이언트 : 저번에 그거 주세요
      서버 : 딸기 한박스 전송!

stateless (무상태)

  • 정의

    • 무상태 = 상태를 유지하지 않는다.

    • 이전에 요청한 정보에 대해서 서버는 알 수 없다.

    • Stateless 프로토콜

      • 어떠한 이전 요청(Request)과도 무관한 각각의 요청을 독립적인 트랜잭션으로 취급하는 통신 프로토콜
      • 서버가 복수의 요청 시간대에서의 각각의 통신 파트너에 대한 세션 정보나 상태 보관을 요구하지 않는다
  • 예시

    • 클라이언트 : 딸기 한박스 나중에 주문할게요

    • 서버 : ok

      (3일 뒤)
      클라이언트 : 저번에 그거 주세요
      서버 : ? 그게 뭐야

2) stateful 과 쿠키 & 세션

HTTP 통신이 Stateless 프로토콜이다.
요청(Request) -> 응답(Response)이 종료되면 연결을 끊는 처리 방식

그러나,
User 입장에서 웹 페이지의 변동 사항이 생길 때마다 연결이 초기화되어서, 매번 다시 로그인해야 한다고 하면 매우 불편할 것이다.
로그인 상태(어떤 상태든)를 유지해야 할 때, 그 상태(누가 로그인 중인지) 를 기억하기 위해 쿠키, 세션, 토큰을 사용하게 된다.

2. 쿠키 VS 세션

쿠키

개발자도구 > Application(애플리케이션) > Storage(저장용량) > Cookies(쿠키) 에 도메인 별로 저장

1) 정의

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

  • 사용자에게 발급된 세션을 열기 위한 열쇠(SESSION ID)

  • 쿠키만으로 인증을 사용할 경우, 서버의 도움 없이 클라이언트가 인증 정보를 책임지게 된다. --> 보안 취약

  • 사용처: 장바구니, 자동로그인 설정

2) 구성요소

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

  • Value (값) : 쿠키의 값

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

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

  • Expires (만료기한) : 쿠키의 만료기한 (만료기한 지나면 삭제됩니다.)

3) 장단점

장점

  • 쿠키가 담긴 HTTP 요청(Request)이 통신 도중에 제 3자에게 노출되더라도,
    쿠키에 담긴 Session ID와 같은 정보는 자체로 유의미한 값을 갖고 있지 않음

  • 서버의 저장 공간 절약

    • 쿠키 정보는 클라이언트에 저장되기 때문에, 서버의 자원 사용이 적어서 서버의 부하 감소

단점

  • 제한된 저장 공간, 제한된 쿠키 개수
    (쿠기 개수 : 사이트별로 20개, 총 300개)

  • 웹 브라우저마다 지원 형태가 다르므로, 웹 브라우저를 변경할 경우 다른 웹 브라우저에서 저장한 쿠키 사용 불가

  • 쿠키 용량이 제한되어 있기 때문에, 많은 정보 저장이 어려움

  • 쿠키 사이즈가 클 경우, 네트워크 부하 가능성

  • 사용자가 보안상 문제로 쿠키 사용을 거부할 경우, 사용 불가능

  • 클라이언트에 저장된 쿠키를 송수신하는 과정에서 쿠키 정보의 탈취 or 변조 위험성

4) 사용법

@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) {      // @CookieValue(쿠키 이름) 으로 가져오기 -> 변수 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());
        }
    }
}

쿠키가 생성된 것을 확인 할 수 있다.

생성된 쿠키를 가져올 수 있다.

세션

1) 정의

  • 서버에서 가지고 있는 정보

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

  • 사용자 개념에서 쿠키가 세션ID 보다 더 큰 범주 → 세션ID를 쿠키라고 봐도 무방함. 세션ID를 쿠키로 저장하는 셈

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

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

⇨ 결론적으로, 인증의 책임을 서버가 지게하기 위해 세션을 사용 (사용자가 해킹당하는 것보단 서버가 해킹당하는게 훨씬 어렵다)

2) 장단점

장점

  • (비교적) 보안이 좋음

    • 브라우저를 닫거나, 서버에서 세션을 삭제했을 때에만 삭제되기 때문
    • 사용자의 정보를 서버에서만 관리하기 때문에, 클라이언트에서 수정될 우려가 없음
  • 각 유저별로 고유 Session ID 를 부여하므로, 유저를 구분하여 각 유저 요구에 맞는 서비스 제공 가능

  • 클라이언트의 웹 브라우저에 의존하지 않음

  • Session ID만 전송하기 때문에, 세션의 크기가 커도 네트워크 부하가 거의 없음

단점

  • 세션 하이재킹 공격에 대한 대비가 필요
    (로그인한 상태를 가로채는 공격)

  • 서버에 세션에 대한 별도의 추가 공간이 필요

    • 사용자가 많아질수록, 서버의 메모리 사용량이 증가하기 때문
  • Multi Server 환경에서는 정합성 이슈가 발생될 수 있어 세션 클러스터링 도입이 필요
    (정합성 : 데이터의 올바른 유/무와 무관하게, 데이터들의 값이 서로 일치하는 상태)
    (세션 클러스터링 : 2대 이상의 WAS(웹 어플리케이션 서버) 또는 서버를 사용할 때 로드 밸런싱, 장애 대비 등 세션을 공유하는 것)

3) 사용법

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

    public static final String AUTHORIZATION_HEADER = "Authorization";

    // 세션 생성
    @GetMapping("/create-session")
    public String createSession(HttpServletRequest req) {
        // 세션이 존재할 경우 세션 반환,
        // 없을 경우 새로운 세션을 생성한 후 반환
        HttpSession session = req.getSession(true);

        // 세션에 저장될 정보 Name - Value 를 추가합니다.
        session.setAttribute(AUTHORIZATION_HEADER, "Robbie Auth");

        return "createSession";
    }

    // 세션 가져오기
    @GetMapping("/get-session")
    public String getSession(HttpServletRequest req) {
        // 세션이 존재할 경우 세션 반환,
        // 없을 경우 null 반환
        HttpSession session = req.getSession(false);

        String value = (String) session.getAttribute(AUTHORIZATION_HEADER); // 가져온 세션에 저장된 Value 를 Name 을 사용하여 가져옵니다.
        System.out.println("value = " + value);

        return "getSession : " + value;
    }
}

간단 정리

3. 쿠키 & 세션

쿠키와 세션의 동작 방식

서버는 세션ID 를 사용하여 세션을 유지

그래서 결론은?
사용자(클라이언트)는 쿠키를 이용
서버에서는 쿠키를 받아 세션의 정보를 접근하는 방식으로 인증

profile
개발자로 거듭나기!

0개의 댓글