- 웹 서버는 서로 다른 수천개의 클라이언트와 동시에 통신함.
- 서버 들은 익명의 클라이언트로 부터 받는 모든 요청을 처리하는 것 뿐만 아니라 서버와 통신하고 있는 클라이언트를 추적해야 할 수도 있음.
- 서버가 통신하는 대상을 식별하는 데 어떤 기술을 사용하는지 알아보자.
개별 접촉
- 현대의 웹 사이트들은 개인화된 서비스를 제공하고 싶어함.
- 기록한 내용을 바탕으로 사이트를
개인화
시켜서 사용자에게 제공함. - 사용자 특화 환영 메시지 혹은 페이지 내용이 보여짐.
- 고객의 생일이나 특별한 날에 고객의 흥미에 따라 특별한 제품을 추천.
- 주소, 신용 카드 정보 등을 데이터베이스에 저장하여, 식별된 사용자는 더 이상 정보를 입력하지 않고 편리하게 사용함.
- HTTP 트랜젝션은 상태가 없음(stateless). 하지만 많은 웹사이트에서 사용자가 사이트와 상호작용할 수 있게 사용자의 상태를 필요로 함. (ex 장바구니 기능)
- 상태를 유지하기 위해서, 웹 사이트는 사용자에게서 오는 HTTP 트랜젝션을 식별할 방법이 필요함.
HTTP의 사용자 식별 기술에 대해 알아보자.
HTTP 헤더

- 우선 앞의 3개 (From, User-Agent, Referer)를 살펴보자.
(쉽기 때문..)
From
- 사용자의 이메일 주소를 포함함.
- 다만 악의적인 목적으로 사용자들의 이메일 주소를 모아 스팸메일 발송 등의 문제가 있어서 From 헤더를보내는 브라우저는 많지 않음.
- 보통 로봇이나 스파이더는 본의 아니게 웹 사이트에 문제를 일으킬 경우를 대비해 적어 놓음.
User-Agent
- 사용자가 사용하고 있는 브라우저의 이름과 버전정보, 운영체제에 대한 정보를 보냄.
- 보통 특정 브라우저에서 제대로 동작할 수 있도록 콘텐츠를 최적화는데 유용함.
- 다만 사용자 식별에는 도움이 되지 않음.
Referer
- 사용자가 현재 페이지 기준 이전 웹페이지 URL을 가리킴.
- 사용자를 식별할 수는 없지만, 사용자가 이전에 어떤 페이지를 방문했는지를 알아내어 사용자의 웹 사용 행태나 취향을 파악할 수 있음.
위의 3개 헤더들은 사용자 정보를 확실하게 식별하기에는 부족함. 더 자세히 특정 사용자를 식별하는 방법들을 알아보자.
사용자 로그인
- 웹 서버는
사용자 이름과 비밀번호로 인증(로그인)
할 것을 요구해서 사용자에게 명시적으로 식별 요청을 할 수 있음.

- 브라우저는 www.google.com 사이트로 요청.
- 사이트는 사용자 식별정보를 알지 못하므로,
401 Login Required HTTP 응답코드
와WWW-Authenticate 헤더
를 반환하여 로그인 요청. (브라우저에 로그인 창 띄움)
- 사용자가 이름과 비밀번호를 입력하고, 브라우저는 기존요청을 다시 보내서 사용자 식별을 시도.
- 서버는 사용자 식별정보를 앎.
- 이후 요청에 대해서, 브라우저는 서버에게 사용자 식별정보를 Authorization 헤더에 담아 전송.
- 하지만, 웹 사이트 로그인은 매우 귀찮은 일임. 사이트를 옮겨다닐 때 마다 해당 사이트에 로그인을 해야 하고 사이트 마다 정보가 다를 수 있으며 그 정보를 사용자가 모두 기억해야 함.
클라이언트 IP 주소
- 초기의 웹 선구자들은 사용자 식별에
클라이언트의 IP 주소
를 사용하려 함. 단, 사용자가 확실한 IP 주소를 갖고 있어야 하고, 그 주소가 절대 바뀌지 않고, 웹 서버가 요청마다 클라 IP를 알 수 있다면 가능함. - 여러 사용자가 한 대의 컴퓨터를 사용한다면 하나의 IP로 어떤 사용자인지 식별할 수 없음.
- 인터넷 서비스 제공자(ISP)는 사용자가 로그인하면 동적으로 IP 주소를 할당함. 매번 다른 주소를 받으므로 식별할 수 없음.
- 네트워크 주소 변환(Network Address Translation, NAT) 방화벽을 통해 인터넷을 사용할 경우, NAT 장비는 실제 IP 주소를 방화벽 뒤로 숨기고, 내부에서 사용하는 하나의 방화벽 IP 주소(다른 포트번호)로 변환함.
- HTTP 프락시와 게이트웨이는 원 서버에 새로운 TCP 연결을 함. 웹 서버는 클라이언트의 IP 대신 프락시 서버의 IP 주소를 보게 됨.

