HTTP 프로토콜의 가장 큰 특징중 하나는 사용자가 브라우저에서 서버 어떠한 요청(Request)를 보내면, 서버는 요청에 맞는 응답을(Response)를 보내주고, 바로 연결을 끊는다는 것이다.
HTTP 통신이 모두 끝난 후, 클라이언트와 서버는 연결되었던 상태정보를 유지하지 않는 특징이 있다. 이를 “Stateless”하다고 한다.
어떤 하나의 A 사이트에 접속 한다고 했을 때, 처음 접속했을 때와, 이 연결에서 새로고침을 하여 접속했다고 생각해보자.
A사이트에 두번의 통신이 이루워졌다. 이때 연속하여 전달된 두 개의 요청은 서로 아무 연관이 없는 독립적인 연결이라는 것이다.
서버에 입장에서 생각해보면, 자신에게 요청을 보낸 이 친구가 과거에 요청을 보낸적이 있는지 기억을 하지 못하는…기억 상실증 에 걸리는 것이다.
이러한 Stateless한 특징은 쇼핑몰의 장바구니, 로그인 등과 같이 일관된 방식과 내용으로 사용자가 페이지와 상호작용 하길 원할 때 문제가 생긴다.
“쿠키(Cookie)와 세션(Session)”은 이러한 HTTP 프로토콜의 특징들을 보안하기 위해 사용한다.
서버 관점에서는 쿠키를 통해 이전에 요청을 보냈던 이력이 있는지 확인할 수 있는 수단이 되는 것이고,
사용자 관점에서 웹 페이지가 계속 동일한 상태를 유지하게 하여 연속성있는 유연한 경험을 할 수 있도록 도와주는 기술이다.
“웹 페이지(서버)에 접속한 사용자(요청자)의 정보를 “사용자의 PC에 저장”하는 작은 파일이다.”
“HTTP의 Stateless”한 특징을 보안하기 위해 쿠키를 사용한다고 하였다. 웹 페이지를 제공해주는 웹 서버에서는 자신에게 요청을 보낸 사용자의 정보를 기억하기 위해 어떠한 형태로 파일을 구성하여, 요청을 보낸 사용자에게 응답(Response)와 함께 파일(Cookie)을 전달하여, 사용자의 PC에 저장하도록 한다.
이후 요청부터는 해당 Cookie를 함께 전달받아 웹 서버가 이전에 요청이 들어왔던 사용자인지 파악하고, 그에 맞는 응답을 전달해주는 방식이다!
(Cookie는 나 누구에요~ 알려주며 요청보내라고 웹 서버가 웹 브라우저에게 주는 것!)
기본적으로 Cookies는 HTTP 프로토콜 상에서 구현되며 Cookie는 HTTP 메시지의 헤더(header) 영역을 통해서 송수신되도록 약속이 되어있다.
Cookie의 데이터 저장 형태는 기본적으로 <name>=<value> 형태를 지니는 단순한 문자열로 되어있다.
웹 서버가 요청자의 정보를 알아내기 위한 목적으로 사용하는 것이 Cookie 이기 때문에
→ “생성하고, 전달하는 주체 또한 웹 서버가 된다.”
하지만, 클라이언트(사용자)의 요청 없이는 데이터를 보낼 수 없다.
웹 서버에서는 첫 응답(Response)에 Set-Cookie로 요청(Require)한 사용자에게 전달해준다.
//Set-Cookie 예시
Set-Cookie: <cookie-name>=<cookie-value>
Set-Cookie: <cookie-name>=<cookie-value>
Set-Cookie: <cookie-name>=<cookie-value>
이렇게 웹 서버에서 작성한 내용을 HTTP header에 넣어 전달된다.
//HTTP 응답 예시
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
이렇게 되면 요청자의 브라우저에 Cookie가 자동으로 생성되어 저장이 된다.
(naver.com에 접속하였을 때 아래 같이 Cookie가 저장 되었음을 확인할 수 있다.)

