[WEB] HTTP 쿠키

minidoo·2023년 4월 12일
0

WEB

목록 보기
6/8
post-thumbnail
post-custom-banner

쿠키 등장 배경

HTTP 프로토콜의 비연결성(Connectionless)과 무상태성(Stateless)라는 특징 때문에 서버는 클라이언트의 응답이 끝나면 연결 상태를 해제한다. 그러나 이로 인해 동일한 페이지에 접속해도 이전에 접속했던 사용자를 식별할 수 없게 되었다.

이 문제를 해결하기 위해 2가지 방법이 제안되었다.

  1. 쿠키 : 웹서버는 클라이언트에 특정 정보를 저장하도록 요청
  2. 세션 : 사용자 정보를 웹서버에 저장하고, 임의의 사용자 식별 ID를 만들어 클라이언트와 상호작용

즉, 쿠키와 세션은 웹서버와 클라이언트 간의 정보 교환을 가능하게 하는 기술이다.

MDN Web Docs

HTTP 쿠키(=웹 쿠키, 브라우저 쿠키)는 서버가 사용자의 웹 브라우저에 전송하는 작은 데이터 조각이다. 브라우저는 그 데이터 조각들을 저장해 놓았다가, 동일한 서버에 재요청 시 저장된 데이터를 함께 전송한다.

HTTP Header 쿠키 속성

Set-Cookie : 웹서버에서 클라이언트로 쿠키 전달(응답)

HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: name=minidoo

Cookie : 서버에서 받은 쿠키를 클라이언트가 저장하고, HTTP 요청시 서버로 쿠키 전달(요청)

GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: name=minidoo

Expires : 만료일자 / Max-Age : 초 단위로 지정 (쿠키의 생명 주기)

Set-Cookie: name=minidoo; Expires: Wed, 21 Oct 2023 07:10:11 GMT;

쿠키의 생명주기를 지정하지 않으면, 브라우저 창이 닫히면 쿠키가 삭제된다. (= 세션쿠키 ①)
반대로, 생명주기를 지정하면 웹 브라우저가 종료되어도 만료일자까지 쿠키가 삭제되지 않는다. (=영속쿠키)

Secure : HTTPS 프로토콜 상에서 암호화된(encrypted) 요청일 경우에만 전송

Set-Cookie: name=minidoo; Secure

HttpOnly : Cross-site 스크립팅 공격을 방지하기 위해, document.cookie에 접근할 수 없도록 설정

Set-Cookie: name=minidoo; HttpOnly

Domain : 쿠키가 전송될 호스트 명시. 도메인이 명시되면, 서브도메인들은 항상 포함됨 (쿠키의 스코프)

Set-Cookie: name=minidoo; Domain=minidoo.com

minidoo.com은 루트 도메인으로 dev.minidoo.com과 같은 서브도메인에서도 쿠키를 사용할 수 있게된다. 쿠키는 동일 도메인이 원칙이기 때문에 Domain 값을 잘 이용하는 것이 중요하다.

Path : 쿠키가 전송될 URL 경로를 지정

Set-Cookie: name=minidoo; Domain=minidoo.com; Path=/docs

만약 도메인이 mindioo.com이고 path가 ‘/docs’로 설정된 경우, 해당 도메인의 ‘/docs’ 이하의 모든 URL에서 쿠키를 사용할 수 있다. (예: minidoo.com/docs/web/http)

세션 (Session)

클라이언트는 서버에서 생성된 Session ID를 쿠키나 URL Parameter과 같은 방법으로 전달받고, 이후 요청에서 해당 Session ID를 서버에 전달함으로서, 클라이언트와 서버 간의 연결 정보를 유지할 수 있다.

비밀번호 등의 민감한 인증 정보는 쿠키에 저장하지 않고, 식별자인 Session ID를 생성해 서버에 저장(②)한다.

HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: sessionId=tk32fkdgo

클라이언트는 사용자의 sessionId 쿠키를 요청과 함께 전달한다. 서버는 클라이언트에게 쿠키 값을 받아서 내부의 세션 저장소에서 Session ID를 조회하여 사용자를 식별한다.

세션 쿠키의 이중적 의미

  1. 브라우저가 종료되면 삭제되는 쿠키(①)
  2. Session ID를 저장하고 있는 쿠키(②)

쿠키 공유

한 프로젝트가 WebApp과 API로 나뉘어져 있다. WebApp의 도메인은 example-webapp.com, API의 도메인은 example-api.com 이라면, example-api.com에서 발급받은 쿠키는 example-webapp.com 에서 사용할 수 없게 된다. 동일 도메인이 원칙이기 때문에 !

이를 해결할 수 있는 방법은 쿠키의 Domain 속성을 이용하는 것이다.

  • WebApp 도메인 : webapp.example.com
  • API 도메인 : api.example.com
Set-Cookie: name=hyemin; Domain=example.com

webapp.example.com과 api.example.com은 example.com의 서브도메인으로, Domain 속성은 쿠키를 사용하는 웹사이트 여러 서브도메인을 가질 경우, 서브도메인 간에 쿠키를 공유할 수 있도록 한다.

Reverse Proxy

또 다른 방법은 Reverse Proxy를 사용하는 것이다.

외부에서 내부 서버가 제공하는 서비스에 접근하는 경우, 프록시 서버를 통해 들어오는 방식이다. 접근하는 사용자는 실제로 어디에 접근하는지 관계가 없고, 운영자가 제공해준 방법에 따라서 Serving 할 수 있다.

# /etc/nginx/nginx.conf

location / {
	proxy_pass http://127.0.0.1:5000;
}

location /api {
	proxy_pass http://127.0.0.1:5001;
}
  • WebApp 도메인 : example.com
  • API 도메인 : exmaple.com/api

위의 설정에서 proxy_pass 는 URL이 api로 시작하는 주소로 접근하면 5001번 포트로 보내준다는 뜻이다. 즉, 하나의 도메인을 사용하지만(쿠키 공유 가능), location 설정 덕분에 2개의 포트로 연결될 수 있다.

그러나, Reverse Proxy는 URL이 충돌될 가능성이 있다. WebApp의 페이지 중 api로 시작하는 URL이 있다면 nginx에 설정해놓은 5001번 포트와 연결될 것이다. 또한 WebApp을 기준으로 location을 설정한다고 했을 때, 프로젝트 구조를 잘 파악해야 하는데, 예를들어 NestJS에서는 자동으로 ‘/_next’ 경로에서 로드되는 파일이 있다. 따라서 location에 이러한 프로젝트 특징을 파악하여 경로를 명시를 해야하는데 쉽지 않다 😢

참고 문서

[1] MDN HTTP 쿠키
https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies

[2] 쿠키(cookie), 세션(session)
https://bentist.tistory.com/86#recentEntries

post-custom-banner

0개의 댓글