- 위의 문제점들로 인해 이 방식은 제대로 동작하지 않음. 인트라넷(단체의 직원만 접근이 가능한 사설망) 같이 제한된 영역 내에서는 적절해 보일 수 있지만, IP 주소가 임의로, 타의로 변경되거나 프락시 때문에 문제가 발생할 수 있음.
뚱뚱한 URL
- 어떤 웹 사이트는 사용자의
URL
마다 버전을 기술하여 사용자를 식별하고 추적함.
- URL 경로의 처음이나 끝에 어떤
상태정보
를 추가해 확장.
- 사용자의 상태 정보를 포함하고 있는 URL을
뚱뚱한 URL
이라고 함.
- (아마존 URL 참고)
<a href="/exec/obidos/002-1234567-333">All Gifts</a> <a href="/exec/wishlist/ref=gr_pp/002-1234567-333">Wish List</a>
- 사용자가 처음 웹 사이트에 방문하면 유일한 ID가 생성되고, 이 값은 URL에 추가되며 서버는 클라이언트를 이 뚱뚱한 URL로 리다이렉트 시킴.
- 그런데 이 기술에는 심각한 문제가 있음.
- 뚱뚱하고 못생긴 URL은 사용자에게 혼란을 줌.
- 특정 사용자와 세션에 대한 정보를 포함하기 때문에, 그 주소를 누군가에게 공유하면 누적된 개인정보를 타인에게 공유하게 됨.
- URL이 달라지기 때문에 기존 캐시에 접근할 수 없음.
- 뚱뚱한 URL에 해당하는 HTML 페이지를 다시 그려야 해서 서버 부담이 가중됨.
- 사용자가 특정 URL을 요청하거나 링크를 타고 다른 사이트로 이동하면 뚱뚱한 URL 세션에서 이탈하게 됨. 이탈하면, 그동안 쌓였던 데이터(장바구니 등)가 초기화됨.
- 뚱뚱한 URL을 북마크하지않는 이상, 로그아웃 하면 모든 정보를 잃음 (세션 간 지속성의 부재).
쿠키
- 쿠키는 사용자를 식별하고 세션을 유지하는 방식 중에서 현재까지 가장 널리 사용하는 방식임.
- 쿠키는 새로운 HTTP 헤더를 정의함.
- 쿠키는 캐시와 충돌할 수 있어서, 대부분의 캐시나 브라우저는 쿠키에 있는 내용물을 캐싱하지 않음.
ㅤ | 캐시(Cache) | 쿠키(Cookie) |
정의 | 캐시는 웹 페이지 요소를 저장하기 위한 임시 저장소이다.
특히, 후에 필요할 것 같은 요소들을 저장한다.
이러한 요소들은 그림 파일이나 문서 파일 등이 될 수 있다. | 쿠키 또한 정보를 저장하기 위해 사용된다.
기본적으로 웹서버에서 PC로 보내는 작은 파일들을 저장한다.
보통 쿠키는 누군가 특정한 웹 사이트를 접속할 때 발생한다. |
목적 | 캐시는 웹 페이지가 빠르게 렌더링 할 수 있도록 도와준다. | 쿠키는 사용자의 인증을 도와준다. |
삭제 | 사용자가 직접 수동으로 삭제해주어야한다. | 만료기간이 있어 시간이 지나면 자동삭제 된다. |
예시 | 오디오, 비디오 파일 | 유저의 선호도(로그인 정보, 방문기록, 방문횟수) |
쿠키의 타입
세션 쿠키(session cookie)와 지속 쿠키(persistent cookie)
두 가지 타입으로 나뉨.세션 쿠키
사용자가 사이트를 탐색할 때, 관련한 설정과 선호 사항들을 저장하는 임시 쿠키로 브라우저를 닫으면 삭제됨.지속 쿠키
삭제되지 않고 더 길게 유지디스크에 저장되어, 브라우저를 닫거나 컴퓨터를 재시작해도 남아있음. 주기적으로 방문하는 사이트 정보나 로그인 이름을 유지.
- 둘의 다른 점은
파기되는 시점
뿐. 파기되는 시점을 가리키는 Expires 혹은 Max-Age 파라미터가 없으면 세션쿠키임.
쿠키는 어떻게 동작하는가