두번째 요청(Require)부터는 웹 브라우저에는 생성된 Cookie를 HTTP Header를 통해 웹 서버에 전달하여 기존의 요청 정보들을 동일하게 유지하여 이용할 수 있게 된다.
Cookie의 요청하는 Header에는 아래와 같은 형식으로 여러개의 Cookie를 ; 으로 구분하여 나열할 수 있다.
//Cookie 요청 예시
Cookie: <이름>=<값>; <이름>=<값>; <이름>=<값>
브라우저에서 Cookie를 웹 서버에 보낼 때 기본적으로 Cookie를 보낸 서버가 속한 Domain으로만 쿠키를 돌려보내지만, 어떤 URI를 방문할 때, Cookie를 보낼지 말지를 제어해줄 수 있습니다.
(Domain + path) 를 통해 제어해줄 수 있습니다.
이것은 웹 서버에서 응답으로 Set-Cookie를 보낼 때 함께 명시 해줄 수 있습니다.
Set-Cookie: <쿠키 이름>=<쿠키 값>; Domain=도메인
Set-Cookie: <쿠키 이름>=<쿠키 값>; Path=경로
이렇게 응답 Header에 Domain 과, path 속성을 명시해주면, 좀 더 세밀하게 Cookie의 범위를 해당 경로로 축소시켜줄 수 있습니다.
사용자가 a.com 이라는 도메인에 멈무른다면,/index.html을 방문하던, /about.html에 방문하던 동일한 Cookie 를 돌려준다..
//HTTP 요청 예시
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
Cookie를 얼마나 지속하여 사용해야지를 웹 서버가 처음 쿠키를 보낼 때 결정 할 수 있습니다.
동일하게 Set-Cookie 응답 헤더에 명시하여 적용합니다.
// Cookie 유효기간 명시
Set-Cookie: <쿠키 이름>=<쿠키 값>; Expires=종료 시점
Set-Cookie: <쿠키 이름>=<쿠키 값>; Max-Age=유효 기간
이때, 유효기간이 별도로 명시되지 않아 브라우저의 세션이 종료될 때 만료되는 Cookie를 세션 쿠키(Session Cookie) 라고 합니다.
반면, 유효기간이 명시되어 있는 쿠키를 영속 쿠키(Persistent Cookie)라고 하고, 응답 헤더에 명시되어 있는 기간동안 유효하여 사용됩니다.
쿠키의 종류는 각각의 특성에 따라서 4가지로 구분할 수 있습니다.
응답 헤더에 Secure 을 명시하여 설정할 수 있습니다.
HttpOnly쿠키는 JavaScript의 Document.cookie API에 접근할 수 없습니다응답 헤더에 HttpOnly 을 명시하여 설정할 수 있습니다.
// 보안 속성이 입력된 응답 헤더 예시
Set-Cookie: <쿠키 이름>=<쿠키 값>; Secure; HttpOnly
SameSite 쿠키는 Cookie가 cross-site 요청과 함께 전송되지 않았음을 요구하게 만들어, cross-site 요청 위조 공격(CSRF)에 대해 어떤 보호 방법을 제공합니다.
SameSite 쿠키는 여전히 실험 중이며 모든 브라우저에 의해 아직 제공되지 않고 있습니다.
Strict : 퍼스트파티 쿠키 전송만 허용
Lax : 서드파티 쿠키라도 특수 케이스 GET, <a href>, <link rel=”prerender”> 엔 부분 허용
→ "보안 업데이트 후 최신 크롬 Default"
None : 서드파티 쿠키 모두 허용 (단, Secure 설정 강제 - - HTTPS 미사용시 MITM 탈취 방지)
브라우저의 개발자 도구안에서 Cookie 값을 쉽게 확인할 수 있어서 너무나 개방적으로 노출되어 있다. 또한 Cookie는 JavaScript로 조작할 수 있으며, 브라우저에 저장되는 것이다보니 PC의 하드디스크의 어느 경로안에 저장되어있게 된다. 그래서 쉽게 변조되고, 유실되기가 너무 쉬운 환경에 놓여있다.
그래서 Cookie에는 민감한 개인정보 등의 값을 저장해서는 안된다.
웹 브라우저 단위의 저장소이다보니 지역성 문제가 발생한다. 그래서 다른 PC에서나 심지어 같은 PC내의 다른 브라우저에서 같은 사이트에 접속 하더라도, 서로 다른 Cookie를 저장하는 것을 알 수 있다.
쿠키는 Domain + Path 만 일치한다면 해당 웹 서버로 모든 쿠키를 담아 보내다보니 많은 요청을 보내게 될 수 있다.
Cookie에 들어있는 정보의 양 만큼 요청의 크기가 커지게 되므로, 브라우저에서는 Cookie의 최대 크기를 “4KB”로 제한해 두었다.
“웹 브라우저가 Stateful 하도록 *웹 서버 측에 요청자 정보(웹 브라우저)의 식별자를 저장하는 기술*”
→ 웹 브라우저에서 Cookie로 id값을 넘겨주면, 그것에 맞는 정보를 Session에 저장한다.
즉, 브라우저가 종료되기 전까지 클라이언트의 요청을 유지하게 해주는 기술을 Session이라고 한다.
Cookie와 사용하는 목적은 크게 다르지 않다. 앞서 말했던 내용과 같이 HTTP의 Stateless 한 특성을 보완하기 위한 기술로, 브라우저에 값을 저장하는 Cookie와 다르게, Session은 웹 서버에 저장한다.
Session은 웹 서버에 저장하는 방식의 기술이다.
그렇기 때문에 요청자의 정보와 일치하는 데이터를 Session에서 주기 위해서는 데이터를 식별할 수 있는 Session-id 값이 필요하다.
이때 Session-id 값은 일반적으로 Cookie를 사용하여 요청자(클라이언트)에 저장된다.
그래서 정리하여 보면 Session의 동작 순서는 아래와 같다.
클라이언트가 서버에 접속하면 session-id가 Cookie를 통해 클라이언트에 저장됨.
클라이언트가 서버에 요청(Require)을 보낼 때마다, Cookie에 저장되어 있던 session-id가 요청과 함께 서버로 전송 됨.
서버는 session-id를 사용하여 Session 저장소에 저장된 해당하는 사용자의 상태 정보에 접근한다.
서버는 session에 필요한 작업을 수행 후, 응답(response)을 클라이언트에 반환한다.
→ 이때 변경된 session 정보가 응답(response)에 포함될 수 있다.
Session은 웹 서버에 저장이 되는 기술이기 때문에, Session 저장소에서 값을 식별할 수 있는 session-id가 있다면, 다른 브라우저에서, 다른 플랫폼에서도 같은 상태 정보를 공유할 수 있다.
또한, 그렇다보니 쉽게 접근할 수 없는 개인정보 등 민감한 정보들을 안전하게 저장하는데 사용한다.
Cookie와 Session을 비교하는 것은 큰 오류인 것 같다.
이 둘의 개념은 서로 대비되는 개념이 아니다. 이 둘은 저장하는 위치가 브라우저와 서버이냐의 차이점이 있지만, HTTP의 Stateless의 특징을 보완하기 위한 것이 동일하다.
Session을 효과적으로 이용하기 위해서 거의 반드시 Cookie를 사용해야하고, Cookie는 스스로 사용되기에는 담을 수 있는 정보의 양이 아주 제한적이기 때문에 이 둘은 거의 필연적으로 함께 사용하게 된다고 봐도 무방하다.