Post

[HTTP] HTTP 상태 코드와 정보성 헤더 및 특수 헤더 (with 쿠키, 캐시)

HTTP 상태코드

🐙 HTTP 상태코드

HTTP 상태코드는 클라이언트가 보낸 요청의 상태를 응답에서 알려주는 기능을 한다.

HTTP Statusreason-phrasedescrelated-response-header
1xxInformational요청이 수신되어 처리중 
2xxSuccessful요청을 정상 처리  
200OK요청을 정상 처리 
201Created요청에 성공해서 새로운 리소스가 생성됨Location: /members/100
생성된 리소스 경로 해당 필드로 식별
202Accepted요청이 접수되었으나, 처리가 완료되지 않음(ex. 배치처리) 
204No Content서버가 요청을 정상 처리 했지만, 응답 페이로드 본문에 보낼 데이터가 없음 
3xxRedirection요청을 완료하려면, User-Agent 추가 조치가 필요 
301Moved Permanently리다이렉트 시, 요청 메서드가 GET으로 변하고, 본문이 제거될 수 있음Location 헤더가 있으면 해당 위치로 자동 이동
308Permanent Redirect리다이렉트 시, 반드시 요청 메서드와 본문 유지Location 헤더가 있으면 해당 위치로 자동 이동
302Found리소스가 잠시 다른 경로에 있으며, 해당 url을 여전히 사용할 것을 알림
리다이렉트 시, 요청메서드가 GET으로 변하고, 본문이 제거될 수 있음
Location 헤더가 있으면 해당 위치로 자동 이동
307Temporary Redirect리소스가 잠시 다른 경로에 있으며, 해당 url을 여전히 사용할 것을 알림
리다이렉트 시, 요청메서드와 본문 유지
Location 헤더가 있으면 해당 위치로 자동 이동
303See Other리다이렉트 시, 요청메서드가 GET으로 변경Location 헤더가 있으면 해당 위치로 자동 이동
4xxClient Error클라이언트 오류, 잘못된 요청으로 서버가 요청을 수행할 수 없음  
400Bad Request요청파라미터가 잘못되거나, API 스펙이 맞지 않음 etc 
401Unauthorized클라이언트가 해당 리소스에 대한 인증이 필요함WWW-Authenticate 해당 필드로 인증방법을 설명
403Client Error서버가 요청을 이해했지만, 승인을 거부함
인증 자격증명은 있지만, 접근 권한이 불충분함
 
404Not Found요청 리소스를 찾을 수 없음 
5xxServer Error서버 오류, 서버가 정상 요청을 처리하지 못함 
500Internal Server Error서버 문제로 오류 발생 
503Service Unavailable서비스 이용불가, 일시적인 과부하 또는 예정된 작업으로
잠시 요청을 처리할 수 없음
Retry-After 해당 필드로 복구 시점 명시 가능

일반 정보성 헤더

🐀 일반 정보성 헤더
headerReq or Resdesc
User-AgentRequest클라이언트 애플리케이션(웹브라우저) 정보
FromRequestUser-Agent의 이메일 정보
검색엔진에서 주로 사용
RefererRequest현재 요청된 페이지의 이전 웹페이지 주소
유입경로 분석가능
ServerResponse요청을 처리하는 Origin 서버의 정보
DateResponse메세지가 발생한 시간
🍍 Origin 서버
HTTP 요청을 보내면 중간에 여러 프록시 서버를 거치게 되는데
HTTP 응답을 해주는 마지막 서버

명시가 필요한 헤더

🐁 명시가 필요한 헤더
headerReq or Resdesc
HostRequest요청한 호스트 정보(도메인)
하나의 ip주소에 여러 도메인이 적용되어 있을 때, 정확하게 명시해줘야 한다
LocationResponse페이지 리다이렉션 리소스
201일 때는 생성된 리소스 URI, 3xx일 때는 리다이렉션 대상 리소스를 가리킨다
AllowResponse허용가능한 HTTP 메서드
405(Method Not Allowed)응답과 함께 명시
Retry-AfterResponseUser-Agent가 다음 요청을 하기까지 기다려야 하는 시간
503(Service Unavailable)응답과 함께 서비스가 언제까지 불능인지 명시
AuthorizationRequest클라이언트 (인증 메커니즘에 따른) 인증정보 전달
WWW-AuthenticateResponse리소스 접근 시 필요한 인증방법 정의
401(Unauthorized) 응답과 함께 명시

🍍 가상호스팅을 통해 여러 도메인을 한번에 처리할 수 있는 서버는 Host 필드를 통해 각각의 도메인을 구분한다.

RFC7230 ~ 7235, 표현(Representation) 헤더

🍝 표현 헤더는 message body (payload) 를 해석할 수 있는 정보를 제공한다

표현 헤더는 Request, Response 둘다 사용 가능 하다.

representation-headerdescvalue
Content-Type페이로드 형식text/html;charset=UTF-8
application/json
image/png
Content-Encoding페이로드 압축방식gzip
deflate
identity (압축안함)
Content-Language페이로드 자연언어ko
ko-KR
en
en-US
Content-Length페이로드 길이(byte) 