- 처음 사용자가 웹 사이트에 방문하면 웹 서버는 사용자에 대해 아무것도 모름.
- 웹 서버는 사용자가 다시 왔을 때, 해당 사용자를 식별하기 위한 유일한 값을 쿠키에 할당함. 그 리스트는 Set-cookie 또는 Set-cookie2 같은 HTTP 응답 헤더에 전달. 브라우저는 서버에게 받은 Set-cookie 헤더에 있는 쿠키 콘텐츠를 브라우저 쿠키 데이터베이스에 저장.
- 사용자가 다시 같은 사이트를 방문하면, 브라우저는 서버가 이 사용자에게 할당했던 쿠키를 Cookie 요청 헤더에 기술해 전송함.
쿠키 상자 : 클라이언트 측 상태
- 브라우저는 쿠키 정보를 저장할 책임이 있음.
- 이 시스템을 클라이언트 측 상태 라고 함.
- 쿠키 명세의 공식적인 이름은
HTTP 상태 관리 체계(HTTP State Management Mechanism)
.
사이트마다 다른 쿠키들
- 각 브라우저는 각기 다른 방식으로 쿠키를 저장함.
- 구글 크롬 쿠키.
- SQLite에 쿠키를 저장함. SQLite 파일에 있는 각 행이 쿠키 한 개에 해당함.
- creation_utc : 쿠키가 생성된 시점을 초 단위로 기술
- host_key : 쿠키의 도메인
- name : 쿠키의 이름
- value : 쿠키의 값
- path : 쿠키와 관련된 도메인에 있는 경로
- expires_utc : 쿠키의 파기 시점을 초 단위로 기술
- is_secure : 이 쿠키를 SSL 커넥션일 경우에만 보낼지 여부. 0이 아님을, 1이 맞음을 의미.

- MS IE 쿠키
- 캐시 디렉터리에 각각의 개별 파일로 쿠키를 저장함.

- 브라우저는 수백 수천 개의 쿠키를 가질 수 있지만, 보통 각 사이트에 2~3개의 쿠키만을 보냄.
- 성능 저하.
- 서버에 특화된 name/value 쌍이기에, 대부분의 사이트에서는 무의미한 값.
- 특정 사이트에서 제공한 정보를 신뢰하지 않는 사이트에서 가져갈 수 있어서 보안에 문제.
- 그렇기에 브라우저는 쿠키를 생성한 서버에게만 쿠키에 담긴 정보를 전달함.
- google.com 에서 생성된 쿠키는 google 에만, naver.com에서 생성된 쿠키는 naver 에만 보냄.
- 쿠키 Domain 속성
- 서버는 쿠키를 생성할 때 Set-cookie 응답 헤더에 Domain 속성을 기술해서 어떤 사이트가 해당 쿠키를 읽을 수 있는지 제어할 수 있음.
Set-cookie: user="mary17"; domain="github.com"
Cookie: user="mary17"
- 쿠키 Path 속성
- URL path 속성을 기술해서 더 정확한 페이지로 쿠키를 전달할 수 있음.
Set-cookie: pref=compact; domain="github.com"; path=/pro/
Cookie: user="mary17"
만 얻고, www.github.com/pro/로 접근하면 Cookie: pref=compact
도 함께 얻을 수 있음.- 쿠키는 일종의 상태정보 라고 할 수 있음.
광고사는 이 기술에 Referer 헤더를 접목하여 사용자의 프로필과 웹 사이트 사용 습관에 대한 방대한 데이터를 구축할 수 있음.
쿠키 구성요소(명세)
- 쿠키 명세에는 Version 0 쿠키(넷스케이프 쿠키), Version 1 쿠키(RFC 2965)가 있음.
- Version 1은 RFC 6265 "HTTP State Management Mechanism"에 의해 폐기됨.
- Version 0(넷스케이프) 쿠키
- 최초의 쿠키는 넷스케이프가 정의함.
- 전반적인 형태는 다음과 같음.
Set-Cookie: name=value [; expires=date] [; path=path] [; domain=domain] [; secure] Cookie: name1=value1 [; name2=value2] ...
- 세미 콜론으로 구분하며, Domain, Path, Secure 필터들이 현재 요청하려는 사이트에 적합하면 파기되지 않은 쿠키들을 함께 보냄.
- 참고) 도메인에서 .com, .edu 같은 형식의 도메인 기술을 방지하고자, 최대 2~3개의 도메인을 기술하게 함.
- ex)
Cookie: session-id=002-123341-4444444; session-id-time=1007884800

