
HTTP Message를 활용하기 위해 먼저 HTTP Message 통신 웹 계층을 알아봤고,
HTTP Message에 대해 자세히 살펴보았다.
HTTP의 특징 중에는 클라이언트의 정보를 저장하지 않는 무상태 프로토콜(Stateless)이 있었다.
사실 서버는 로그인과 같은 기본 정보는 저장해두어야 하기에
완벽한 무상태 프로토콜 환경을 구축하는 것은 불가능하다.
하지만 HTTP는 무상태 프로토콜이다.
그렇다면 어떻게 클라이언트의 정보를 유지할 수 있을까?
HTTP에서 클라이언트 정보를 유지하기 위한 쿠키(Cookie)에 대해 알아보자.

웹 브라우저를 사용하면서 쿠키라는 단어는 한번쯤 들어봤을 것이다.
일부 사이트에서는 쿠키에 동의하냐는 상태창은 빈번하게 볼 수 있기 때문이다.
그렇다면 쿠키란 무엇일까?
쿠키란 HTTP의 특징인 무상태 프로토콜을 극복하여
서버가 브라우저에 사용자 상태 정보를 기억하기 위해 저장하는 작은 데이터 조각을 의미한다.
작은 사용자 상태 정보 데이터 조각이라고 해서 쿠키라는 이름이 붙은 것이다!
쿠키에 동의하냐는 말은, 사용자의 데이터 입력과 웹 이동을 저장하는 것에 동의하냐는 의미이다.
쿠키가 없다면 서버의 메모리를 사용해서 사용자 정보를 저장해야 하는 문제가 생긴다.
쿠키는 Header에 정보를 추가하여 사용할 수 있다.
쿠키와 관련된 Header를 알아보자.

서버는 클라이언트가 전달한 데이터 중 저장해야할 데이터를 정하여
Header에 해당 내용을 포함해서 응답한다.
응답을 받은 클라이언트는 헤더를 분석하여 웹 브라우저의 쿠키 저장소에 데이터를 저장한다.
쿠키는 추가적으로 네트워크 트래픽을 유발하기 때문에 최소한의 정보만을 사용하며
보안에 민감한 데이터는 저장해선 안된다.
서버 측에서 저장해야할 데이터를 지정하는 헤더이다.
저장해야할 데이터는 서버 측에서 설정하여 Set-Cookie에 데이터를 포함하여 응답한다.
쿠키의 만료일을 설정한다.
초 단위로 쿠키의 생명 주기를 설정한다.
생명주기를 설정하지 않으면 브라우저 종료 시 까지만 유지되며, 세션 쿠키라고 부른다.
생명 주기를 입력하면 입력한 시간 동안만 유지되며, 영속 쿠키라고 부른다.
도메인 지정 시 기준 도메인과 서브 도메인에 쿠키를 사용하여 접근한다.
생략 시에는 현재 도메인만 쿠키를 사용해 접근한다.
path 지정 시, path에 지정된 하위 경로에는 쿠키를 사용하여 접근한다.
Secure 적용 시, https에만 저장해야할 쿠키 데이터를 전송한다.
클라이언트는 http로 접근 시에 쿠키에 접근할 수 없다.
클라이언트 측은 쿠키 저장소에 저장된 클라이언트 정보를 Cookie 헤더에 담아 전송한다.
서버 측은 Cookie Header를 통해 저장된 클라이언트의 정보를 확인할 수 있다.

쿠키는 클라이언트의 정보를 저장하기 위한 기술이다.
캐시는 쿠키와는 다른 개념으로, 자주 사용되는 데이터를 저장하여
빠르게 접근하도록 하며 네트워크 트래픽을 줄이는 기술이다.
캐시가 없으면 동일한 데이터를 계속해서 다운로드 해야하고 속도가 저하된다.
캐시가 있는 경우 내부 캐시 저장소를 이용하기 때문에,
네트워크 트래픽이 발생하지 않아 성능이 향상되고 속도가 빨라진다.
캐시 저장소에 데이터가 저장되는 시간인 캐시 시간을 설정한다.
시간이 오래되어 데이터가 수정될 수 있기 때문에,
캐시 시간을 설정하여 만료 시 데이터를 다시 요청하고
수정이 발생했을 수 있는 데이터를 새롭게 저장한다.
하지만 캐시 시간이 만료되기 전에 서버에 데이터가 수정되었다면 말짱 도루묵이다.
이걸로는 부족하다. 다른 수단이 필요하다.

