본문 바로가기

CS

[네트워크] 쿠키와 세션 차이(..그리고 캐시)

쿠키와 세션은 왜 필요할까?


쿠키와 세션은 HTTP 프로토콜의 특징이자 약점을 보완하기 위해 사용합니다. HTTP 프로토콜은 connectionless, stateless한 특징이 있습니다. 요청과 응답이 끝나면 연결을 끊고, 그 순간 클라이언트와 서버는 상태를 유지하지 않습니다. 따라서 리소스 낭비가 줄어드는 장점이 있지만 통신 때마다 서버는 클라이언트를 확인하기 위한 인증과정을 거쳐야합니다.

하지만 로그인을 하고 로그인 상태를 유지한 채로 웹 서비스를 제공해야 하려면 어떻게 해야 할까요? 이처럼 이전 요청과 현재 요청이 같은 사용자에 의한 것인지 알기 위해 상태저장이 필요하며 이를 위해 쿠키와 세션이 필요한 것입니다.

쿠키(Cookie)란?


그렇다면 쿠키는 무엇인가요? 쿠키는 클라이언트(브라우저) 로컬에 저장되는 Key-Value쌍의 작은 데이터 파일입니다.(쿠키에 포함되는 정보는 키=값 형태로 저장)이름, 값, 유효 시간, 경로 등을 포함하며 클라이언트의 상태 정보를 브라우저에 저장해 이를 참조합니다. 쿠키는 사용자가 따로 요청하지 않아도 브라우저가 Request시에 Request Header를 넣어서 자동으로 서버에 전송합니다.

  • 쿠키 사용 예시 : 아이디, 비밀번호 저장, 쇼핑몰 장바구니, 팝업 시 오늘 더이상 보지 않음 체크 등
  • 기본적으로 서버에 저장하지만 세션 ID 등 식별 정보만 클라이언트에 쿠키로 저장

쿠키 동작 과정

  • 클라이언트가 서버에 요청, 서버에서 상태를 유지하고 싶은 값을 쿠키(cookie)로 생성, HTTP 헤더에 쿠키를 포함 시켜 응답
  • 웹 브라우저는 응답받은 메시지에 Set-Cookie라는 문자열이 있는지 확인하고 있으면 저장
  • 전달받은 쿠키는 웹브라우저에서 관리하고 있다가, 다음 요청 때 쿠키를 HTTP 헤더에 넣어서 전송
  • 서버에서는 쿠키 정보를 읽어 이전 상태 정보를 확인한 후 정보를 변경 할 필요가 있을 때 업데이트 등을 통하여 응답

쿠키 단점

  • CSRF(사용자의 권한을 이용한 공격), XSS(사용자의 민감한 정보 탈취)
  • 4kb, 부족한 용량
  • http 요청 시 항상 자동으로 전송, 불필요한 트래픽

세션(Session)이란?


세션은 쿠키를 기반으로 하지만 쿠키와는 달리 서버측에서 관리합니다. 서버에서 클라이언트를 구분하기 위해 세션 ID를 부여하며 웹 브라우저가 서버에 접속해서 브라우저를 종료할 때까지 인증상태를 유지합니다.

  • 세션 사용 예시 : 로그인 등 보안에 중요한 작업

세션 동작 과정

  • 클라이언트(웹브라우저)가 서버에 요청, 서버는 해당 웹브라우저(클라이언트)에 유일한 ID(Session ID)를 부여
  • 서버가 응답할 때 HTTP 헤더(Set-Cookie)에 Session ID를 포함해서 전송
  • 웹브라우저는 이후 웹브라우저를 닫기까지 다음 요청 때 부여된 Session ID가 담겨있는 쿠키를 HTTP 헤더에 넣어서 전송
  • 서버는 서버는 세션 ID를 확인하고, 세션에 있는 클라이언트 정보를 확인 후 응답

세션과 쿠키의 차이점


  • 저장 위치 : 쿠키-클라이언트, 세션-서버
  • 보안 : 쿠키의 경우 클라이언트에 저장되어 보안에 취약(request시 스니핑 당할 우려가 있음), 세션은 쿠키를 이용해 Session ID만 저장하고 이 값을 이용해 비교적 보안성이 좋습니다.(단 사용자가 많아지면 서버 메모리를 차지하며 서버에 과부하를 주게 되므로 성능 저하의 요인이 됨)
  • Lifecycle : 쿠키는 만료시간에 따라 브라우저를 종료해도 남아있을 수 있으나 세션은 브라우저 종료시 삭제됩니다.
  • 속도 : 쿠키는 클라이언트에 저장되어 빠르지만 세션의 경우 서버에 저장되어 서버의 처리가 필요가 쿠키보다 느립니다.

... 그리고 캐시는?

브라우저 저장소 구분(쿠키, 로컬스토리지, 세션스토리지)


공통점

  • 모두 클라이언트(브라우저)에 저장됨
  • 요청시 헤더에 전송하지 않음
  • 문자열만 저장, 직렬화를 통해 객체 전송 가능
  • 쿠키의 저장용량 부족 해결