- Version 1 (RFC 2965) 쿠키
- 원 버전인 넷스케이프 표준보다 좀 더 복잡함.
- 폐기되어 더 이상 지원되지 않음.
set-cookie = "Set-Cookie2:" cookies cookies = 1#cookie cookie = NAME "=" VALUE *(";" set-cookie-av) NAME = attr VALUE = value set-cookie-av = "Comment" "=" value // 설명 가능 "CommentURL" "=" <"> http_URL <"> "Discard" //클라 프로그램 종료시 쿠키 삭제 "Domain" "=" value "Max-Age" "=" value // 절대 날짜 값 대신 초 단위 상태 값으로 생명주기 결정 "Path" "=" value "Port" [ "=" <"> portlist <"> ] // 도메인, 경로 뿐 아니라 포트번호로도 쿠키 제어 가능 "Secure" "Version" "=" 1*DIGIT // 호환되는 버전 정보 portlist = 1#portnum portnum = 1*DIGIT cookie = "Cookie:" cookie-version 1*((";" ",") cookie-value) cookie-value = NAME "=" VALUE [";" path] [";" domain] [";" port] cookie-version = "$Version" "=" value NAME = attr VALUE = value path = "$Path" "=" value domain = "$Domain" "=" value port = "$Port" [ "=" <"> value <"> ]
- 쿠키와 세션 추적
- 쿠키는 웹 사이트에 수차례 트랜잭션을 만들어내는 사용자를 추적하는데 사용함.
- ex) 온라인 쇼핑 중 쇼핑카트를 유지하려 세션 쿠키를 사용함.
- 쿠키와 캐싱
- 쿠키 트랜젝션과 관련된 문서를 캐싱하는 것은 주의해야 함. 이전 사용자의 쿠키가 다른 사용자에게 할당되거나, 누군가의 개인 정보가 다른 사람에게 노출될 수 있기 때문.
- 문서가 Set-Cookie 헤더를 제외하고 캐시를 해도 될 경우라면 문서에 명시적으로
Cache-Control: no-cache="Set-Cookie"
를 기술하자. - 또한, 캐시를 해도 되는 문서에
Cache-Control: public
을 사용하면 웹 대역폭을 더 절약시킬 수 있음. - 캐시가 모든 요청마다 원 서버와 재검사시켜 클라이언트로 가는 응답에 Set-Cookie 헤더 값을 기술할 수 있도록 원 서버는 다음의 헤더를 캐시 문서에 추가함.
Cache-Control: must-revalidate, max-age=0
- Cookie 헤더가 오면, 결과 콘텐츠가 개인정보를 담고 있을 수도 있음. 개인 정보는 캐시되지 않도록 표시되어야 하지만, 그 표시를 하지 않는 서버도 있음.
- 보수적인 경우 Set-Cookie가 있는 이미지에 대해서는 캐시를 하지만, 텍스트는 캐시를 하지 않는 캐시도 있음. 따라서, 캐시 이미지에 파기 시간이 0인 Cookie 헤더를 설정해서 매번 재검사를 하도록 강제할 수 있음.
캐시되지 말아야 할 문서가 있다면 표시하라
Set-Cookie 헤더를 캐시 하는 것에 유의하라
Cookie 헤더를 가지고 있는 요청을 주의하라
- 쿠키, 보안 그리고 개인정보
- 개인정보 정책에만 유의한다면, 쿠키에 관련한 위험성보다 세션 조작이나 트랜젝션상의 편리함이 더 큼.