클라이언트 측과 서버 측은 데이터 수정 날짜를 가지고 있다.
클라이언트는 서버에 데이터를 요청할 때,
if-modified-since Header에 데이터 수정 날짜를 함께 전달한다.
서버는 해당 헤더를 확인하고 서버의 데이터 수정 날짜인 Last-Modified와 일치하면
message body 없이 응답하여 캐시 저장소의 데이터를 사용하도록 유도한다.
(이 때 사용되는 응답이 304 Not Modified 이다)
데이터가 변경됐다면 새롭게 데이터를 전송하고 200 OK로 응답한다.
하지만 수정 날짜에는 한계가 있다.
1초 미만 단위로 조정이 불가능하여 차이가 발생할 수 있고
데이터가 동일해도 수정 날짜가 다르면 데이터가 수정된 것으로 간주한다.
영향 없는 데이터 수정마저 수정된 것으로 간주하여 캐시 로직을 커스터마이징 할 수 없다.
아무래도 좀 더 진화된 방식이 필요해보인다.
ETag란 캐시 데이터의 고유 버전 이름을 의미한다. 즉, 검증 헤더이다.
이제 데이터가 수정되면 수정 날짜가 변하는 것이 아닌 ETag가 수정된다.
클라이언트는 서버에 데이터를 요청할 때,
if-None-Match: ETag 헤더를 통해 ETag 정보를 전달하고
서버 측은 보유한 ETag와 일치하는지 확인하고 일치하면 캐시 저장소를 사용하도록 유도한다.
클라이언트와 서버는 데이터 통신마다 캐시 저장소의 데이터 상태를 확인할 수 있으며,
시간에 구애받지 않고 원할 때 ETag를 수정하며 캐시 로직을 커스터마이징 할 수 있게 됐다!
클라이언트가 항상 원서버에 데이터를 요청하는 것은 속도를 저하시킨다.
클라이언트가 원서버까지 가지 않고 조금이라도 가까운 서버에 요청할 수 있도록
나라마다 프록시 캐시 서버를 도입하여 운영하고 있다.
자주 사용하는 캐시 헤더를 살펴보자.
캐시 유효 시간을 설정하는 헤더이다.
데이터 캐시가 가능하지만 원 서버 검증을 필요로 하는 헤더이다.
원 서버 접근이 어려운 경우 서버 설정에 따라 프록시 캐시에서 데이터를 반환할 수 있다.
참고로 Pragma: no-cache 헤더와 Expires: 헤더는
각각 HTTP 1.0 이전, HTTP 1.0과 같이 HTTP 이전 버전에서 사용되는 헤더이다.
캐시 저장을 불가능하게 하는 헤더이다.
캐시 만료 후 최초 조회 시에만 원 서버에 검증을 요청하는 헤더이다.
캐시 유효 시간에는 캐시 저장소의 데이터를 사용한다는 점이 no-cache와는 다르다.
원서버 검증 실패 시에는 프록시 캐시에 접근하는 것이 아닌 반드시 오류를 반환한다.
Response가 public 캐시에 저장이 가능한 것을 의미한다.
프록시 캐시와 같이 중간 서버에 저장될 수 있다.
Response가 특정 개인의 브라우저에만 저장이 가능한 것을 의미한다
private가 기본값이다.
프록시 캐시에 적용되는 캐시 유효 시간이다.
원서버 응답 이후 프록시 캐시 내에 머문 시간을 의미한다.
프록시 캐시 내에 데이터가 얼마나 오래된 것인지 파악할 수 있다.

HTTP에서 중요하게 사용되는 쿠키와 캐시에 대해 알아봤다.
쿠키의 헤더인 Set-Cookie와 Cookie를 기억해서 Message를 확인해보자.
캐시는 여러 한계를 극복한 ETag를 사용한다는 점을 기억하자.
앞으로 쿠키와 캐시의 차이점을 명확히 이해하고 사용하자.