로컬 스토리지와 세션 스토리지

  • 로컬 스토리지와 세션 스토리지는 HTML5에서 추가된 저장소
  • 로컬 스토리지와 세션 스토리지의 차이점은 데이터의 영구성
  • 로컬 스토리지의 데이터는 사용자가 지우지 않는 이상 계속 브라우저에 남아 있지만 세션 스토리지의 데이터는 윈도우나 브라우저 탭을 닫을 경우 제거됨
  • 지속적으로 필요한 데이터(자동 로그인 등)는 로컬 스토리지에 저장, 일회성 로그인 정보 등은 세션 스토리지에 저장하는 것이 편리
  • 두 스토리지는 모두 window 객체 안에 들어 있으며 storage 객체를 상속받아 공통의 메소드 존재
  • 로컬 스토리지: window.localStorage에 위치, 모두 문자열로 전환되어 저장, 용량 약 10mb
  • 세션 스토리지: window.sessionStorage에 위치, 로컬 스토리지와 다르게 데이터가 영구적으로 보관되지 않음, 용량 약 5mb, 같은 tab에서만 유효

웹 스토리지 문제점

  • xss에 취약(자바스크립트 접근 가능)
  • 독립된 스토리지(브라우저간 공유 불가능)
  • 만료기간 설정 불가, 동기적으로 작동해 메인스레드 블록킹

쿠키

  • 쿠키는 만료 기능이 있는 키-값 저장소
  • 쿠키에 나에 대한 정보를 담아서 서버로 보내면 서버는 쿠키를 읽어서 내가 누군지 파악(html은 상태를 저장하지 않음), 쿠키는 처음부터 서버와 클라이언트 간의 지속적인 데이터 교환을 위해 만들어졌기 때문에 서버로 계속 전송, 4kb 용량 제한
  • 이때 불필요한 데이터는 로컬스토리지와 세션 스토리지에 저장하고 서버에 보내지 않는다.

내용 추가


인증(Authenticaction)과 인가(Authorization)

  • 인증 : 리소스 접근을 허용하기 이전에 등록된 유저의 신원을 입증하는 과정
  • 인가 : 요청된 리소스에 접근할 수 있는 권한이 부여된 인증된 유저인지를 입증하는 과정(인증된 사용자에 대한 자원 접근 권한 확인)
  • OAuth : 다른 웹사이트 상의 자신들의 정보에 대해 접근 권한을 부여할 수 있는 공통적인 수단
  • 인증 요청 : Request Header 사용(사용자가 매번 인증을 해야 하는 문제)
  • 브라우저 스토리지 활용 : 보안 문제가 있음
  • 세션 활용 : 인증된 유저와 세션아이디를 응답의 헤더로 넘겨줌, 세션 만료기간을 정할 수 있으며 raw데이터를 주고받지 않아 보안이 상대적으록 강함
  • 서버 부하 -> 세션 db 대신 토큰 활용
  • 요청과 응답에 사용자의 인증과 인가를 처리하기 위해 Token을 사용

세션 db 대신 토큰 활용(JWT 토큰)

  • 서버를 여러개 뒀을 때 로드밸러서를 통해 요청을 보냄 -> 다음 요청 시 어느 서버에서 세션을 관리하는지 알기 어려움 -> 오버헤드 발생 -> 세션스토리지를 두고 서버에서 관리하는 세션을 한곳에서 관리함 -> 계속 인증 요청을 보내다보면 서버에 과부하가 걸림(무상태성이 특징인 http를 이용하여 상태성을 유지하려 했기 때문)
  • 토큰을 활용해 권한 등을 부여할 수 있음, 서버 여러대에 각자 시크릿키로 토큰을 해독해 인증을 진행할 수 있음
  • 사용자가 id와 password를 입력하여 로그인 -> 서버는 요청을 확인하고 secret key를 통해 Access token을 발급 -> JWT 토큰을 클라이언트에 전달 -> 클라이언트에서 API 을 요청할때 Authorization header에 Access token을 포함 -> 서버는 JWT Signature를 확인 후 사용자 정보 데이터를 반환-> 클라이언트의 로그인 정보를 서버 메모리에 저장하지 않고 토큰기반 인증 메커니즘을 제공
  • JWT 토큰 검증 : 헤더와 페이로드를 서버의 시크릿키로 서명을 하고 JWT 토큰의 서명정보와 비교(해커의 정보변경 방지)
  • JWT에는 필요한 모든 정보를 토큰에 포함하기 때문에 데이터베이스과 같은 서버와의 커뮤니케이션 오버 헤드를 최소화 할 수 있음(각 서버가 가진 시크릿키로 토큰을 관리하면 됨)
  • 처음 사용자를 등록할 때 Access token과 Refresh token이 모두 발급(유효기간을 두어 보안성 향상)
  • 서버는 리프레쉬 토큰만 저장소에 저장, 엑세스토큰이 만료되면 브라우저가 엑세스토큰과 리프레쉬 토큰을 같이 보내면 서버는 갱신한 액세스토큰을 클라이언트에 보냄