| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
- maven
- 데이터분석
- buildtool
- DI
- 빌드툴
- 빅데이터분석
- umc회고
- 리눅스
- 백준dfs
- 백준
- 데이터베이스
- Linux
- DFS
- SpringFramework
- gradle
- Java
- 의존성주입
- 자바
- 스프링
- umc7기
- 알고리즘
- 코딩테스트
- 개발동아리회고
- 메이븐
- Spring
- 시스템프로그래밍
- -
- springboot
- IOC
- Today
- Total
repository
[쿠키 1부] 쿠키란 무엇이며, 어떤 특징을 가지고 있을까? 본문
대부분의 서버 프레임워크에서 쿠키를 직접 다루지 않아도 되도록 추상화가 잘 되어있긴하지만
쿠키는 웹에서 빼놓을 수 없는 핵심적인 기술이다.
프론트 개발을 하든 백엔드 개발을 하든 웹 개발자로서 쿠키를 제대로 이해해두면 두고두고 유용한 지식이 될 것이다!
쿠키란 무엇이고, 어떤 특징을 가지고 있을까?
클라이언트 (웹 브라우저)에 저장되는 작은 데이터 조각을 의미한다.
HTTP에서 클라이언트의 상태 정보를 쿠키 형태로 클라이언트 PC에 저장했다가
필요 시 정보를 참조하거나 재사용 할 수 있다.
key-value 쌍으로 구성되어있는 데이터 파일이며
쿠키 이름, 쿠키값, 만료시간, 전송할 도메인명, 전송할 경로, 보안 연결 여부, httpOnly 여부로 구성된다.
도메인 당 20개의 쿠키를 가질 수 있다.
하나의 쿠키는 4KB(=4096 byte)까지 저장이 가능하다.
HTTP 쿠키란?
브라우저 쿠키라고도 하고 웹 쿠키라고도 불리는 HTTP 쿠키 (cookie)는 이렇게 앞에 붙는 수식어로 유추할 수 있듯이
기본적으로 HTTP 통신을 기반으로 하며 브라우저에서 돌아가는 웹사이트나, 웹 애플리케이션에서 널리 사용되고 있다.
쿠키를 한마디로 정의하면 서버가 어떤 데이터를 브라우저 측에 저장하고 다시 그 데이터를 받아오는 기술, 또는 데이터 자체를 뜻한다.
따라서 밑에서 더 자세히 설명하지만 쿠키가 제대로 작동하기 위해서는 무엇보다 브라우저의 역할이 가장 중요하다.
브라우저가 원격에 있는 서버와 네트워크를 통해 쿠키를 주고 받으려면 이 둘 사이에는 일정한 약속이 필요하다.
이 약속은 바로 HTTP 프로토콜 상에서 구현되며, 쿠키는 HTTP 메세지의 헤더(header) 영역을 통해서 송수신 되도록 약속되어있다.
하지만 HTTP 헤더는 기본적으로 브라우저 화면에 나타나지 않기 떄문에 일반 사용자들은 확인하기 어렵다.
그래서 많은 사람들이 쿠키를 떠올리면 뭔가 실체가 없고 어디선가 몰래 왔다갔다하는..그런 막연한 인식이 생겼을것이다.
쿠키의 매커니즘
쿠키를 기술적으로 제대로 이해하려면 브라우저와 서버가 어떤 과정을 거쳐 쿠키를 주고 받으며 HTTP 통신을 하는지 알아야 한다.
먼저 쿠키라는 데이터는 어떤 모양일까? 쿠키는 <이름>=<값> 형태를 지니는 단순한 문자열이다.
서버와 브라우저는 기본적으로 HTTP 메세지 안에 이 쿠키를 담아서 주고 받게 된다.
서버가 어떤 쿠키를 브라우저에 저장하고 싶다면 당연히 해당 쿠키를 브라우저에 보내줘야 한다.
클라이언트 서버 모델에서는 서버가 클라이언트의 요청없이 클라이언트로 데이터를 보낼 수 없다.
따라서 이러한 쿠키 전달 과정은 서버가 클라이언트 요청에 응답할 때 일어나게 된다.
서버는 Set-Cookie라는 응답 헤더에 브라우저가 수신해야 할 쿠키 정보를 명시하도록 되어 있다.
하나의 Set-Cookie 응답 헤더에는 하나의 쿠키만 담을 수 있어서 여러 개의 쿠키를 보낼 때는 다음과 같은 모습이 된다.
//HTTP응답
Set-Cookie:<이름>=<값>
Set-Cookie:<이름>=<값>
Set-Cookie:<이름>=<값>
이렇게 서버로부터 쿠키를 응답 받은
브라우저는 해당 쿠키를 컴퓨터의 하드 디스크에 저장한다.
그리고 브라우저가 동일한 서버에 요청을 할 때 저장해놓은 쿠키를 Cookie라는 요청 헤더에 실어서
돌려 보낸다.
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 요청
GET /about.html HTTP/1.1
Host: www.test.com
Cookie: a=1; b=2
HTTP 요청
GET /contact.html HTTP/1.1
Host: www.test.com
Cookie a=1;b=2
이제 서버는 이 브라우저로부터 들어오는 요청에서 a=1,b=2라는 쿠키를 읽어서 원하는 용도로 활용할 수가 있다.
즉, 쿠키라는 매커니즘을 통해서 서버는 데이터를 브라우저에 저장해놨다가 나중에 브라우저에서 요청이 들어올 때 그 테이터를 함께 받아올 수 있는 것이다.
쿠키의 유효 기간
위에서 브라우저는 일정 시간동안 계속해서 서버로 쿠키를 돌려 보낸다고 설명했다.
브라우저가 쿠키를 얼마나 오랫동안 돌려 보내야 하는지는 서버가 맨 처음 쿠키를 보낼 때 결정을 하며,
Set-Cookie 응답 헤더를 통해 명시되어야 한다.
유효 기간이 별도로 명시되지 않은 쿠키를 보통 세션 쿠키(session cookie)라고 부르는데 브라우저의 세션이 종료 될 때 함께 만료된다.
즉, 브라우저의 탭이나 윈도우를 닫으면 서버가 보냈던 쿠키는 모두 만료되어 브라우저는 더 이상 해당 쿠키를 서버에 돌려 보내지 않는다.
반면에 유효 기간이 명시되어있는 쿠키인 영속 쿠키(permanent cookie)는 세션과 무방하게
특정 기간이나 특정 시점까지 유효하다.
쿠키의 유효 기간을 명시할 때는 Set-Cookie 응답 헤더에 Expires 속성이나 Max-Age 속성을 다음과 같은 형태로 사용한다.
Set-Cookie:<쿠키 이름>=<쿠키 값>; Expires=종료 시점
Set-Cookie:<쿠키 이름>=<쿠키 값>; Expires=유효 기간
Max-Age 속성은 초 단위로 설정하며, Expires속성과 Max-Age 속성이 둘 다있을 경우 Max-Age 속성이 우선된다.
두 가지 속성이 모두 없을 때 해당 쿠키는 세션이 종료될 때 만료되는 세션 쿠키가 된다.
참고로 브라우저에 저장해두었던 쿠키를 즉시 만료하고 싶을 때는 Max-Age 속성을 0으로 설정해두면 된다.
Set-Cookie: a=1; Max-Age=0
쿠키의 적용 범위
브라우저가 기본적으로 쿠키를 보낸 서버가 속한 도메인으로만 쿠키를 되돌려 보내지만,
어떤 URL을 방문할 때 해당 쿠키를 보내야 할 지 말지를 조금 더 세밀하게 제어할 수 있다.
Set-Cookie 응답 헤더에 Domain 속성을 명시하면, 서브 도메인까지 포함되도록 쿠키의 범위가 확장된다.
Set-Cookie: <쿠키이름>=<쿠키 값>; Domain=도메인
예를 들어, Domain 속성을 test.com으로 설정하면 브라우저는 a.test.com으로부터 받은 쿠키를
b.test.com으로도 보내게 된다.
그러므로 a.test.com과 b.test.com이 쿠키를 공유하는 효과가 발생하게 된다.
Set-Cookie 응답 헤더에 Path 속성을 명시하면 쿠키의 범위를 해당 도메인의 특정 경로로 쿠키의 범위를 축소 시킬 수도 있다.
Set-Cookie: <쿠키 이름>=<쿠키 값>; Path=경로
예를 들어, Path 속성이 /users 라고 설정되어있는 쿠키는, 브라우저가 /users를 포함한 하위 경로로 요청을 할 때만 서버로 돌려 보낸다.
쿠키가 왜 필요하게 되었을까?
이렇게 쭉 살펴보니 쿠키가 기술적으로 상당히 복잡하다는 것을 알 수 있다.
여기서 많은 사람들은 뭐하러 서버는 수고를 들여 데이터를 굳이 브라우저에 저장하려고 하는지 의아해할수도 있을것이다.
그냥 데이터를 싸그리 서버에 저장해두면 훨씬 편할 것 같은데 말이다.
요즘처럼 서버 장비의 가격이 저렴하고 심지어 클라우드 인프라까지 이용할 수 있는 환경에서는 이해가 어렵겠지만, 서버 측에서 많은 데이터를 저장하는것이 부담스러울정도로 하드웨어의 가격이 비싸던 시절로 돌아가보는것을 생각해보자.
예를 들어, 사용자 한 명당 저장해야 할 데이터가 1KB라고 가정하면, 사용자 100만명에게 서비스하려면 서버에 1GB의 저장 공간이 필요했을 것이다.
지금이야 일반 노트북에도 수백 GB의 하드디스크가 장착되어 있지만, 인터넷이 태동한 90년대에 이러한 데이터를 서버가 오로지 감당하기에는 벅찼을 것이다.
하지만 데이터 저장에 대한 부담을 클라이언트에 전가할 수 있다면 어땠을까!
당시에도 브라우저를 설치할 수 있을 정도의 PC라면 1KB정도는 충분히 감당할 저장공간이 있었을 것이다.
따라서 예전에는 이러한 제약사항 때문에 클라이언트 측에 데이터를 저장할 요구가 컸었고,
자연스럽게 브라우저에 데이터를 저장하기 위한 쿠키라는 것이 고안되었던것이다.
쿠키의 한계
쿠키가 브라우저, 즉 클라이언트 측에 저장된다는 것은 상당히 널리 알려진 사실이다.
이 부분은 쿠키가 탄생하게 된 중요한 배경이며, 안타깝게도 갖가지 이슈의 원흉이기도 하다.
따라서 쿠키를 사용할 때는 아래와 같은 쿠키의 한계점들을 잘 인지하고 사용하는 것이 중요하다.
1. 쿠키는 유실되기 쉽다.
대부분의 브라우저는 환경 설정에서 쿠키 일괄 삭제 기능을 제공하며, 웹사이트 별로도 어렵지 않게 쿠키를 삭제할 수 있다.
또한 특정 브라우저가 하드디스크의 어느 경로에 쿠키를 저장하는지는 구글링을 해보면 누구나 쉽게 파악 할 수 있어서 통채로 폴더를 삭제해버릴수도 있다. 그러므로 유실되면 안 되는 중요한 데이터는 쿠키를 사용하여 브라우저에 저장하면 안된다.
2. 쿠키는 변조되기 쉽다.
브라우저의 개발자 도구를 사용하면 각 웹사이트 별로 현재 어떤 쿠키가 저장되어 있는지 한눈에 파악할 수 있으며 쿠키를 손쉽게 변경할 수 있다.
이를 통해 서버가 브라우저로 보낸 쿠키와 전혀 다른 쿠키를 서버에 돌려 보낼 수 있으며, 심지어 서버가 저장한 적잉 ㅓㅄ는 새로운 쿠키를 만들어서 서버에 보낼 수도 있다.
뿐만 아니라 프록시 서버를 이용해 브라우저에서 보낸 쿠키를 중간에 변조해서 서버에 보내는 것도 충분히 가능한 일이다.
따라서 서버에서는 브라우저로부터 수신한 쿠키 데이터가 유효한지 검증할 필요가 있다.
3. 쿠키는 도난되기 쉽다.
클라이언트의 컴퓨터에 저장되는 쿠키는 온갖 해킹의 위험에 노출되어있다.
아무리 클라이언트 단에서 개개인이 보안에 신경을 쓴다고 해도 기업이 소유하고있는 서버 단의 보안 수준에 비할 바가 못된다. 클라이언트에 저장되어있는 쿠키가 탈취되는 것을 서버입장에서 막을 도리는 없을 것이다.
따라서 개인 정보와 같이 민감한 데이터를 쿠키를 사용해서 저장하면 곤란한 일이 벌어질 수도 있다.
이러한 쿠키의 한계를 깨닫게 되면 사실 쿠키로 저장할 만한 데이터가 딱히 없다고 느껴질 것이다.
요즘과 같이 데이터가 중요한 시대에 유실되거나 조작되거나 도난되어도 무방한 데이터가 얼마나 될까
쿠키의 대체 기술
서버 자원이 풍부한 현재에는 순수하게 데이터를 클라이언트 측에 저장하기 위한 용도로써의 쿠키 입지는
많이 좁아진 것이 사실이다.
대부분의 모던 브라우저는 로컬 스토리지나 세션 스토리지와 같은 쿠키를 대체할 수 있는 웹 스토리지 기술을 지원하고있다.
게다가 웹 개발 패러다임이 백엔드에서 프론트엔드로 옮겨오면서 예전보다 많은 코드가 서버가 아닌 브라우저에서 실행되고 있다. 그래서 굳이 브라우저에 저장되어 있는 데이터를 서버로 전송하지 않고도 자바스크립트로 해당 데이터에 쉽게 접근할 수 있게 되었다.
이러한 웹 스토리지 기술 대비 쿠키의 최대 단점은 매 요청마다 같은 데이터가 서버로 전송됨에 따른 네트워크 대역폭 낭비이다.
따라서 굳이 서버 단에서 읽을 필요가 없이 순수하게 브라우저에 저장해도 무방한 데이터라면 굳이 쿠키를 통해 네트웤르르 통해 주고받을 필요가 없다.
쿠키의 보안 속성
이러한 쿠키의 한계와 대체 기술에도 불구하고 반드시 쿠키를 사용해야 하는 상황이라면 가급적 보안 속성을 사용하는것이 권장된다.
첫번째 보안 속성은 Secure이다.
Set-Cookie 응답 헤더에 이 속성이 명시된 쿠키는 브라우저가 https 프로토콜 상에서만 서버로 돌려보낸다.
네트워크 상에서 탈취되었을 때 문제가 될 수 있는 쿠키를 상대로 쓰면 유용할 것이다.
HTTP 응답
Set-Cookie:<쿠키 이름>=<쿠키값>; Secure
두번째 보안 속성은 HttpOnly이다.
Set-Cookie 응답 헤더에 이 속성이 명시된 쿠키는 브라우저에서 JS로 Document.cookie 객체를 통해 접근할 수 없다.
써드 파티 (third party) JS code가 쿠키에 접근하는 것을 제한할 수 있다.
HTTP 응답
Set-Cookie:<쿠키 이름>=<쿠키 값>; HttpOnly
'FrontEnd' 카테고리의 다른 글
| [Frontend] OAuth 2.0을 구현하기 위해 알아야 할 것들 (1) | 2024.08.25 |
|---|---|
| [쿠키 2부]: 세션과 쿠키 (0) | 2024.08.06 |
| [Frontend] 프론트엔드와 백엔드가 소통하는 엔드 포인트, RESTful API (2) | 2024.07.27 |