웹서핑을 하다보면 자주 쿠키
라는 단어를 많이 봤었는데 그게 무엇인지 이번 챕터를 공부하면서 이해 할 수 있었다.
웹 서버는 엄청나게 많은 클라이언트들과 동시에 통신한다.
서버는 많은 클라이언트와 stateless
형태로 통신하지만, 그럼에도 불구하고 클라이언트가 누구인지까지 기억 못할 필욘느 없다.
서버는 클라이언트의 정보를 기억하는 것이 중요하다.
서버가 클라이언트의 정보를 기억한다면
클라이언트 별 맞춤 홈페이지를 제공한다거나 내가 이미 입력한 개인 정보들 (예를 들어 구매를 위한) 을 기억하여 일일히 입력 할 필요가 없게 할 수 있다.
그러니 웹 서버의 클라이언트 식별은 개별 맞춤 형 서비스를 클라이언트에게 제공 할 수 있다.
HTTP
헤더헤더 이름 | 헤더 타입 | 설명 |
---|---|---|
User-Agent | 요청 | 사용자의 브라우저와 운영체제에 대한 정보를 포함합니다. |
Referer | 요청 | 현재 페이지로 이동하기 전에 방문한 페이지의 주소를 나타냅니다. |
Authorization | 요청 | 인증 토큰이나 자격 증명 정보를 포함하여 서버에 전달됩니다. |
Client-IP | 요청 | 클라이언트의 IP 주소를 나타냅니다. |
X-Forwarded-For | 요청 | 웹 서버를 통해 전달되는 요청에서 실제 클라이언트의 IP 주소를 나타냅니다. (프록시를 통한 요청에서 사용) |
Cookie | 요청 | 클라이언트 측에서 서버로부터 전송된 쿠키 정보를 포함합니다. |
웹 서버는 요청 헤더를 통해 클라이언트를 식별 할 수 있다.
이전에는
From
헤더에 클라이언트의 이메일 주소를 적기도 했는데 해당 부분은 잘못 유출 되었을 경우 스팸 이메일 등의 위험이 있어 이제 사용하지 않는다.
Client-IP
모든 IP
가 사용자마다 독립적이라면 Client-IP
헤더만으로도 클라이언트를 식별 할 수 있을 것이다.
사실 엄밀히 말하면 클라이언트가 아니라, 해당 컴퓨터가 어떤 컴퓨터인지를 식별 할 수 있을 것이다.
한 컴퓨터를 4가족이 함께 사용한다고 생각하면, 4가족은 서로 다른 클라이언트이지만, 하나의 동일한 IP
를 가지고 있다.
또 많은 인터넷 서비스 제공자 (ISP
) 는 로그인 하면 동적으로 IP
주소를 할당한다거나
VPN
과 같은 IP
우회 서비스를 이용한다면 클라이언트를 식별하는데 있어 IP
주소만으론느 완벽하게 식별 할 수 없다.
클라이언트의 IP
주소만으로 식별하려고 하는 수동적 방식보다 , 사용자의 이름과 비밀번호를 이용해 클라이언트가 본인을 식별 시키도록 능동적으로 유도 하는 방식도 존재한다.
서버가 클라이언트가 어떤 서비스를 이용하기 전 로그인시키고자 한다면 HTTP 401 Login Required
응답 코드와 함께 로그인 창을 보낸다.
이 때 입력된 데이터를 Authorization
헤더에 정보를 기술하여 보낸다.
하지만 로그인을 한다는 것은 너무나도 귀찮은 일이며
어떤 행동을 하나 하나 할 때 마다 로그인을 하는 것은 UX
입장에서 아주 개떡같은 입장이다.
뚱뚱한 URL 은 클라이언트의 상태 정보를 담고 있는 개별적인 URL 주소를 생성하고 클라이언트의 모든 액션이 해당 URL
주소 형식에서 이뤄지게 하는 것이다.
서버는 클라이언트를 식별하고 추적하기 위해 클라이언트 별 식별자가 포함된 맞춤형 URL
주소를 생성한다.
클라이언트가 처음으로 웹 서버에 방문할 경우 해당 클라이언트의 식별자가 자동으로 생성되고 앞으로 해당 식별자가 붙은 URL 주소로 클라이언트를 리다이렉트 시킨다.
하지만 이는 몇 가지 단점을 갖는다.
www.naver.com
이 아니라 www.naver.com/001-23-4-214-024-124
이렇게 생겼다고 생각해보자 윽URL
에는 나의 개인 상태 정보가 담겨있기 때문에 다른 이에게 URL
을 공유 하는 것이 쉽지 않다.URL
주소에 맞춰 캐시된 정보를 제공하는데 클라이언트 별 개별적인 URL
주소를 갖는다면 캐시를 사용 할 수 없다.www.clothmarket.com/wishlist/123123123
이란 장바구니 차엥서 장바구니에 차곡 차곡 담았다가 새로고침이 되었다고 생각해보자. 내가 여태 한 담은 행동을이 서버 단에 요청으로 날라가지 않았기 때문에, 날라가지 않은 정보들은 모두 사라진다. 그럼 어떻게 해야 웹 페이지와 서버는 클라이언트를 식별하기도 하고 , 클라이언트의 상태 정보를 저장 할 수 있을까 ?
그것은 바로 ~ 쿠키 ~~
우선 쿠키는 세션 쿠키
와 지속 쿠키
두 가지 타입으로 나눌 수 있다.
세션 쿠키는 사용자가 브라우저를 탐색 할 때 설정과 선호 사항 등을 저장하는 임시 쿠키 이다. 이는 브라우저 메모리에 저장되기 때문에 브라우저가 새로 작동하면 정보가 모두 날라간다.
지속 쿠키는 브라우저 메모리 단이 아닌 디스크 단에서 정보를 저장한다. 그렇기 때문에 세션 쿠키와 다르게 브라우저를 재시작해도 문제없이 정보를 저장해둘 수 있다.
이는 쿠키가 설정 될 때 서버가 제공한
Expire
와 같은 유효 기간을 기준으로 저장된다
클라이언트가 사이트에 처음 접속하는 순간, 해당 사이트는 클라이언트를 식별 할 수 있는 식별자를 Cookie
헤더에 붙여 클라이언트에게 응답을 보낸다. 이 때 서버는 클라이언트에게 보낸 쿠키에 대해 Expire
와 같이 쿠키의 유효 기간을 보낸다.
Cookie
헤더에는 단순한 식별자 뿐이 아닌 여러 정보가 담겨 있을 수 있다.
서버는 클라이언트에게 보낸 쿠키를 쿠키 데이터베이스에 저장하고 , 브라우저는 클라이언트의 쿠키를 지속 쿠키로 저장한다. 이를 쿠키 스토리지라고 한다.
귀여워
이후 클라이언트와 서버가 소통 할 때에는 쿠키에 대한 정보가 헤더에 담긴 채로 오고 가게 된다.
이를 통해 웹 서버는 클라이언트를 식별 할 수 있다.
만약 클라이언트가 브라우저를 닫고 다음 날 다시 동일한 사이트에 접속했을 때 , 서버는 클라이언트의 쿠키 정보를 기억하고 있고 웹 브라우저에도 쿠키 스토리지 에 쿠키 정보가 존재하기 때문에 해당 쿠키를 이용해 다시 웹 서버와 소통한다.
쿠키가 처음 웹 서버로부터 클라이언트에게 전달 될 때 웹 서버는 쿠키의 속성을 설정 한 채로 보낼 수 있다.
Domain
Domain
은 해당 쿠키를 보낼 사이트들을 의미한다 .
클라이언트는 다양한 사이트를 돌며 다양한 쿠키들을 받을텐데 , 모든 사이트의 쿠키들을 내가 접속한 사이트에게 보낼 필요가 없다.
그렇기 때문에 웹 서버는 쿠키를 클라이언트에게 보낼 때,받은 쿠키를 보낼 사이트들의 위치를 Domain
속성에 같이 적어 보낸다.
쿠키는
set-cookie : name = 'lee'; domain='example.com'
이런식으로 설정된다.
Path
Path
는 Domain
의 상세 경로를 지정 할 수 있다.
만약 www.example.com/wishlist
라는 페이지에서 발생한 쿠키들을 www.example.com
에 모두 보낼 것이 아니라 /wishlist
라는 경로에만 보내길 원한다면
Set-cookie : Domain = "example.com"; Path = "/wishlist"
이런식으로 보낸다.
Path
에 설정된 경로 뿐이 아니라 해당Path
의 하위 경로에도 보내진다.
헤더 값 | 설명 |
---|---|
Set-Cookie: user_id=12345 | 단순한 쿠키 설정. 값은 "12345". |
Set-Cookie: session_id=abcde; Expires=Wed, 21 Feb 2024 10:00:00 GMT | 유효 기간이 설정된 쿠키. "abcde" 값이며, 만료일은 특정 날짜로 설정됨. |
Set-Cookie: lang=ko; Path=/; Domain=.example.com | 도메인 및 경로 제한이 있는 쿠키. "ko" 값이며, 도메인은 ".example.com", 경로는 "/"로 제한됨. |
Set-Cookie: auth_token=xyz; Secure; HttpOnly | 보안 속성이 추가된 쿠키. "xyz" 값이며, HTTPS에서만 전송되고, JavaScript를 통한 접근이 불가능함. |
다음과 같은 예시들로 쿠키의 다양한 헤더를 알 수 있다.
쿠키를 설정 할 때 클라이언트는 식별 할 수 있는
이름 = 값
형태의 속성이 하나 이상 존재해야 한다.
위 예시와 교재를 보고 아 ~ 쿠키로 클라이언트를 식별하는게 가능하구나 까지는 이해가 갔다
하지만 어떻게 쿠키로 사용자의 로그인 정보를 기억하고 어떻게 장바구니 등을 기억하는지, 또 어떤 것을 선호하는지를 저장하는지 잘 이해가 안갔다.
그래서 여기저기 블로그를 뒤져보고 지피티 목을 한 번 더 졸라보았다.
처음 내가 했던 예상은 쿠키 안에 내 아이디랑 비밀번호를 넣어 놓고
서버 단에서 쿠키를 받아 인증을 하나 .. 이랬다.
무식맨
그게 아니였다.
클라이언트가 웹 서버에서 최초 로그인을 하는 순간 , 로그인 전에 존재하던 쿠키가 아닌 로그인 후 새로운 쿠키를 웹 서버에서 제공한다.
Set-Cookie: session_token=abcdef123456; Path=/; HttpOnly; Secure
// 이런식으로 말이다
그러면 브라우저에선 로그인 된 쿠키 정보를 저장한다.
브라우저나 웹 서버는 클라이언트에게 오는 쿠키를 통해 로그인 이후 할 수 있는 액션을 취하게 해준다든지, 자동으로 로그인 해준다.
캐시는 자주 들어오는 요청에 대한 응답값을 저장해두었다가, 동일한 요청이 들어오면 해당 응답값을 보내준다.
그런데 위에서 생각해보면 클라이언트와 웹 서버는 요청과 응답 사이에 쿠키 값들을 담아 보낸다고 했다.
그럼 나에게 주어진 Set-cookie
값이 캐싱되었다가 다른 사람에게 가버리면, 유일하지 않게 되거나, 내 개인정보가 유출되는거 아닌가 ?
그래서 다양한 제한이 있다.
가장 근본적인 방법으로는 Set-cookie
가 있을 때엔 캐시되지 않도록
Cache-Control : no-cache = "Set-cookie"
로 명시해주는 방법이 있다.
혹은 매우 보수적인 서버는 쿠키 관련 헤더가 존재하는 경우엔 아예 캐시하지 않을 수도 있다.