쿠키는 클라이언트에 저장되고… 음.. 보안에 좋지 않습니다.
-
그럼 보안을 위해서 쿠키는 안 쓰는 게 좋겠네요?
쿠키가 어떻게 서버와 브라우저 간에 이동을 하는지, 그리고 쿠키의 유효 기간과 적용 범위를 설정하는 방법과 쿠키의 한계와 대체 기술에 대해서 알아보겠습니다.
HTTP 쿠키(=브라우저 쿠키, 웹 쿠키)란?
HTTP 쿠키(cookie)는 서버가 어떤 데이터를 브라우저 측에 저장한 후 다시 그 데이터를 받아오는 기술, 또는 그 데이터 자체를 뜻합니다. 보통 데이터는 서버와 통신하기 때문에 브라우저에서 데이터를 다룬다는 것에 생소하실 수 있지만, 서비스에 따라 데이터를 매번 서버에서 받아오는 것이 비효율적일 때가 있습니다. 바로 이때, HTTP 쿠키를 사용하게 됩니다.
🔥여기서 잠깐
통신하기 위해서는 서로 약속된 규칙이 있어야 하기 마련입니다.
브라우저가 원격에 있는 서버와 네트워크를 통해 쿠키를 주고받기 위한 약속은 바로 HTTP 프로토콜 상에서 구현되며 쿠키는 HTTP 메시지의 헤더(header) 영역을 통해서 송수신되도록 되어 있습니다.
크롬 브라우저의 [개발자도구(F12)] 를 들어가보면 Network탭에 Blocked response cookie 라는 박스가 보이시나요? 앞으로 유용하게 사용한 DevTools이니 익숙해지는 것을 권장드려요 :)
쿠키의 메커니즘
쿠키를 기술적으로 제대로 이해하려면 브라우저와 서버가 어떤 과정을 거쳐 쿠키를 주고받으며 HTTP 통신을 하는지 알아야 합니다.
먼저 쿠키라는 데이터는 어떤 모양일까요? 쿠키는 <이름>=<값> 형태를 지니는 단순한 문자열입니다. 서버와 브라우저는 기본적으로 HTTP 메시지 안에 이 쿠키를 담아서 주고받게 됩니다.
서버가 어떤 쿠키를 브라우저에 저장을 하고 싶은데 문제는 서버가 클라이언트의 요청 없이 클라이언트로 데이터를 보낼 수 없습니다. 따라서 이러한 쿠키 전달 과정은 서버가 클라이언트 요청에 응답할 때 일어나게 됩니다.
(마치.. 클라이언트를 향한.. 일반적인 짝사랑이라고 할까요..?ㅎ)
서버는 Set-Cookie라는 응답 헤더에 브라우저가 수신해야 할 쿠키 정보를 명시하도록 되어 있습니다. 하나의 Set-Cookie 응답 헤더에는 하나의 쿠키만 담을 수 있어서 여러 개의 쿠키를 보낼 때는 아래와 같은 모습이 됩니다.
방법 1.
Set-Cookie: <이름>=<값>
Set-Cookie: <이름>=<값>
Set-Cookie: <이름>=<값>
방법 2.
Cookie: <이름>=<값>; <이름>=<값>; <이름>=<값>
이렇게 서버로부터 쿠키를 응답받은 브라우저는 우선 해당 쿠키를 클라이언트 컴퓨터의 하드디스크에 저장합니다. 그리고 브라우저가 동일한 서버에 요청을 할 때 저장해 놓은 쿠키를 Cookie라는 요청 헤더에 실어서 돌려보냅니다.
여기서 중요한 점은 서버가 Set-Cookie 헤더를 통해 브라우저로 쿠키를 보내는 것은 일회성 작업이지만, 반대로 브라우저가 Cookie 헤더를 통해 서버로 쿠키를 돌려보내는 것은 일정 시간 동안 반복해서 수행되는 작업이라는 것입니다.
쉽게 말해서 서버 입장에서 보면 사실 쿠키는 완전히 개꿀인 기술입니다... 브라우저에게 쿠키 하나만 툭 던져놓으면 🍪 매번 시키지 않아도 브라우저가 스스로 계속해서 쿠키를 들고 오니까요 🚚
Set-Cookie 응답 헤더로 넘어온 쿠키를 다시 Cookie 요청 헤더로 돌려보내는 것이 가능한 이유
브라우저라는 HTTP 클라이언트만 해주는 매우 독특한 작업입니다.
만약 curl 커맨드처럼 다른 HTTP 클라이언트 도구를 사용하면 Set-Cookie 응답 헤더는 Content-Type과 Date와 같은 다른 평범한 응답 헤더처럼 그 이상의 특별한 의미를 갖지 않게 된다.
결론적으로 모든 브라우저가 쿠키를 지원하기 위해서 이러한 일종의 계약을 준수하고 있기 때문에 서버가 브라우저에 쿠키를 저장해 놓고 계속해서 받아올 수 있는 것입니다.
쿠키의 송수신 예제
서버에서 a=1, b=2라는 2개의 쿠키를 브라우저에 저장하고자 한다. www.test.com 서버는 브라우저의 요청이 들어오면 각 쿠키를 Set-Cookie 헤더에 실어서 응답하는 예제를 보고 작성해봅시다.
HTTP 요청
GET /index.html
HTTP/1.1 Host: www.test.com
HTTP 응답
HTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: a=1
Set-Cookie: b=2
브라우저는 서버로부터 받은 이 2개의 쿠키를 동일한 서버로 요청을 할 때 Cookie 헤더에 이전에 서버로부터 받았던 쿠키를 그대로 돌려보내게 됩니다.
HTTP 요청 2
GET /index.html
HTTP/1.1 Host: www.test.com
Cookie: a=1; b=2
브라우저는 사용자가 test.com 도메인에 있는 동안 /index.html /about.html /contact.html 등 매번 같은 쿠키를 돌려주게 됩니다. 서버는 쿠키라는 메커니즘을 통해 필요한 데이터를 브라우저에 저장해 놨다가 브라우저 요청 시 함께 데이터를 받아오도록 할 수 있게 되는데 이렇게 하면 뭐가 좋을까요?
서버에서 필수 parameter로 필요로 하는 데이터들이 종종 아니 자주 있습니다. 그러나, 필수 데이터를 모두 서버에서 찾아 서비스를 처리하는 것이 비효율적일 때 다음과 같이 쿠키를 활용하곤 합니다. (실무에서도 자주 쓰이는 방법입니다ㅎㅎ)
쿠키의 유효 기간
브라우저는 일정 시간 동안 계속해서 서버로 쿠키를 돌려보내는데 유효기간은 있을까요? ⭕️ 네, 당연하죠!
브라우저가 쿠키를 얼마나 오랫동안 돌려보내야 하는지는 서버가 맨 처음 쿠키를 보낼 때 결정을 하며, Set-Cookie 응답 헤더를 통해 명시돼야 합니다.
유효 기간 미설정시,
유효 기간이 별도로 명시되지 않은 쿠키를 보통 세션 쿠키(session cookie)라고 부르는데 브라우저의 세션이 종료될 때 함께 만료됩니다.
즉, 브라우저의 탭이나 윈도를 닫으면 서버가 보냈던 쿠키는 모두 만료되어 브라우저는 더 이상 해당 쿠키를 서버에 돌려보내지 않습니다.
유효 기간 설정시,
유효 기간이 명시되어 있는 쿠키를 영속 쿠키(permanent cookie)라 하며, 세션과 무방하게 특정 기간이나 특정 시점까지 유효합니다. 쿠키의 유효 기간을 명시할 때는 Set-Cookie 응답 헤더에 Expires 속성이나 Max-Age 속성을 다음과 같은 형태로 사용합니다.
HTTP응답
Set-Cookie: <쿠키 이름>=<쿠키 값>; Expires=종료 시점
Set-Cookie: <쿠키 이름>=<쿠키 값>; Max-Age=유효 기간
Max-Age 속성은 초 단위로 설정하며, Expires 속성과 Max-Age 속성이 둘 다 있을 경우 Max-Age 속성이 우선합니다. 둘 가지 속성이 모두 없을 때 해당 쿠키는 세션이 종료될 때 만료되는 세션 쿠키가 됩니다.
📌 브라우저에 저장해 두었던 쿠키를 즉시 만료하고 싶을 때는 다음과 같이 Max-Age 속성을 0으로 설정
쿠키의 적용 범위
도메인을 통해 쿠키의 적용 범위를 넓히거나 좁힐 수 있습니다. 좀 더 세밀하게 제어해볼까요?
1. 쿠키의 범위 확장하기
Set-Cookie 응답 헤더에 Domain 속성을 명시하면, 서브 도메인까지 포함되도록 쿠키의 범위가 확장됩니다.
HTTP응답
Set-Cookie: <쿠키 이름>=<쿠키 값>; Domain=도메인
예를 들어, Domain 속성을 test.com으로 설정하면 브라우저는 a.test.com으로 부터 받은 쿠키를, b.test.com으로도 보내게 됩니다. 그러므로 a.test.com과 b.test.com이 쿠키를 공유하는 효과가 발생하게 됩니다. 데이터를 공유할 때, 설계에 의한 공유라면 괜찮지만 잘못된 이해로 공유/누수되는 데이터는 치명적인 실수가 될 수 있습니다😇
2. 쿠키의 범위 축소하기
Set-Cookie 응답 헤더에 Path 속성을 명시하여 쿠키의 범위를 해당 도메인의 특정 경로로 쿠키의 범위를 축소시키는 법
HTTP응답
Set-Cookie: <쿠키 이름>=<쿠키 값>; Path=경로
예를 들어, Path 속성이 /users라고 설정되어 있는 쿠키는, 브라우저가 /users를 포함한 하위 경로로 요청을 할 때만 서버로 돌려 보냅니다.
쿠키의 한계
쿠키는 클라이언트 측에 저장되는 장단점이 있기 때문에 사용할 때는 아래와 같은 쿠키의 한계점들을 잘 인지하고 사용하는 것이 중요합니다.
첫째, 쿠키는 유실되기 쉽습니다.
대부분 브라우저는 환경 설정에서 쿠키 일괄 삭제 기능을 제공하며, 웹사이트 별로도 어렵지 않게 쿠키를 삭제할 수 있습니다. 또한 특정 브라우저가 하드디스크의 어느 경로에 쿠키를 저장하는지는 구글링을 해보면 누구나 쉽게 파악할 수 있어서 통째로 폴더를 삭제해버릴 수도 있습니다. 그러므로 유실되면 안 되는 중요한 데이터는 쿠키를 사용해서 브라우저에 저장하면 안 되겠습니다.
둘째, 쿠키는 변조되기 쉽습니다.
브라우저의 개발자 도구를 사용하면 각 웹사이트 별로 현재 어떤 쿠키가 저장되어 있는지 한 눈에 파악할 수 있으며 쿠키를 손쉽게 변경할 수 있습니다. 이를 통해 서버가 브라우저로 보낸 쿠키와 전혀 다른 쿠키를 서버에 돌려 보낼 수도 있으며, 심지어 서버가 저장한 적이 없는 새로운 쿠키를 만들어서 서버에 보낼 수도 있습니다. 뿐만 아니라 프록시 서버를 이용해서 브라우저에서 보낸 쿠키를 중간에서 변조해서 서버에 보내는 것도 충분히 가능한 일 입니다. 따라서 서버에서는 브라우저로 부터 수신한 쿠키 데이터가 유효한지 검증할 필요가 있습니다.
둘째, 쿠키는 도난되기 쉽습니다.
클라이언트의 컴퓨터에 저장되는 쿠키는 항상 온갖 해킹의 위험에 노출되어 있습니다. 아무리 클라이언트 단에서 개개인이 보안에 신경을 쓴다고 해도 기업이 소유하고 있는 서버 단의 보안 수준에 비할 바가 못되겠죠. 클라이언트에 저장되어 있는 쿠키가 탈취되는 것을 서버 입장에서 막을 도리는 없을 것입니다. 따라서 개인 정보와 같이 민감한 데이터를 쿠키를 사용해서 저장하면 곤란한 일이 벌어질 수도 있습니다.
이러한 쿠키의 한계를 깨닫게 되면 사실 쿠키로 저장할 만한 데이터가 딱히 없다고 느껴질 것입니다. 요즘 같이 데이터가 중요한 시대에 유실되거나 조작되거나 도난되어도 무방한 데이터가 얼마나 될까요? 적재적소에 어떤 데이터를 활용할 수 있을지 한번 고민해보는 시간이 되었으면 좋겠습니다 :)
마치며
쿠키는 로컬 스토리지나 세션 스토리지와 같은 웹 스토리지 기술로 대체되곤 합니다. 그러나, 쿠키는 어딘가에서 오늘도 쓰이고 있습니다. 웹 개발의 패러다임이 점차 커지며 예전보다 많은 코드가 서버가 아닌 브라우저에서 실행되며, 기술이 끊임없이 변화하고 있는 와중에도 쿠키가 살아남은 이유가 있다고 생각합니다. 어떤 이유인지 생각해보며, 다음 포스팅에서 연결지어보겠습니다.
끝.
'Study > cs (computer science)' 카테고리의 다른 글
쿠키 2부 : 세션은 쿠키가 필요하다 (1) | 2023.11.30 |
---|---|
equals() 와 hashCode() 동일성과 동등성, 완전범죄하기 (48) | 2023.10.31 |
REST API/RESTful API Design Guide/REST 디자인 패턴/Http Methods 는 무엇인가 #2 (0) | 2023.01.04 |
REST API/RESTful API란/Representational State Transfet API/REST 디자인패턴 쓰는 이유 #1 (0) | 2023.01.03 |
빌드(Build)/Jankins 젠킨스/CI도구 써야하는 이유 (0) | 2023.01.03 |