본문 바로가기

기술들/Today I Learned

Cookie

 사이트 유저 인증 수단의 도구로 사용하는 cookie에 대한 개념을 정리하려고 한다. 쿠키에 대한 여러 자료를 봐도 명확히 "이거다!"라고 설명할 수 없어서, 글로 정리하면 명확하게 들어오지 않을까 싶어 정리하려고한다. 공식문서인 MDN의 문서를 참고해서 정리한다.

 

 

 

쿠키란?

 웹 기술에서 사용하는 쿠키는, 주로 HTTP Cookie를 일컫는 말이다. 쿠키란 서버가 유저의 브라우저에 전송하는 작은 데이터 조각을 의미한다. 이 작은 데이터 조각은 서버에서 브라우저로 전송되면 브라우저에 저장 된다. 그리고 브라우저는 쿠기를 제공한 서버로 매번 여러 요청들을 보낼때마다, 이 쿠키를 같이 전송한다.이 쿠키를 매 요청마다 서버로 같이 전송하는 이유는, 요청들이 같은 브라우저에서 왔는지 판별하기 위해서다.

 웹 사이트는 HTTP protocol의 특성을 가지고 있기 때문에 stateless(상태 유지가 안되는)한 특징을 가지고 있다. 이 특징은 물론 장점도 있지만, 유저의 입장에서는 나쁜 UX(사용자 경험)를 제공한다. 대표적인 예로, 로그인을 하고나서 다른 페이지(사이트내에서)로 이동할때마다 로그인 상태 유지가 안되는 것이다. 이런 Stateless한 특성을 보완하기 위해 사용하는 쿠키이지만, 유저 인증과 같은 로그인 분야에서는 보안 위협 때문에 직접 쓰이진 않고 간접적으로 쓰인다. 직접적으로 사용할 경우, 만약 쿠키에 유저 정보가 담겨있고, 누가 이 쿠키를 탈취한다면 유저 정보를 쉽게 알아낼 수 있기 때문이다. 그래서 주로, 탈취되도 별 문제가 없는 데이터들을 담을 때 사용한다. (ex: 장바구니, 오늘하루보지않기 상태유지 등등) 추가적으로 Session이나 Token과 같은 인증도구를 전송할 때 운송수단이 되기도 한다. 

 

쿠키는 과거 브라우저에 데이터를 저장하는 유일한 방식이었지만, 요즘은 WebStorage API인 localStorge. sessionStorage 기술을 주로 사용한다. (이러한 storage정보들은 브라우저 개발자 도구에서 Application 창에서 확인할 수 있다)

 

쿠키헤더

쿠키는 최초로 서버에서 HTTP 헤더에 Set-Cookie란 이름의 헤더에 담겨져 브라우져(클라이언트)로 보내진다. 개발자 도구 Network창에서 클라이언트로 보내진 Response Header를 확인해보면 다음과 같다. 

Set-Cookie: <cookie-name>=<cookie-value>

이런 형식으로 서버는 몇개의 쿠키를 설정해서 브라우져에 제공할 수 있다. 

 

HTTP/2.0 200 OK
Content-Type: text/html
Set-Cookie: favoite=soccer
Set-Cookie: hobby=riding

브라우저는 이 쿠키들을 저장하고, 서버로 요청을 보낼 때마다 쿠키를 Cookie 헤더에 담아 전송한다.

 

GET /sample_page.html HTTP/2.0
Host: www.example.org
Cookie: favoite=soccer; hobby=riding

 

 

쿠키옵션

쿠키에 다양한 옵션을 부여해서 사용할 수 있다. 

 

1. Expires 옵션 

쿠키의 만료시간을 구체적으로 정해줄 수 있는 옵션이다. 만약 정해주지 않는다면, 쿠키는 Session-cookie가 되어, 브라우저 창을 닫으면 같이 사라진다. 그렇지만 대부분의 웹사이트는 브라우저 복구 기능이 있어, 닫은 창을 다시 복원하는 기능을 가지고 있다. 그래서 이 때, Session-cookie도 같이 복원된다. 

 

설정 방법

// 현재부터 하루 뒤에 만료되게 설정, 1000을 곱한 이유는 ms단위를 second단위로 변환하기 위해서
res.cookie('Key', 'value', {expires: new Date(Date.now() + 86400*1000 )});

 

헤더에 다음과 같이 표시된다. 

