HTTP는 익명으로 사용하며 상태가 없고 요청과 응답으로 통신하는 프로토콜이다. HTTP는 연결 자체에 대한 정보를 가지지 않으며 매 요청은 일회성이고 독립적으로 처리된다. 이를 상태가 없다고 하거나 무상태(stateless)라 부른다.
서버는 클라이언트가 보낸 요청을 처리하고 나서 그 응답을 클라이언트로 전송하는데 웹 서버는 요청을 보낸 클라이언트를 식별하거나 방문자가 보낸 연속적인 요청을 추적하기 위해 약간의 정보를 이용할 수 있다.
From 헤더는 사용자의 이메일 주소를 포함한다. 각 사용자가 서로 다른 이메일 주소를 가지므로 사용자를 식별할 수 있지만 악의적인 서버가 이메일 주소를 모아서 스팸 메일을 발송하는 문제가 있기에 From 헤더를 보내는 브라우저는 많지 않다.
User-Agent 헤더는 사용자가 쓰고 있는 브라우저의 이름과 버전 정보, 어떤 경우에는 운영체제에 대한 정보까지 포함하여 서버에게 알려준다. 이는 특정 브라우저에서 제대로 동작하도록 그것들의 속성에 맞춰 콘텐츠를 최적화하는 데 유용할 순 있지만, 특정 사용자를 식별하는 데는 큰 도움이 되지 않는다.
Referer 헤더는 사용자가 현재 페이지로 유입하게 한 웹페이지의 URL를 가리킨다. Referer 헤더만으로 사용자를 식별할 순 없지만, 사용자가 이전에 어떤 페이지를 방문했었는지는 알려준다.
초기 웹 서버들은 사용자 식별에 클라이언트 IP 주소를 사용하려 했다. 클라이언트의 IP 주소는 보통 HTTP 헤더에 없지만 웹 서버는 HTTP 요청을 보내는 반대쪽 TCP 커넥션의 IP 주소를 알아낼 수 있다.
하지만 클라이언트 IP 주소로 사용자를 식별하는 방식은 여러 단점들이 있다.
웹 서버는 사용자 이름과 비밀번호로 인증(로그인)할 것을 요구해서 사용자에게 명시적으로 식별 요청을 할 수 있다.
웹 사이트 로그인이 더 쉽도록 HTTP는 WWW-Authenticate와 Authorization 헤더를 사용해 웹 사이트에 사용자 이름을 전달하는 자체적인 체계를 가지고 있다.
한번 로그인하면, 브라우저는 사이트로 보내는 모든 요청에 이 로그인 정보를 함께 보내므로 웹 서버는 그 로그인 정보를 항상 확인할 수 있다.
서버에서 사용자가 사이트에 접근하기 전에 로그인을 시키고자 한다면 HTTP 401 Login Required 응답 코드를 브라우저에 보낼 수 있다. 브라우저는 로그인 대화상자를 보여주고, 다음 요청부터
Authorization 헤더에 그 정보를 기술하여 보낸다.
쿠키는 사용자를 식별하고 세션을 유지하는 방식 중에서 현재까지 가장 널리 사용하는 방식이다. 쿠키는 캐시와 충돌할 수 있어서 대부분의 캐시나 브라우저는 쿠키에 있는 내용물을 캐싱하지 않는다.
쿠키는 크게 세션 쿠키와 지속 쿠키 두 가지 타입으로 나눌 수 있다. 세션 쿠키는 사용자가 사이트를 탐색할 때, 관련한 설정과 선호 사항들을 저장하는 임시 쿠키다. 세션 쿠키는 사용자가 브라우저를 닫으면 삭제된다. 지속 쿠키는 삭제되지 않고 더 길게 유지될 수 있다. 지속 쿠키는 디스크에 저장되어, 브라우저를 닫거나 컴퓨터를 재시작하더라도 남아있다. 지속 쿠키는 사용자가 주기적으로 방문하는 사이트에 대한 설정 정보나 로그인 이름을 유지하려고 사용한다.
세션 쿠키와 지속 쿠키의 다른 점은 파기되는 시점뿐이다. 쿠키는 Discard 파라미터가 설정되어 있거나, 파기되기까지 남은 시간을 가리키는 Expires 혹은 Max-Age 파라미터가 없으면 세션 쿠키가 된다.
쿠키는 서버가 사용자에게 명찰표를 주는 것과 같다.
사용자가 웹 사이트에 방문하면, 웹 서버는 사용자가 준 명찰표를 읽을 수 있다.
처음에 사용자가 웹 사이트에 방문하면 웹 서버는 사용자에 대해서 아무것도 모른다. 웹 서버는 사용자가 다시 돌아왔을 때, 해당 사용자를 식별하기 위한 유일한 값을 쿠키에 할당한다. 쿠키는 임의의 이름=값 형태의 리스트를 가지고, 그 리스트는 Set-Cookie 혹은 Set-Cookie2(확장 헤더) 같은 HTTP 응답 헤더에 기술되어 사용자에게 전달한다.
브라우저는 서버로 온 헤더에 있는 쿠키 콘텐츠를 브라우저 쿠키 데이터베이스에 저장한다. 사용자가 미래에 같은 사이트를 방문하면 브라우저는 서버가 이 사용자에게 할당했던 쿠키를 Cookie 요청 헤더에 기술해 전송한다.
쿠키의 기본적인 발상은 브라우저가 서버 관련 정보를 저장하고, 사용자가 해당 서버에 접근할 때마다 그 정보를 함께 전송하는 것이다.
보통 브라우저는 쿠키를 생성한 서버에게만 쿠키에 담긴 정보를 전달한다.
서버는 쿠키를 생성할 때 Set-Cookie 응답 헤더에 Domain 속성을 기술해서 어떤 사이트가 그 쿠키를 읽을 수 있는지 제어할 수 있다.
💡 예) Set-cookie: user=”Jun”; domain=”abc.com” domain속성의 중점은 url이 아닌 사이트다. 즉, 여러 사이트 중 어떤 사이트에 접속할 때 해당 쿠키를 읽게 할 것인지 정하는 것웹 사이트 일부에만 쿠키를 적용하는 것. URL 경로의 앞부분을 가리키는 Path 속성을 기술해 해당 경로에 속하는 페이지에만 쿠키를 전달한다.
💡 예) Set-cooke: user=”Jun”; path=”abc.com”; path=/main/ 만약 사용자가 http://abc.com/main/index.html에 접근하면 해당 쿠키를 받게 되지만 http://abc.com/index.html로 접근하면 해당 쿠키를 얻지 못한다.쿠키 트랜잭션과 관련된 문서를 캐싱하는 것은 주의해야 한다. 이전 사용자의 쿠키가 다른 사용자에게 할당돼버리거나, 누군가의 개인 정보가 다른 이에게 노출되는 상황이 일어날 수 있다.
만약 문서가 Set-Cookie 헤더를 제외하고 캐시를 해도 될 경우라면 그 문서에 명시적으로 Cache-Control: no-cache=”Set-Cookie”를 기술해 명확히 표시한다. 또한 캐시를 해도 되는 문서에 Cache-Control: public을 사용하면 웹의 대역폭을 더 절약시켜준다.
만약 응답이 Set-Cookie 헤더를 가지고 있으면, 본문은 캐시할 수 있지만 Set-Cookie 헤더를 캐시하는 것을 주의를 기울여야만 한다. 같은 Set-Cookie 헤더를 여러 사용자에게 보내게 되면, 사용자 추적에 실패할 것이기 때문이다.
어떤 캐시는 응답을 저장하기 전에 Set-Cookie 헤더를 제거하기 때문에, 그 캐시 데이터를 받는 클라이언트는 Set-Cookie 헤더 정보가 없는 데이터를 받게 되어 문제가 발생할 수 있다.
캐시가 모든 요청마다 원 서버와 재검사시켜 클라이언트로 가는 응답에 Set-Cookie 헤더 값을 기술해서 이 문제를 개선할 수 있다. 원 서버는 Cache-Control: must-revalidate, max-age=0 헤더를 캐시된 문서에 추가함으로써 재검사가 일어나게 할 수 있다.
또한, 캐시는 콘텐츠가 캐시해도 되는 데이터라고 하더라도 Set-Cookie 헤더를 가지고 있는 응답은 캐시를 하지 않을 수 있다. 어떤 캐시는 Set-Cookie가 있는 이미지는 캐시를 하지만 Set-Cookie가 있는 텍스트는 캐시를 하지 않는다.