🍪 전송 방식에 따른 헤더

transfer-methodrelated-header
단순전송Content-Length
압축전송Content-Encoding
Content-Length
분할전송Transfer-Encoding: chunked
Content-Length x
범위전송(Request)Range: byte=1001-2000
(Response)Content-Range: bytes 1001-2000/2000

협상(Content Negotiation) 헤더

🍝 클라이언트가 선호하는 페이로드 우선순위
기본 항목 
Accept클라이언트가 선호하는 미디어 타입 전달
Accept-Charset클라이언트가 선호하는 문자 인코딩
Accept-Encoding클라이언트가 선호하는 압축 인코딩
Accept-Language클라이언트가 선호하는 자연언어
🍪 협상과 우선순위 (Quality Values, q)
ex. Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7 ⚠️ q가 생략되어 있으면 1
ex. Accept: */*,text/*,text/plain,text/plain;format=flowed ⚠️ 구체적인 것이 우선한다.

쿠키와 헤더

🌋 HTTP는 무상태 프로토콜이다

클라이언트와 서버가 요청과 응답을 주고 받으면 연결이 끊어지고,
🐖 서버는 이전 요청을 기억하지 못한다.
즉, 클라이언트와 서버는 서로의 상태를 유지하지 않는다.

웹브라우저에는 🍪 쿠키 저장소가 있다.
🍪 쿠키 저장소에 최소한의 정보(상태)를 저장할 수 있다.
쿠키 저장소에 저장된 정보는 모든 요청에 자동 포함된다.
⚠️ 네트워크 트래픽을 추가 유발하므로, 최소한의 정보만 담는것을 권장

🎯 쿠키의 주 사용처는 사용자 로그인 세션 관리에 사용된다.
로그인 시, 서버에서 세션키라는 것을 만들어 Set-Cookie에 세션키를 담아 클라이언트에 전달한다.
Cookie-related-headerReq or Resdesc
Set-CookieResponse서버에서 클라이언트로 쿠키전달
웹브라우저는 해당 필드 값을 쿠키 저장소에 저장
CookieRequest클라이언트가 HTTP 요청 시 서버로 자동 전달 (쿠키값 존재 시)

ex. set-cookie: sessionId=abc123; expires=Sat, 25-Dec-2024 00:00:00 GMT; path=/; domain=google.com; Secure

  • expires
    쿠키 만료일 명시
    만료일이 되면 쿠키 삭제
  • max-age
    쿠키 만료시간 초단위 명시
    0이나 음수를 지정하면 쿠키 삭제
  • domain
    클라이언트가 쿠키를 포함해 요청할 도메인 명시, 서브도메인 포함
    도메인을 생략하면 현재 문서 기준 도메인만으로 한정, 서브도메인x
  • path
    경로로 한번 더 필터링, 해당 경로를 포함한 하위 경로 페이지만 쿠키 전송
    일반적으로 path=/ 루트로 지정
  • Secure
    https인 경우에만 쿠키 전송 가능
    (원래 쿠키는 http, https 구분하지 않고 전송)
  • HttpOnly
    XSS 공격 방지, 자바스크립트에서 접근 불가 document.cookie
    HTTP 전송에만 사용
  • SameSite
    XSRF 공격 방지, 요청 도메인과 쿠키에 설정된 도메인이 같은 경우에만 쿠키 전송

🍪 세션쿠키 : 만료날짜/초를 생략하면 브라우저 종료시까지만 쿠키 유지
🍪 영속쿠키 : 만료날짜/초를 입력하면 해당 날짜/초까지 유지

쿠키와 웹스토리지

🥯 Cookie  /  Web Storage

웹브라우저 내부에 데이터를 저장해두고,
서버에 요청을 보낼 때마다 해당 데이터와 함께 보내고 싶으면 🍪 쿠키를 쓰면 되고
서버에 전송하지 않고, 웹브라우저 내부에 데이터를 저장하고 싶으면
🪹 웹스토리지 localStorage sessionStorage를 쓰면된다.
즉, 클라이언트 자바스크립트 로직에서만 쓸거면, 웹스토리지에 저장한다.

캐시와 조건부 요청 헤더, 검증 헤더

🌋 조건부 요청 헤더에 데이터를 보내고, 검증헤더로 검증과정을 거쳐 캐시를 구현할 수 있다

캐시 유효시간 안에 같은 요청이 발생했을 때,
캐시 유효시간을 검증하고, 🥟 브라우저 캐시에서 결과를 가져오면
유효시간 동안은 네트워크를 통해서 데이터를 다운받지 않아도 된다. 빠른 사용자 경험

더 나아가서, 캐시가 만료되었더라도
해당 요청에 대해 클라이언트가 가진 캐시 데이터와 서버가 가진 데이터가 같다면
그 역시 데이터를 다시 다운받지 않아도 된다. 캐시를 재사용
검증을 위한 네트워크를 통한 데이터 전송은 발생하지만 전송 용량을 줄일 수 있다.

서버가 미리 비교를 위한 검증데이터를 검증헤더에 실어 보내고,
클라이언트는 재요청시 해당 검증데이터를 조건부 요청 헤더에 실어 보낸다.

cache-related-headerReq or Resdesc
Last-ModifiedResponse페이로드 최종 수정일
if-modified-sinceRequest비교를 위한 캐시된 페이로드 최종수정일

서버는 if-modified-since 필드값과 재요청에 대한 리소스의 최종 수정일을 비교하여
HTTP Status code를 반환한다.

1
2
3
4
5
6
HTTP/1.1 304 Not Modified
Content-Type: image/jpeg
Cache-Control: max-age=60
Last-Modified: ...
Content-Length: 34012

캐시된 최종수정일과 리소스 최종수정일이 같으면, 캐시된 데이터가 바뀌지 않은 값임을 알리는
응답 코드(304)를 반환하고, 이때 HTTP BODY는 전송하지 않는다.
캐시된 데이터를 재사용할꺼니까.. 단, 응답 헤더 정보로 캐시의 메타정보는 갱신한다.

해당 응답이 오면 웹브라우저는 캐시로 리다이렉트하여,
🥟 브라우저 캐시에서 캐시된 데이터를 조회한다.

☄️ 검증헤더 Last-Modified와 If-Modified-Since 조건부 요청헤더의 한계
데이터를 수정하여 최종 수정일이 다르지만 데이터 결과가 캐시된 데이터와 같은 경우
또는, 서버에서 별도로 캐시로직을 관리하고 싶은 경우는 다룰 수 없다.

검증헤더 ETag (Entity Tag)조건부 요청헤더 if-None-Match를 사용하면 위의 상황을 다룰 수 있다.

cache-related-headerReq or Resdesc
ETagResponse캐시용 데이터에 임의의 고유한 이름을 달아둠
일반적으로 해시값이나 버전으로 지정한다
if-None-MatchRequest조건을 만족하면 200 0K
조건을 만족하지 않으면 304 Not Modified 응답, 캐시로 리다이렉트

※ 해시알고리즘은 내용이 동일하면 같은 해시값을 뱉는다.

ETag에 실어 보낼 고유한 이름 즉, 캐시 제어 로직은 서버에서 완전히 관리한다.
클라이언트는 캐시 메커니즘을 모른 채 단순히 전달받은 ETag 필드값조건부 요청헤더에 실어 보내면 된다.

프록시 캐시 서버와 캐시 제어 헤더

🍝 프록시 캐시 서버는 인터넷 망 중간에서 공용으로 사용하는 캐시서버(노드)를 말한다

보통 프록시 캐시 서버(public cache)가 존재하면,
웹브라우저가 프록시 캐시 서버에 접근하게 만든다.
즉, 첫번째 요청 유저가 한번 프록시 캐시에 리소스를 다운로드 받아놓으면
두번째 요청 유저부터는 해당 프록시 캐시에서 캐시된 데이터를 사용할 수 있게 설정되어 있다. 빠른 응답

웹브라우저의 🥟 브라우저 캐시는 로컬에서 사용하는 캐시로 private cache라면
프록시 캐시 서버는 공용으로 사용하는 public cache이다.

cache-related-headerReq or Resdesc
Cache-ControlResponsepublic이면 응답이 프록시 캐시 서버(public cache)에 저장되어도 됨을 의미
private면 브라우저 캐시에 저장해야 됨을 의미(default)
s-maxage=60은 프록시 캐시서버에만 적용되는 max-age를 의미
AgeResponseorigin 서버에서 응답 후 프록시 캐시 서버에 머문 시간(초)을 의미

캐시 유효시간

🥯 Cache-Control: max-age  /  expires

둘다 캐시 유효시간을 의미하지만 max-age는 초단위로 지정하고,
expires는 날짜로 캐시 만료일을 지정한다.
초단위가 훨씬 유용하므로 Cache-Control: max-age를 권장한다.
🚫 Cache-Control과 함께 사용되면 expires는 무시된다.

예제: 캐시 무효화

⚔️ 예제: 캐시 무효화
cache-related-headerReq or Resdesc
Cache-ControlResponsemax-age는 캐시 유효 시간(초)를 의미
no-cache는 캐시해도 되지만, 항상 조건부 요청헤더를 통해 origin 서버에서 검증하고 캐시된 데이터를 사용해야 함을 의미
no-store는 저장하면 안되고, 메모리에서 사용 후 삭제해야 함을 의미
Cache-ControlResponsemust-revalidate는 캐시 만료 후 최초 조회 시 origin 서버에서 검증해야함을 의미
origin 서버 접근 실패 시, 반드시 오류 발생 (504 Gateway Timeout)
캐시 유효시간이라면 캐시 사용

확실한 캐시 무효화 응답
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache

※ Pragma는 HTTP/1.0 버전의 하위호환 캐시 제어헤더이다.

This post is licensed under CC BY 4.0 by the author.