Date: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT //형식

Date: Wed, 21 Oct 2015 07:28:00 GMT //예시

구체적인 표기법 참고

 

 

2. Max-Age 옵션 

초 단위로 쿠키의 만료시간을 정해줄 수 있는 옵션이다. 만약 0(초)이나 음수를 집어넣는다면 쿠키는 금방 만료될 것이다. 만약 Expires옵션과 Max-Age옵션을 둘 다 설정했다면, Max-Age가 우선 적용이 된다. 

 

설정 방법

// 아래 만료시간의 옵션설정은 하루 뒤로 설정되었다.
res.cookie('Key', 'value', {maxAge: 86400000}); // ms단위로 설정

 

 

3. Path 옵션

쿠키를 위한 경로를 지정해줄 수 있다. 기본값은 '/'(root)로 설정된다. 이 경로란, 클라이언트의 특정 path를 말한다. 만약 path가 '/'로 설정되면 클라이언트의 '/'에서만 쿠키를 받을 수 있다. 

res.cookie('Key', 'value', {path: '/'});

 

4. Domain 옵션 

클라이언트의 특정 도메인을 지정해줄 수 있다. 지정된 도메인에서만 쿠키를 공유할 수 있다. 만약 이 옵션이 생략된다면, 서브도메인을 포함하지 않고, 현재 URL의 호스트로 기본 설정된다. 

res.cookie('key', 'value', { domain: 'example.com' }

 

5. Secure 옵션 

이 옵션이 설정된다면 https 프로토콜에서만 쿠키 공유가 가능하다. 한 가지 주의할점은, https프로토콜을 사용한다고 해서 완벽하게  쿠키 안에 담긴 정보를 읽을 수 없는 것은 아니다. 만약 해커가 유저의 하드디스크에 접근하면 여전히 쿠키를 읽고 수정할 수 있고, 만약 httpOnly옵션이 설정되어 있지 않다면, 자바스크립트를 이용한 해커의 공격이 여전히 가능하다.   

 

6. SameSite 옵션 

Cross-origin 사이트로부터의 쿠키전송을 제어할 수 있다. 만약 Cross-origin 사이트로부터 쿠키전송을 불가하게 한다면, CSRF공격을 막을 수 있다. 

 

SameSite옵션에는 다음 세가지 값을 줄 수 있다.

 

sameSite = Lax   =>  만약 sameSite옵션이 설정되어 있지 않다면, 기본적으로 Lax가 설정된다(원래는 none이 기본값이었음). Lax를 주게되면, Cross-origin사이트로 부터 쿠키 공유를 할 수 없다. 하지만, Same-Origin사이트 내에 링크로 연결된 cross-origin사이트에서는 쿠키 공유가 가능하다. (쿠키 공유 제한 강도: 상)

 

sameSite = Strict  => Cross-origin 사이트와 일체 쿠키 공유를 할 수 없다. CSRF공격을 막을 수 있지만, 사용자 편의성을 제한한다.  (쿠키 공유 제한 강도: => 보안이 강할수록, 서비스 이용은 불편해진다. 

 

sameSite = none => 모든 사이트와 쿠키 공유를 할 수 있다. 만약 sameSite옵션을 none으로 줄 경우, Secure옵션은 반드시 true로 줘야한다. Secure옵션이 설정되면 https에서만 쿠키공유가 가능하다는 것을 명심하자. 결국 none으로 옵션 줄거면 https 사용해라 이 말이다. (쿠키 공유 제한 강도:)

res.cookie('key', 'value', { domain: 'example.com', secure: true, sameSite: 'none' }

 

7. httpOnly 옵션

이 옵션을 설정하면 document.cookie를 통한 자바스크립트 공격을 완화할 수 있다. 완벽히는 못 막는다. 쿠키를 사용할 때 개발자가 기본으로 설정해야 하는 옵션이다. 

 

참고자료:

developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie

developer.mozilla.org/en-US/docs/Web/HTTP/Cookies

expressjs.com/en/resources/middleware/cookie-session.html

'기술들 > Today I Learned' 카테고리의 다른 글

MVC 패턴  (0) 2020.12.20
Session  (0) 2020.12.16
Node.js architecture 정리  (0) 2020.12.01
CORS 정책 정리  (0) 2020.11.23
HTTP Header 정리 (HTTP/1.1 기준)  (0) 2020.11.22