쌩로그

모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런(김영한) 본문

CS/네트워크

모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런(김영한)

.쌩수. 2023. 9. 19. 07:02
반응형

목록

  1. 포스팅 개요
  2. 본론
      2-1. TCP/IP가 나오게 된 배경
      2-2 TCP와 UDP
      2-3. PORT
      2-4. DNS(Domain name service)
      2-5. URI, URL, URN
      2-6. 브라우저에서 홈페이지를 접속하면,
      2-7. HTTP
      2-8. stateful vs statesless
      2-9. HTTP 메시지
      2-10. HTTP 메서드
      2-11. HTTP 메서드 종류
      2-12. HTTP메서드의 특징
      2-13. 클라이언트와 서버의 데이터 전송
      2-14. HTTP의 상태코드
      2-15. HTTP 일반 헤더
      2-16. 표현
      2-17. 협상(콘텐츠 네고시에이션)
      2-18 전송 방식
      2-19 일반 정보
      2-20 특별한 정보
      2-21 인증 헤더
      2-22 쿠키
      2-23 캐시 기본 동작
      2-24 검증 헤더와 조건부 요청1
      2-25 검증 헤더와 조건부 요청2
      2-26 캐시와 조건부 요청 헤더
      2-27 프록시 캐시
      2-28 캐시 무효화
  3. 요약

1. 포스팅 개요

이 포스팅은 인프런에서 김영한님의 모든 개발자를 위한 HTTP 웹 기본 지식을 출퇴근 길에 강의를 들은 것을 총 정리한 내용입니다.

2. 본론

2-1. TCP/IP가 나오게 된 배경

TCP/IP가 나오게 된 배경은 다음과 같습니다.
인터넷 프로토콜은 변수가 많았습니다.

  1. 목적지가 없을 수도 있고, (있는지 확신할 수 없고,)
  2. 중간에 패킷이 유실될 우려가 있으며,
  3. 패킷의 순서가 다르게 갈 수 있습니다.
    (예를 들면, Hello, World를 보냈는데, World Hello로 오는 경우입니다.)

그래서 나온 것이 바로 TCP 입니다.

2-2 TCP와 UDP

TCP의 특징은 다음과 같습니다.

  • 연결 지향 (3 way handshake)적입니다
    • 참고로 이 부분은 개념적인 부분입니다.
  • 데이터 전달 보증
    • 데이터를 받았는지에 대한 여부를 알 수 있습니다.
  • 순서 보증
    • 순서가 다르게 왔으면 다시 보내라고 합니다.

UDP는 최근 HTTP3이 등장하면서 각광받고 있지만 현재 자주 쓰이는 곳(HTTP 1.1)에서는 인터넷 프로토콜과 별 차이 없습니다.
다만, 여기에 포트와 체크섬이 더해졌습니다.

2-3. PORT

PORT는 같은 IP로 여러 서비스가 접근하는데 구분할 수 있는 용도로 사용합니다.
비유하자면,
IP를 아파트, PORT는 아파트의 호수로 비유할 수 있습니다.

포트는 0-65535 까지 사용가능하며
0-1023 잘 알려진 포트(Well known port)로 이미 약속되어있습니다.

2-4. DNS(Domain name service)

DNS(Domain name service)
IP는 기억하기 어렵습니다. 기억도 어려운데 변경될 수 있다.
그래서 IP를 보다 쉽게 기억하기 위해 고안되었다고 합니다.

참고로, IP를 DNS로 등록하려면 DNS서버에 등록해야합니다!

2-5. URI, URL, URN

URI는 URL과 URN의 개념을 합친 것입니다.
URL은 자원의 경로를 뜻하고,
URN은 자원의 이름을 뜻합니다.

URN만으로는 자원 식별이 어렵습니다.
보통 URL을 쓰고, 통상적으로 URL과 URI를 동일한 의미로 봅니다.

URL구조

URL 구조는 다음과 같습니다.

스키마(=프로토콜) . 호스트 : 포트(생략 가능 80 HTTP , 443 HTTPS) / 쿼리 - 계층적 구조?쿼리스트링(=쿼리 파라미터)

쿼리스트링은 ?로 시작하며, 값들을 &으로 이어서 작성합니다.
쿼리스트링이라고 하는 이유는 값을 넣으면 문자열로 들어가기 때문에 쿼리스트링이라고 합니다.

2-6. 브라우저에서 홈페이지를 접속하면,

말 그대로 웹브라우저로 요청을 보내면 다음과 같은 일이 일어납니다.

// 먼저 DNS서버로 가서 DNS에 등록된 아이피를 찾는다.
// 아이피를 찾아서 HTTP 요청메세지를 보낸다.
// 서버가 요청에 대해 응답한다.
// 응답메세지의 본문에 HTML 정보를 담는다.
// 브라우저가 받은 응답메세지의 본문을 보고, 사용자에게 렌더링을 한다.

(이 과정은 SSR느낌이네요 ...^^;; )

2-7. HTTP

원래 Hyper Text transfer Protocol인데, 하이퍼 텍스트(링크 가능한 텍스트 문서) 전송 프로토콜인데, 요즘은 거의 모든 데이터를 HTTP로 통신하고있다고 합니다..
버전은
HTTP 1.1이 현재 중요하고, 2 or 3도 나오고있지만, 1.1이 현재는 대중적이다.
HTTP 2TCP, HTTP 3UDP를 기반으로 합니다.

클라이언트와 서버

클라이언트와 서버의 역할이 나눠지면 일을 독립적으로 진행할 수 있는 장점이 있습니다.
클라이언트는 프론트에 집중, 서버는 백엔드에 집중하면되고, 아키텍쳐의 고도설계를 굳이 클라이언트(프론트)에 알리지않고 진행해도 무방하다.

2-8. stateful vs statesless

stateful은 상태유지, statesless는 무상태성을 의미합니다.

stateful

stateful은 상태를 유지합니다.

중간에 서버가 장애가 나서 다른 서버 디바이스로 바뀌면, 이전까지의 요청과 응답은 아무 의미가 없어집니다. 때문에 같은 서버를 계속 유지해야한다는 단점이 있습니다.

statesless

stateless는 클라이언트의 상태를 유지하지 않는다.
중간에 서버가 바뀌어도 어차피 상태를 유지하지 않기 때문에 상관없습니다.
때문에 같은 서버를 계속 유지하지 않아도 됩니다.
이는 무한으로 확장가능하고, 클라이언트로부터 많은 요청이 들어왔을때, 서버를 대거 투입할 수 있는 장점이 있습니다.

stateless에는 비연결성의 특징도 있는데,
이는 요청과 응답이 끝나면 바로 연결을 끊음으로써 최소한의 자원만 사용하도록 합니다.

그런데 브라우저에서 하지만 한 번의 연결(요청)로 css,이미지, html 태그가 모두 다 다운되는데, 만약 상태를 유지하지 않으면 계속 똑같은 정적 리소스를 받아야되는 비효율적인 부분이 있습니다.

이런 부분때문에 상태유지가 필요할 때도 있습니다.
또 다른 예를 들어 로그인도 그렇습니다.
그래서 브라우저의 쿠키와 세션을 이용해서 최소한의 상태를 유지할 수 있도록 하였습니다.

그리고, HTTP 2와 3에는 더욱이 최적화되었다.

영한님은 말하시기를 "우리는 stateless를 최대한 지향"해야한다고 하셨습니다.
그렇게 해야 동시에 많은 요청이 들어왔을 때 대응할 수 있다고 하면서요.. ㅎㅎ;

============

2-9. HTTP 메시지

HTTP 메서드의 구조는 다음과 같습니다.

=========================
스타트라인 (응답은 status라인이라고도함)
헤더
공백라인(empty-line=CRLF)
바디(요청메세지 본문)

=========================

요청메세지

요청메세지는 다음과 같습니다.

시작 라인
헤더
공백 라인

시작 라인

HTTP메서드 요청대상 HTTP버전

헤더(Heaser)

헤더의 요소로는 field-name이 있는데, 다음과 같습니다.
field-name: OWS(띄어쓰기를 허용하는) 필드에 대한 값

field-name의 특징은 다음과 같습니다.

  • field-name은 대소문자를 구분하지 않습니다.
  • 전송에 필요한 모든 정보를 담습니다.
  • 표준 헤더가 너무 많습니다.
  • 필요시 추가 가능가능하니다.

메세지 바디

  • 실제 전송할 데이터를 의미합니다.
  • byte로 표현할 수 있는 모든 데이터를 전송할 수 있습니다.

2-10. HTTP 메서드

HTTP API에서 URI는 리소스를 식별하는 식으로 설계해야합니다.

리소스의 행위를 식별하는 것이 아니다.
예를 들면, "미네랄을 캐라"에서 미네랄이 자원이지, 미네랄을 캐는 것이 자원은 아닙니다.

가장 먼저 처음하는 실수는 다음처럼 행위로 API를 설계한다.
/members/create
/members/update
/members/find-by-id
/members/delete

하지만 리소스를 식별하는 식으로 API설계를 하면 모든 행위(메소드)에 대한 url은 다음과 같을 수 있습니다.
바로 이 url로 다양하게 할 수 있습니다.
/members/{id}

그럼 하나의 URI로 행위를 어떻게 구별할까요?
바로 HTTP 메서드를 통해서 구별합니다.

2-11. HTTP 메서드 종류

종류는 다음과 같습니다.
GET : 리소스 조회
POST : 요청 데이터 처리, 주로 등록에 사용합니다.
PUT : 리소스를 대체, 해당 리소스가 없으면 생성합니다.
PATCH : 리소스의 부분 변경을 합니다.
DELETE : 리소스를 삭제합니다.
HEAD : GET과 동일하지만 메서지 부분을 제외하고, 상태줄과 헤더만 반환합니다.
OPTIONS : 대상 리소스에 대한 통신 가능 옵션(메서드)을 설명(주로 CORS에서 사용)합니다.
CONNECT : 대상 자원으로 식별되는 서버에 대한 터널을 설정
TRACE : 대상 리소스에 대한 경로를 따라 메세지 루프백 테스트를 수행.

참고로!
CONNECT, TRACE는 잘 사용하지 않는다고 하니 참고해주세요!

GET

GET은 리소스를 조회합니다.
서버에 전달하고 싶은 데이터는 query(쿼리 스트링, 쿼리파라미터)를 통해서 전달합니다.
메세지 바디를 통해서 데이터를 전달할 수 있지만, 지원하지 않는 곳이 많고, 실무에서는 보통 GET메서드에 바디를 넣지 않는다고 하네요.

POST

POST는 요청 데이터를 처리합니다.
메세지 바디를 통해 서버로 요청데이터를 전달하면 서버는 요청데이터를 처리합니다.
메세지 바디를 통해 들어온 데이터를 처리하는 '모든' 기능을 수행합니다.
주로 전달된 데이터는 신규 리소스를 등록하거나, 프로세스 처리에 사용합니다.

POST는

  • 새로운 리소스를 등록하는데 주로 사용합니다.
  • 요청 데이터를 처리할 수 있습니다.
  • 단순히 데이터를 생성하거나 변경하는 것을 넘어서 프로세스를 처리해야하는 경우에 POST를 사용합니다.
  • 다른 메서드로 처리하기 애매한 경우에 사용합니다.
  • post메서드로 조회하는 경우 조회를 하고싶지만, 메세지 바디에 넣고싶은 경우에 사용한다

참고로 get메서드를 통해서 들어오는 값은 캐싱이 가능합니다.
웬만한 조회는 get을 통해서 하되, 어쩔 수 없을 때 post를 사용하는 것을 권장합니다.

put

post와 다르게 클라이언트가 식별자를 알고있습니다.
put은 리소스가 있으면 대체합니다.
또한, 리소스가 없으면 새로 생성한다.
그리고 리소스를 완전 대체한다.

ex) 이름, 나이를 가진 데이터에 나이에 대한 값만 put으로 넣으면 이름, 나이를 가진 데이터는 나이만 가집니다.

put은 부분 대체가 되지 않습니다.
그래서 나온 HTTP 메서드가 patch 메서드이다.
드물게 patch 메서드를 지원하지않는 서버가 있는데, 이 때는 깡패메서드인 post메서드를 사용하면 됩니다.

delete

delete는 리소스를 제거하는데 사용합니다.

2-12. HTTP메서드의 특징

HTTP의 특징은 다음과 같습니다.

  • 안전합니다.
    • 호출해도 리소스를 변경하지 않습니다.
  • 멱등
    • 한 번 호출하든 두 번 호출하든 결과가 똑같습니다.
      • GET 한 번 조희하든 두 번 조회하든 결과는 같습니다.
      • PUT 결과를 대체한다. 같은 요청을 여러 번 해도 결과는 같습니다.
      • DELETE 삭제한다. 같은 요청을 어러 번 해도 삭제된 결과는 같습니다.
      • POST 멱등이 아니다. 두 번 호출하면 결제가 중복됩니다.
    • 멱등을 통해서
      • 자동 복구 매커니즘을 활용할 수 있고,
      • 서버가 TIMEOUT 등으로 항상 응답을 주지 못 했을 때, 클라이언트가 같은 요청을 해도 되는가에 대한 판단 근거가 된다.

단!, 멱등은 외부 요인으로 인해서 리소스가 변경되는 것까지 고려하진 않습니다.

  • 캐시가능
    • 응답결과 리소스를 캐시해서 사용해도 되는가에 대한 내용입니다.
      • GET HEAD POST PATCH는 캐시가능합니다.
        • 하지만 실제론 GET HEAD 정도만 캐시로 사용합니다.
    • POST PATCH는 메시지 바디 내용까지 캐시 키로 사용해야하는데, 구현이 쉽지 않습니다.

2-13. 클라이언트와 서버의 데이터 전송

클라이언트에서 서버로 데이터 전송을 하는데 있어서 크게 두 가지가 있습니다.

  • 쿼리파라미터로 전달하느냐,
  • 메시지 바디로 전달하느냐
    가 있습니다.

쿼리파라미터로 전달하는 방식은 GET메서드인데, 주로 검색어같은 정렬 필터를 전달할 때 사용합니다.

메세지 바디를 통해 전달하는 방식은 POST PUT PATCH이다
예를 들어 회원 가입, 상품주문 같은 리소스 등록, 리소스 변경에 주로 쓰입니다.

클라이언트에서 서버로 데이터를 전송하는 방식은 4가지가 있습니다.

  1. 정적 데이터 조회
  2. 동적 데이터 조회
  3. HTML form을 통한 데이터 전송
  4. HTTP API를 통한 데이터 전송

정적 데이터 조회는 주로 이미지, 정적 텍스트 문서 같은 것을 의미하고,
동적 데이터 조회는 검색, 게시판 목록 조회 같이 전송하는 데이터에 따라 결과가 달라지는 것을 의미합니다.

HTML Form을 통한 데이터 전송은 회원가입, 상품주문과 같이 주로 데이터의 변경이 많이 일어납니다.

HTTP API를 통한 데이터 전송은 HTML Form 데이터 전송 같이 데이터의 변경을 일으키기도하지만, 서버와 서버끼리, 혹은 웹클라이언트와 서버, 또는 앱 클라이언트와 서버끼리 데이터를 주고 받을 때 사용합니다.

정적 데이터 조회시 주로 GET 매핑을 사용하는데, 쿼리파라미터 없이 리소스의 경로로 조회 가능합니다.

  • 전에 언급했다시피 GET에도 메시지 바디를 사용할 수 있긴합니다.

동적 데이터 조회쿼리 파라미터(쿼리스트링)의 값에 따라 결과가 동적으로 나타나는 것을 의미합니다.
주로 검색, 조회 조건을 줄여주는 필터, 조회된 데이터의 정렬 조건에 주로 쓰입니다.

GET 메서드를 주로 사용하며, 쿼리파라미터(쿼리 스트링)을 통해 데이터를 전달합니다.

HTML form 을 통한 데이터 전송은 HTML의 form 태그를 통해 데이터를 전송하는데, 태그로 전달하는 데이터들을 가지고 웹 브라우저가 알아서 자동적으로 메세지 바디를 생성합니다.

그리고 GET을 사용하면 form태그로 전달한 데이터가 쿼리 파라미터를 통해서 전달됩니다.
그것 또한 웹브라우저가 자동으로 생성해줍니다.
GET은 주로 조회에 쓰입니다.
리소스 변경이 일어나는 곳에 사용하면 안 됩니다.

HTML form의 submit을 통한 데이터 전송은 POST매핑을 사용합니다.
HTML Form으로 데이터를 전송하려면 x-www-form-urlencoded 형식으로 데이터를 전송합니다.

HTML Form 으로 데이터를 전송할 때 multipart/form 형식으로 데이터를 전송할 수 있는데,
주로 이미지나 파일을 전송할 때 사용합니다.
그리고 웹브라우저에 명시된 boundary의 표시에 따라, 메시지 바디에서 데이터의 값마다 알ㅇ사ㅓ 경계를 나눕니다.
파일 업로드 같이 바이너리 데이터를 전송시에 사용합니다.
다른 종류의 여러 파일과 폼 데이터의 내용을 동시에 전송가능하기 때문에 multipart라고 합니다.

참고로 HTML Form 데이터 전송은 GET과 POST만 가능합니다.

HTTP API 전송

  • 서버와 서버끼리 통신할 때 사용합니다.

  • 앱 클라이언트가 통신할 때도 사용합니다.

  • 웹 클라이언트에서 HTML Form 전송이 아닌 자바스크립트를 통한 AJAX 통신을 합니다.

  • POST PUT PATCH는 메서지 바디를 통해서 데이터를 전달합니다.

  • GET은 쿼리 파라미터 통해서 데이터를 전달합니다.

  • Header에 컨텐트타입을 주로 json을 사용하는데, 사실상 표준입니다.

HTTP API 설계에는 3가지가 있습니다.
컬렉션, 스토어, HTML FORM입니다.

컬렉션(디렉터리 계층 구조: 슬래시)

  • 컬렉션은 POST를 기반으로 등록합니다.
  • 예시) 회원 관리 API 등록

스토어(파일 관리)

  • PUT을 기반으로 등록합니다.
  • 예시) 정적 파일, 원격 파일을 관리한다.

HTML FORM

  • 예시) 홈페이지 회원을 관리하고, GET과 POST만 지원한다.

※컬렉션이란>
서버가 관리하는 리소스 디렉터리입니다.
서버가 컬렉션을 통해서 리소스 URI를 관리합니다.

※스토어란?
서버가 관리하는 리소스 저장소입니다.
클라이언트가 리소스의 URI를 알고 관리합니다.

※컨트롤 URI
HTTP 메서드의 사용만으로 한계가 있을 때, URI에 동사(행위)를 붙여 리소스를 식별합니다.

2-14. HTTP의 상태코드

클라이언트에서 보낸 요청의 처리 상태를 서버가 응답을 통해서 알려주는 기능을 합니다.

개괄적으론 다음과 같습니다

  • 1xx - information 요청이 처리되어 수신중(잘 안씀)
  • 2xx - Successful 요청 정상 처리
  • 3xx - Redirection 요청을 완료하려면 추가적인 행동 필요
  • 4xx - Client Error 클라이언트 오류, 잘 못된 문법 등으로 서버가 요청을 수행할 수 없음
  • 5xx - Server Error 서버 오류, 서버가 정상 요청을 처리하지 못 함.**

만약 모르는 상태코드가 나타난다면...?

  • 클라이언트는 상위 상태코드로 해석해서 처리하면 됩니다.
  • 미래에 새로운 상태 코드가 추가되어도 클라이언트를 변경하지 않아도 됩니다.

2xx (Successful)

클라이언트의 요청을 성공적으로 처리할 때의 코드입니다.

  • 200 Ok
  • 201 Created
    • 요청에 의해 데이터 생성처리가 되었을 때
  • 202 accepted
    • 요청이 접수되었으나 처리가 완료되지 않았음을 의미합니다.
    • 배치처리에서 사용
    • 예) 요청 후 1시간 뒤에 배치프로세스가 요청을 처리하는 경우가 있습니다.
  • 204 No Content
    • 서버가 요청을 성공적으로 처리했으나 응답 페이로드 본문에 보낼 데이터가 없을 때 사용합니다.
    • 요청을 성공적으로 수행하고 응답에 메세지를 보내지 않아도 될 때 사용합니다.

3xx (Redirection)

요청을 완료하기위해 유저 에이전트의 추가조치가 필요합니다.

  • 300 Multiple choise
  • 301 Moved permanently
  • 302 Found
  • 303 See Other
  • 304 Not Modified
  • 307 Temporary Redirect
  • 308 Permanent Redirect

리다이렉션
웹 브라우저는 3xx 응답결과에 Location 헤더가 있으면 자동으로 Location의 경로로 자동으로 이동합니다.(Redirect)

리다이렉션의 종류

  • 영구 리다이렉션
    • 특정 리소스의 URI가 영구적으로 이동했을 때 사용합니다.
    • 예시)
      • /members가 /user
      • /event /new-evnet
  • 임시 리다이렉션
    • 일시적인 리소스의 변경이 일어났을 때 사용합니다.
    • 예를 들면, 주문 완료후 주문 내역으로 이동 같은 경우가 있습니다.
    • PRG(Post/Redirect/Get)
  • 특수 리다이렉션
    • 결과 대신 캐시를 사용합니다.

영구 리다이렉션

리소스의 URI가 영구적으로 이동했을 때 사용합니다.
원래의 URL을 사용하면 안 됩니다.
301, 308은 검색 엔진에서도 변경을 인지합니다.
/event에서 /new-event로 리다이렉트 되면 브라우저에서 이를 인지합니다.

301 Moved Permanently

리다이렉트시 요청 메서드가 GET으로 바뀌고, 본문이 제거될 수도 있습니다.
(지금은 거의 제거되는데, 원래 이런 의도로 만든 것이 아니었고 브라우저들마다 그렇게 구현했으므로 거의 관행(?)이 되었다고 합니다...;;)

308 Permanently Redirect

301과 기능은 같습니다.
요청시 메서드와 본문을 유지한다.

그러나 잘 쓰지 않는다고 합니다.

308 상태코드를 안쓰는 이유
보통 URI가 영구적으로 바뀌면 전송해야할 데이터도 다 바뀌기 때문이라고 합니다.

일시적인 리다이렉션

리소스의 URI가 일시적으로 변경되었음을 의미합니다.
영구적인 리다이렉션이 아니기 때문에, URL을 유지하면 됩니다.
역시 검색 엔진 등에서 URL을 변경하면 안 됩니다.

302 Found

리다이렉션시 요청 메서드가 GET으로 변하고 본문이 제거될 수 있습니다.

307 Temporary Redirect

302와 같은 기능이지만, 리다이렉션시 요청메서드와 본문을 유지합니다.
(요청메서드를 변경하면 안 됩니다.)

303 See Other

302와 같은 기능이지만, 리다이렉션시 요청 메서드를 명확히 GET으로 변경합니다.

PRG : Post/Redirect/Get

일시적인 리다이렉션의 예시입니다.

POST로 주문 후에 웹 브라우저를 새로고침을 하면, 주문이 중복으로 들어가는데,
왜냐하면 새로 고침은 똑같은 요청을 다시 합니다.
그래서 주문을 중복으로 하는 상황이 발생할 수 있습니다.

이를 방지하는 것이 PRG입니다.

// POST로 주문 후에 주문 결과 화면을 GET메서드로 리다이렉트 합니다.
// 그러면 새로 고침을 해도 결과 화면을 GET으로 조회하게 됩니다.
// 따라서 주문을 중복으로 하는 상황을 방지할 수 있습니다.

다음 그림으로 이해하시면 될 것 같습니다.

만약 이 세 상태 코드 중 어떤 것을 사용해야할지 고민된다면,
자동 리다이렉션시 GET으로 변해도 크게 상관없다면, 그냥 302 상태코드를 사용해도 무방하다고 합니다.

기타 리다이렉션

  • 300 Multiple Choices : 안 씁니다.
  • 304 Not Modified
    • 캐시를 목적으로 사용합니다.
    • 클라이언트에게 리소스가 수정되지 않았음을 알려줍니다.
    • 클라이언트는 로컬 PC에 저장된 캐시를 재사용합니다. (캐시로 리다이렉트 합니다.)
    • 304 응답은 응답에 메시지 바디를 포함하면 안 됩니다.(로컬 캐시를 사용해야하기 때문입니다.)
    • 조건부 GET, HEAD 요청시 사용합니다.

(304는 밑에서 또 다룹니다.)

4xx - Client Error

클라이언트 오류의 상태코드입니다.

클라이언트의 요청에 잘못된 문법 등으로 서버가 요청을 수행할 수 없다는 것을 의미합니다.
4xx대 오류는 오류의 원인이 클라이언트에 있습니다.
그리고 클라이언트가 이미 잘못된 요청, 혹은 잘못된 데이터를 보내고 있기 때문에, 똑같은 재시도가 실패합니다.(반면에 5xx대 오류는 재시도가 성공할 수 있습니다.)

400 - Bad Request

클라이언트가 잘못된 요청을 해서 서버가 요청을 처리할 수 없는 상태입니다.
주로, 요청 구문, 메시지 등등의 오류로 발생합니다.
클라이언트는 요청 내용을 다시 컴토하고 내보내야 합니다.

예를 들면, 요청 파라미터가 잘못되거나, API 스펙이 맞지 않을 때가 있습니다.

401 Unauthorized

클라이언트가 해당 리소스에 대한 인증이 필요합니다.

  • 인증(Authentication)이 되지않았음을 의미합니다.
  • 401 오류 발생시 응답에 WWW-Authenticate 헤더와 함께 인증 방법을 설명합니다.

403 Forbidden

서버가 요청을 이해했지만 승인을 거부한 상태입니다.
주로 인증 자격 증명은 되었지만, 접근 권한이 불충분할 경우에 보냅니다.
예를 들어 사용자가 어드민에 접근했을 경우입니다.

404 Not Found

요청 리소스를 찾다는 의미입니다.
요청 리소스가 서버에 없고, 또한 클라이언트가 권한이 부족한 리소스에 접근할 때 해당 리소스를 숨기고 싶을 때 사용합니다.

참고로 인증과 인가의 차이는 다음과 같습니다.
- 인증(Authentication): 본인이 누구인지 확인하는 것입니다.(로그인)
- 인가(Authorization) 권한부여(ADMIN 권한처럼 특정 리소스에 접근할 수 있는 권한을 가리키는데, 인증이 있어야 인가가 있습니다.)

5xx - Server Error

서버의 문제로 인한 오류 발생 상태코드입니다.
서버에 문제가 있기 때문에 재시도하면 성공할 수도 있습니다.

500 - Internal Server Error

서버 문제로 오류가 발생한 상태입니다.
애매하면 500오류를 내면 됩니다.

503 - Service Unavailable

서비스를 이용 불가하다는 상태입니다.
서버가 일시적인 과부하 또는 예정된 작업으로 잠시 요청을 처리할 수 없을 때 사용합니다.
Retry-After 헤더 필드로 얼마 뒤에 복구되는지 보낼 수도 있습니다.

2-15. HTTP 일반 헤더

다음은 위에서 봤던 내용입니다.

헤더(Heaser)

헤더의 요소로는 field-name이 있는데, 다음과 같습니다.

field-name: OWS(띄어쓰기를 허용하는) 필드에 대한 값
field-name의 특징은 다음과 같습니다.

  • field-name은 대소문자를 구분하지 않습니다.
  • 전송에 필요한 모든 정보를 담습니다.
  • 표준 헤더가 너무 많습니다.
  • 필요시 추가 가능가능하니다.

RFC2616

RFC2616(과거)의 헤더는 4가지 영역이 있었습니다.

  • General 헤더 : 메시지 전체에 적용되는 정보를 담고 있습니다.
  • Request 헤더 : 요청 정보를 담고 있습니다.
  • Response 헤더 : 응답 정보를 담고 있습니다.
  • Entity 헤더 : 엔티티 바디 정보를 담고 있습니다.

RFC2616(과거)의 HTTP BODY는 다음과 같습니다.

  • 메시지 본문(message body)은 엔티티 본문(entity body)을 전달하는데 사용합니다.
  • 엔티티 본문은 요청이나 응답에서 전달할 실제 데이터입니다.
  • 엔티티 헤더는 엔티티 본문의 데이터를 해석할 수 있는 정보를 제공합니다.
    • 데이터 유형(html인지, json인지), 데이터 길이, 압축 정보 등이 있습니다.

그러나, RFC7230~7235가 등장하면서 RFC2616 즉, 위의 내용은 폐기됩니다.

RFC723x의 변화는 다음과 같습니다.

  • 엔티티(Entity)라는 용어대신 표현(Representation)이라는 용어를 사용합니다.
  • Representation = representation Metadata + Representation Data
  • 즉, 표현은 표현 메타데이터 + 표현 데이터를 합친 것입니다.

RFC7230의 HTTP BODY

  • 메세지 본문(message body)을 통해 표현 데이터를 전달합니다.
  • 메세지 본문을 페이로드(payload)라고 합니다.
  • 표현은 요청이나 응답에서 전달할 실제 데이터를 의미합니다.
  • 표현 헤더는 표현 데이터를 해석할 수 있는 정보를 제공합니다.
    • 데이터 유형(html인지, json인지), 데이터 길이, 압축 정보 등이 있습니다.

2-16. 표현

리소스를 넘겨줄 때, 표현 데이터의 형식, 압축 방식, 언어, 길이 등 내용들을 알려주는 특징을 뜻합니다.

  • Content-Type: 표현 데이터의 형식을 의미합니다.
    • 메시지 바디에 들어간 표현 데이터의 형식이 어떤걸지 알려줍니다.
  • Content-Encoding : 표현 데이터의 압축 방식을 의미합니다.
    • 데이터를 읽는 쪽에서 인코딩 헤더의 정보로 압축 해체합니다.
  • Content-Language : 표현 데이터의 자연 언어
    • 자연 언어를 표현하는 것입니다. (한국어인지, 영어인지)
  • Content-Length : 표현 데이터의 길이
    • 바이트 단위를 뜻합니다.
    • (이후에 또 나올 내용이지만,) Transfer-Encoding(전송 코딩)을 사용하면 Content-Length를 사용하면 안 됩니다.

2-17. 협상(콘텐츠 네고시에이션)

클라이언트가 선호하는 표현 요청이라는 의미입니다.
쉽게 말하면, 클라이언트가 서버에게 원하는 대로 표현을 요청하는 겁니다.
그럼 서버는 "반드시가 아니라, 최대한 반영해볼게"라고 하는 것입니다.

4가지 종류가 있습니다.

  • Accept : 클라이언트가 선호하는 미디어 타입을 요청합니다.

  • Accept-Charset : 클라이언트가 선호하는 문자 인코딩을 요청합니다.

  • Accept-Encoding : 클라이언트가 선호하는 압축 인코딩을 요청합니다.

  • Accept-Language: 클라이언트가 선호하는 자연 언어를 요청합니다.

  • 참고로 협상 헤더는 요청시에만 사용합니다.

예를 들어서 Accept-Language를 적용한다고 가정했을 때는 다음과 같습니다.

-- Accept-Language 적용 전,

// 서버는 다중언어를 지원하고, 기본 언어가 영어이고, 한국어를 지원한다(2번째로)고 가정했을 때,
// 클라이언트가 그냥 요청을 하면, 서버의 기본 언어인 영어로 응답을 합니다.

-- Accept-Language 적용 후,

// 가정이 같은 상황에서
// 클라이언트가 한국어로 요청을 하면, 서버는 한국어를 지원하기 때문에, 한국어로 응답합니다.

복잡한 예시의 Accept-Language 적용은 다음과 같습니다.

-- 복잡한 Accept-Language 적용 후,

// 서버는 다중언어를 지원하고, 기본 언어가 독일어이고, 영어를 지원한다(2번째로)고 가정했을 때,
// 클라이언트가 한국어로 요청을 하면, 서버는 한국어가 없기때문에, 독일어를 응답합니다.

이로 인해서 협상에는 우선순위가 필요합니다.

협상과 우선순위 예시 1

Quality Values(q)

  • Quality Values(q)값을 사용합니다.
  • 0 에서 1사이에 클수록 높은 우선순위를 가집니다.
    • 이 값을 생략하면 1입니다.
  • 예를 들어, 다음과 같이 있다고 가정하면, 우선 순위는 다음과 같습니다.
    • Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
        1. ko-KR;q=1(q생략) (한국어)
        1. ko;q=0.9 (한국공통어)
        1. en-US;q=0.8 (US에서 쓰는 영어)
        1. en:q=0.7 (공통 용어)

한국어, 한국공통어 무슨 차인지 모릅니다.. 아신다면 댓글로 알려주세요..;;ㅎㅎ

협상과 우선순위 예시 2

Quality Values(q)

  • 구체적인 것이 우선시됩니다.
  • 예를 들어, 다음과 같이 있다고 가정하면, 우선 순위는 다음과 같습니다.
    • Accept: text/, text/plain, text/plain;format=flowed, `/*`
        1. text/plain;format=flowed
        1. text/plain
        1. text/*
        1. */*

협상과 우선순위 예시 3

Quality Values(q)

  • 구체적인 것을 기준으로 미디어 타입을 맞춥니다.
  • 예를 들어, 다음과 같이 있다고 가정하면, 우선 순위는 다음과 같습니다.
    • Accept: text/;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4,`/*;q=0.5`
Media Type Quality
text/html;level=1 1
text/html 0.7
text/plain 0.3
image/jpeg 0.5
text/html;level=2 0.4
text/html;level=3 0.7

구체적인 것을 먼저 맞추면서 해당되는 것으로 우선순위가 맞춰지게 됩니다.

2-18 전송 방식

  • 단순 전송(Content-Length)

    • 한 번의 요청에 한 번의 응답을 줄때의 방식입니다.
  • 압축 전송(Content-Encoding)

    • 단순 전송의 결과를 압축하여, 용량을 줄이고, 압축 인코딩 정보를 같이 주는 방식입니다.
  • 분할 전송(Transfer-Encoding)

    • 데이터를 chunk(덩어리)단위로 쪼개서 보내는 방식입니다.
    • 분할 전송시엔 Content-Length를 보내면 안 됩니다.
      • chunk 단위로 쪼개서 보내기 때문에, Content-Length가 예상이 어렵습니다.
  • 범위 전송(Range, Content-Range)

    • 만약 어떤 데이터를 받다가 끊겼을 때, 이미 받은 데이터가 절반을 받았다면, 다시 처음부터 다 다운로드하기에는 용량이 크므로 이미 받은 데이터를 제외한 다음 범위를 지정하여 요청하며 전송하는 방식입니다.

2-19 일반 정보

  • From

    • 유저 에이전트의 이메일 정보를 뜻합니다.
    • 일반적으로 잘 사용되진 않습니다만, 검색 엔진 같은 곳에서 주로 사용합니다.
    • 요청에서 사용합니다.
  • Referer

    • 이전 웹 페이지 주소를 의미합니다.
    • 현재 요청된 페이지의 이전 웹 페이지 주소를 저장합니다.
    • A -> B로 이동하는 경우 B를 요청할 때 Referer: A를 포함해서 요청합니다.
    • Referer를 사용하면 유입 경로를 분석 가능합니다.
    • 요청에서 사용
    • 참고로 referer는 단어 referrer의 오타입니다. ㅋㅋ
  • User-Agent
    • 유저 에이전트 애플리케이션 정보
    • 예시) user-agent:Mozila/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36
    • 클라이언트의 애플리케이션 정보를 뜻합니다. 웹 브라우저 정보, 등등
    • 통계 정보를 나타낼 때 많이 사용합니다.
    • 어떤 종류의 브라우저에서 장애가 발생하는지 파악 가능합니다.
    • 요청에서 사용합니다.
  • Server
    • 요청을 처리하는 ORIGIN 서버의 소프트웨어 정보를 뜻합니다.
      • 참고로 ORIGIN 서버란? HTTP 요청을 보내면 중간에 여러 프록시 서버, 캐시 서버를 거쳐가는데, 진짜 요청을 받는 단말 서버를 ORIGIN 서버라고 합니다.
    • 예시) Server: Apache/2.2.2.2(Debian)
    • 응답에서 사용합니다.
  • Date
    • 메시지가 발생한 날짜와 시간을 의미합니다.
    • 예시) Date: Tue, 15 Nov 1994 08:12:31 GMT
    • 응답에서 사용합니다.

2-20 특별한 정보

  • Host

    • 요청한 호스트 정보를 의미합니다.
    • 요청에서 사용합니다.
    • 필수값입니다.
    • 하나의 서버가 여러 도메인을 처리하거나, 하나의 IP 주소에 여러 도메인이 적용되어 있을 때 구분을 해줍니다.
  • Location

    • 페이지 리다이렉션을 의미합니다.
    • 웹 브라우저는 3xx 응답의 결과에 따라 Location 헤더가 있으면, Location 위치로 자동 이동(리다이렉트)합니다.
    • 응답코드 3xx에서 설명합니다.
    • 201(Created): Location 값은 요청에 의해 생성된 리소스 URI입니다.
    • 3xx(Redirection):Location 값은 요청을 자동으로 리디렉션하기 위한 대상 리소스를 가리킵니다.
  • Allow

    • 허용 가능한 HTTP 메서드를 의미합니다.
    • 예를 들어, URL 경로가 있고 허용하는 메서드의 정보는 다음과 같다고 가정했을 때,
      • Allow:GET, HEAD, PUT
      • GET, HEAD, PUT만 지원하는데, POST를 지원하면, 405 에러가 나옵니다.
  • Retry-After

    • 유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간을 뜻합니다.
    • 예시)
      • 503 (Service Unavailable)
        • 이 503 에러가 나왔을 때, 서비스가 언제까지 불능인지 알려줄 수 있는데, 이때 Retry-After를 사용합니다.
    • 날짜를 표기할 수도 있고, 초단위로 표기할 수 도 있습니다.
      • Retry-After:Fri, 31 Dec 1999 23:59:59 GMT (날짜 표기)
      • Retry-After: 120(초단위 표기)

2-21 인증 헤더

  • Authorization
    • 클라이언트 인증 정보를 서버에 전달합니다.
  • WWW-Authenticate
    • 리소스 접근시 필요한 인증 방법을 정의합니다.
    • 401 Unauthorized 응답과 함께 사용합니다.
    • WWW-Authenticate : Newauth realm="apps", type=1, title="Login "apps"", Basic realm="simple" (공식문서 사이트에 가져온 내용인데, 인증을 하려면, 이런 정보를 참고해서 인증데이터를 달라고 서버가 클라이언트의 요청에 반환한다는 의미입니다.)

2-22 쿠키

  • Set-Cooke : 서버에서 클라이언트로 쿠키 전달(응답)합니다.
  • Cookie : 클라이언트가 서버에서 받은 쿠키를 저장하고, HTTP 요청시 서버로 전달합니다.

클라이언트가 로그인을 하고, 서버로 요청을 보내더라도, 서버에선 클라이언트를 구분하지 못 하는데, 그에 대한 대안으로 나온 것이 쿠키입니다.

만약에 쿠키를 미사용한면 대안은 모든 요청에 사용자 정보를 포함하는 것입니다.
그런데 모든 요청과 링크에 사용자 정보를 포함하는 것은 적절치 않습니다.

모든 요청에 정보를 넘기면 다음과 같은 문제가 발생합니다.

  • 모든 요청에 사용자 정보가 포함되도록 개발해야합니다.
  • 브라우저를 완전히 종료하고 다시 열면?
    • 요즘은 웹스토리지에 저장합니다만, 그 또한 구현해야합니다.

쿠키를 사용하면?

// 클라이언트가 서버로 로그인을 하면, 서버는 HTTP 메시지에 Set-Cookie에 user 정보를 저장합니다.
// 로그인 이후 클라이언트는 서버로 요청을 보낼때 서버로부터 받은 Cookie값을 가지고, HTTP 메시지를 만들어 보냅니다.
// 그럼 서버는 요청의 쿠키를 가지고, 사용자가 누구인지 식별합니다.

쿠키는 모든 요청에 쿠키 정보를 자동으로 포함합니다.

쿠키의 사용처

  • 사용자 로그인 세션을 관리할 때, 사용합니다.
    • 세션 저장소에 담아둔 정보를 쿠키에 담아서 보냅니다.
  • 광고 정보 트래킹에 사용합니다.
  • 쿠키 정보는 항상 서버에 전송됩니다.
    • 이로 인해서, 네트워크 트래픽을 추가로 유발합니다.
    • 최소한의 정보만 사용합니다.(세션 id, 인증 토큰 등이 있습니다.)
    • 서버에 전송하지 않고, 웹 브라우저 내부에 데이터를 저장하고 싶으면 웹 스토리지 기능을 사용하면됩니다.
  • 주의할 점은 민감한 데이터는 저장하면 안 됩니다.(ex: 주민번호, 신용카드 정보입니다.)

쿠키의 생명주기

Expires, max-age

  • Set-Cookie: expires=Sat, 25-Dec-2020 04:38:21 GMT
    • 만료일이 되면 쿠키 삭제됩니다.
  • Set-Cookie: max-age:3600(3600초)
    • 0이나 음수를 지정하면 쿠키가 삭제됩니다.
  • 세션 쿠키: 만료 날짜를 생략하면 브라우저 종료시까지만 유지합니다.
  • 영속 쿠키: 만료 날짜를 입력하면 해당 날짜까지만 유지합니다.

쿠키 - 도메인

쿠키에 Domain을 지정해줄 수 있습니다.
왜냐하면, 쿠키하나가 여러 도메인에 접근하는 것도 말이 사실.. 안 되죠..?ㅎㅎ
그래서 Domain을 지정해줄 수 있는데,

도메인을 명시하면,
명시한 문서 기준 도메인 + 서브 도메인을 포함합니다.
예를 들어서,
domain=example.org를 지정해서 쿠키를 생성하면,
example.org는 물론이고, dev.example.org도 쿠키가 같이 접근됩니다.

도메인 명시를 생략하면,
example.org에서 쿠키를 생성하고 domain 지정을 생략하면,
example.org에서만 쿠키를 접근할 수 있고,
dev.example.org는 쿠키가 접근할 수 없습니다.

경로 - Path

예를 들어서 path=/home 을 지정했을 때,

  • 이 경로를 포함한 하위 경로 페이지만 쿠키 접근이 가능합니다.
  • 일반적으로 path=/ (최상위)를 루트로 지정합니다.
  • 예들 들어path=/home를 지정했으면, 다음과 같습니다.
    • /home -> 접근 가능합니다.
    • /home/level1 -> 접근 가능합니다.
    • /home/leve1/leve2 -> 접근 가능합니다.
    • /hello -> 접근 불가능합니다.

보안

쿠키와 관련된 보안은 세 가지가 있습니다.
Secure, HttpOnly, SameSite

Secure

  • 쿠키는 http, https를 구분하지 않고 전송합니다.
  • Secure를 적용하면, https인 경우에만 전송합니다.

HttpOnly

  • XSS 공격을 방지합니다.
  • 자바스크립트에서 접근이 불가합니다(document.cookie)
  • HTTP 전송에만 사용합니다.

SameSite

  • XSRF 공격을 방지합니다.
  • 요청 도메인과 쿠키에 설정된 도메인이 같은 경우만 쿠키를 전송합니다.

개인적인 것인데, SameSite와 SameOrigin을 잘 구분하면 좋겠습니다.
Origin은 ㄹㅇ 핵심 호스트를,
Site가 호스트외 www 같은 하위 경로가 더 붙은 것을 의미합니다.

2-23 캐시 기본 동작

1. 캐시가 없을 때

클라이언트가 사진에 대한 첫 번째 요청시,
서버는 사진을 주는데,
만약 HTTP 헤더의 용량이 0.1MB, HTTP 바디가 1.0MB라고 할 때,
1.1MB를 클라이언트에 줍니다.

클라이언트가 사진에 대한 두 번째 요청시,
서버는 사진을 주는데, 첫 번째 요청과 마찬가지로,
1.1MB를 클라이언트에 줍니다.

  • 데이터가 변경되지 않아도 계속 네트워크를 통해서 데이터를 다운로드 받아야합니다.
  • 인터넷 네트워크는 매우 느리고 비쌉니다.
  • 브라우저 로딩 속도가 느립니다.
  • 사용자가 느린 경험을 겪게 됩니다.

2. 캐시 적용

클라이언트가 사진에 대한 첫 번째 요청시 HTTP헤더에 cache-controle: max-age=60과 같은 정보를 함께 보내게 되는데,
서버는 사진에 대해 응답을 해줍니다.
그러면 클라이언트는 설정한 시간(위의 경우로는 60초)동안 브라우저 캐시에 저장합니다.

크리고 두 번째 요청시, 먼저 캐시에서 찾아보고,
캐시에서 찾았다면, 서버로 요청을 하지않고, 캐시에서 불러옵니다.

  • 캐시 덕분에 캐시 가능 시간동안 네트워크를 사용하지 않아도 됩니다.
  • 비싼 네트워크 사용량을 줄일 수 있습니다.
  • 브라우저 로딩 속도가 매우 빠릅니다.
  • 빠른 사용자 경험을 겪게합니다.

그런데, 만약 캐시의 시간이 초과되었다면?
서버에 다시 요청을 합니다.
그리고 받은 응답 결과를 다시 캐시에 저장합니다.

캐시 시간 초과

  • 캐시 유효 시간이 초과하면, 서버를 통해 데이터를 다시 조회하고, 캐시를 갱신합니다.
  • 이때 다시 네트워크 다운로드가 발생합니다.

2-24 검증 헤더와 조건부 요청1

클라이언트가 캐시 시간이 만료된 후, 똑같은 요청(예들 들어 사진)을 또 서버에 보냈을 때, 응답해줬을 때의 용량을 또 다시 줘야됩니다.
굳이 다시 다운로드 해야될까? 라는 의문점에서 시작되는 개념입니다.

만약, 캐시 유효 시간이 초과해서 서버에 다시 요청하면 다음 두 가지 상황이 나타납니다.

  1. 서버에서 기존 데이터를 변경합니다.
  2. 서버에서 기존 데이터를 변경하지 않습니다.

캐시 시간 초과가 된 상태에서 캐시 만료 후에도 서버에서 데이터를 변경하지 않았을 때, 생각해보면 데이터를 전송하는 대신에 저장해 두었던 캐시를 재사용할 수 있습니다.
단, 클라이언트의 데이터와 서버의 데이터가 같다는 사실을 확인할 수 있는 방법필요합니다.

이 때 검증 헤더를 사용할 수 있습니다.
캐시 시간도 시간이지만, 데이터가 마지막에 수정된 시간을 의미하는 Last-Modified: 헤더를 추가합니다.(표기는 UTC 표기법을 사용합니다.)

캐시 시간, 데이터가 마지막에 수정된 시간 헤더에 설정하고, 첫 번째 1.1MB 용량의 사진을 요청했을 때,
응답 결과를 브라우저 캐시에 저장합니다. 그리고, 데이터 최종 수정일도 함께 저장합니다.

그런데, 두 번째 요청시 캐시 시간이 초과했다고 가정했을 때, 그런데, 캐시에 데이터 최종 수정일에 대한 정보가 있을 때,
서버에서 요청을 받으면, 데이터 최종 수정일을 의미하는 Last-Modified:가 동일하다면, 데이터가 아직 수정되지 않았다는 내용을 메시지에 담아서 응답하는데, 참고로 이 응답에는 HTTP Body가 없습니다.

그리고 응답을 받은 클라이언트는 응답결과를 재사용하고, 헤더의 데이터를 갱신합니다.

이후에 캐시를 보고 데이터를 가져옵니다.

정리하자면,

  • 캐시 유효시간이 초과해도, 서버의 데이터가 갱신되지 않으면, 304 Not Modified + 헤더 메타 정보만 응답합니다.(참고로 바디는 없습니다.)
  • 클라이언트는 서버가 보낸 응답 헤더 정보로 캐시의 메타 정보를 갱신합니다.
  • 클라이언트는 캐시에 저장되어 있는 데이터를 재활용할 수 있습니다.
  • 결과적으로 네트워크 다운로드가 발생하지만, 용량이 적은 헤더 정보만 다운로드 합니다.
  • 매우 실용적인 해결첵입니다.

2-25 검증 헤더와 조건부 요청2

검증 헤더

  • 캐시 데이터와 서버 데이터가 같은지 검증하는 데이터입니다.
  • Lasg-Modified, ETag 가 있습니다.

조건부 요청 헤더

  • 검증 헤더로 조건에 따른 분기를 서버에게 요청합니다.
  • If-Modified-Since: Last-Modified 를 사용합니다.
  • If-None-Match: ETag를 사용합니다.
  • 조건이 만족하면 200 OK를 응답합니다.
  • 조건이 만족하지 않으면 304 Not Modified를 응답합니다.

만약 If-Modified-Since 이후에 데이터가 수정되었으면 어떻게 될까요?
두 경우를 예시를 들면 다음과 같습니다.

  • 데이터 미변경 예시
    • 캐시 : 2020년 11월 10일 10:00:00 vs 서버: 2020년 11월 10일 10:00:00
    • 304 Not Modified, 헤더 데이터만 전송합니다.(BODY를 미포함합니다.)
    • 헤더 0.1M이고, 바디가 1.0M이라면 전송 용량 0.1M입니다.
  • 데이터 변경 예시
    • 캐시 : 2020년 11월 10일 10:00:00 vs 서버: 2020년 11월 10일 11:00:00
    • 200 OK, 모든 데이터를 전송합니다. (BODY를 포함합니다.)
    • 헤더가 0.1M이고, 바디가 1.0M이라면 이 때 전송 용량은 1.1M입니다.

Last-Modified, If-Modified-Since 단점

  • 1초 미만(0.x초) 단위로 캐시 조정이 불가능합니다.(최소가 1초입니다.)
  • 날짜 기반의 로직을 사용합니다.
  • 데이터를 수정해서 날짜가 다르지만, 같은 데이터를 수정해서 데이터 결과가 똑같은 경우에는 인식하지 못합니다.
  • 서버에서 별도의 캐시로직을 관리하고 싶은 경우 예를 들어, 스페이스나 주석처럼 크게 영향이 없는 변경에서 캐시를 유지하고 싶은 경우 사용이 적절하지 않습니다.

이 단점을 보완하기 위해서 나온 것이 ETag입니다.

ETag, If-None-Match

  • Entity Tag라고도합니다.
  • 캐시용 데이터에 임의의 고유한 버전 이름을 달아둡니다.
    • 예를 들면 다음과 같습니다. ETag : "v1.0", ETag: "a2jiodwjekjl3"
  • 데이터가 변경되면 이 이름을 바꾸어서 변경합니다.
    • Hash를 다시 생성합니다.
    • 예를 들면 다음과 같습니다. ETag: "aaaaa" -> ETag: "bbbbb"
  • 진짜 단순하게 ETag만 보내서 같으면 유지하거나, 다르면 다시 받으면 됩니다.

로직은 다음 예시와 같습니다.

// 클라이언트가 서버로 사진을 처음으로 요청합니다.
// 서버는 헤더에 ETag를 붙여서 응답합니다.
// 클라이언트는 웹 브라우저 캐시에 사진을 저장합니다.

// 클라이언트가 서버로 사진을 두 번째 요청합니다.
// 이 때 요청에 If-None-Match 를 달아서 보냅니다.
  // 이 뜻은 "만약 매치가 안 되면"이라는 의미입니다.
// 서버는 요청정보의 If-None-Match 값과 요청 데이터의 ETag를 비교합니다.
  // 데이터가 수정되지 않았다면, 상태코드 304를,
  // 데이터가 수정되었다면 상태코드 200을 보냅니다.

정리하자면,

  • 진짜 단순하게 ETag만 서버에 보내서 같으면 유지하거나, 다르면 다시 받습니다.
  • 캐시 제어 로직을 서버에서 완전히 관리합니다.
  • 클라이언트는 단순히 이 값을 서버에 제공하면 됩니다.(클라이언트는 캐시 매커니즘을 모릅니다.)

2-26 캐시와 조건부 요청 헤더

캐시 제어 헤더

캐시 제어 헤더에는 다음과 같은 것들이 있습니다.

  • Cach-Control : 캐시 제어
  • Pragma : 캐시 제어(하위 호환)
  • Expires : 캐시 유효 기간(하위 호환)

Cach-Control

캐시 지시어(directives)입니다.

  • Cache-Control : max-age
    • 캐시 유효 시간을 의미하고, 초 단위로 입력할 수 있습니다.
  • Cache-Control: no-cache
    • 의미상 캐시하지 않는다는 의미지만, 주의할 점은 **데이터는 캐시해도 되지만, 항상 원(origin) 서버에 검증하고 사용해야합니다.
      • 원 서버라고 표현한 이유는 중간마다 서버가 있기때문에, 원 서버라고 하셨다고 합니다..^^;
  • Cach-Control: no-store
    • 데이터에 민감한 정보가 있으므로 저장하면 안 됩니다.
    • 메모리에서 사용하고 최대한 빨리 삭제를 해야합니다.

Pragma

캐시 제어를 하지만, 하위 호환을 위해 사용합니다.

  • Pragma: no-cache
  • HTTP 1.0에 대한 하위 호환용으로 사용합니다.

Expires

캐시 만료일을 지정할 수 있습니다. Pragma와 같이 HTTP 1.0 하위 호환용으로 사용합니다.

  • 캐시 만료일을 정확한 날짜로 지정합니다.
  • HTTP 1.0부터 사용해왔습니다.
  • 지금은 더 유연한 Cache-Controle: max-age를 권장합니다.
  • Cache-Controle: max-age와 함께 사용하면, Expires는 무시됩니다.

조건부 요청 헤더

조건부 요청 헤더에는 다음과 같은 것들이 사용됩니다.

  • If-Match, If-None-Match

  • If-Modified-Since, If-Unmodified-Since

  • If-Match, If-None-Match 는 ETag 값을 사용합니다.

  • If-Modified-Since, If-Unmodified-Since는 Last-Modified 값을 사용합니다.

2-27 프록시 캐시

한국에 있는 여러 클라이언트가 미국에 있는 원 서버(origin)에 접근할 때, 500ms가 소요된다고 가정했을 때,

프록시 캐시를 도입했다면,
첫 번째 요청시
한국에 있는 여러 클라이언트가 미국에 있는 원 서버(origin)에 접근할 때, 한국 클라이언트와 미국의 서버 중간 어딘가에 프록시 캐시 서버가 있는데,
프록시 캐시 서버가 한국 어딘가에 있다고 가정하면,
프록시 캐시 서버가 없던 경우에 500ms가 들었지만,(예시)
그보다 훨씬 더욱 빠르게 클라이언트는 응답을 받을 수 있습니다.(예를 들면 100ms로.)

프록시 캐시 서버를 두면,
첫 번째 요청자는 원서버로부터 요청을 받아야하기 때문에, 느릴 수 있지만,
두 번째 요청부터는 빠릅니다.
그리고, 프록시 캐시 서버를 공통으로 사용하는 캐시라고 하여, public 캐시라고 하고,
로컬에서 사용하는 캐시를 private 캐시라고 합니다.

Cache-Control

  • Cache-Control: public
    • 응답이 public 캐시에 저장을 허용합니다.
  • Cache-Control: private
    • 응답이 해당 사용자만을 위한 것이므로, private 캐시에 저장해야 합니다.
    • private이 기본값입니다.
  • Cache-Control: s-maxage
    • 프록시 캐시에만 적용되는 max-age입니다.
  • Age: 60(HTTP 헤더)
    • 원 서버(origin)에서 응답 후 프록시 캐시 내에 머문 시간을 뜻합니다.
    • 보통 초단위입니다.

2-28 캐시 무효화

확실한 캐시 무효화를 하는 응답이 있습니다.
다음과 값들을 다 넣어주면 됩니다.

  • Cache-Control: no-cache, no-store, must-revalidate
  • Pragma: no-cache
    • HTTP 1.0 하위 호환을 한다면 넣어줍니다.

Cache-Control: no-cache

  • 의미상 캐시하지 않는다는 의미지만, 주의할 점은 데이터는 캐시해도 되지만, 항상 원(origin) 서버에 검증하고 사용해야합니다.
  • 이름에 주의합니다.

Cach-Control: no-store

  • 데이터에 민감한 정보가 있으므로 저장하면 안 됩니다.
  • 메모리에서 사용하고 최대한 빨리 삭제를 해야합니다.

Cache-Control: must-revalidate

  • 캐시 만료후 최초 조회시 원 서버에 검증해야합니다.
  • 원 서버 접근 실패시 반드시 오류가 발생해야합니다.
    • 504(Gateway Timeout)
  • must-revalidate는 캐시 유효 시간이라면 캐시를 사용합니다.

Pragma: no-cache

  • HTTP 1.0이라면 하위 호환을 위해서 넣어줍니다.

no-cache vs must-revalidate

요청을 하고, 응답하는 과정은 동일하지만,
프록시 서버와 원서버의 네트워크가 단절되었을 때, 어떻게 처리하냐의 차이입니다.

no-cache 같은 경우, 오류페이지를 보여주거나, 오래된 데이터라도 이전 데이터를 보여주는 방식으로 해도되지만,
must-revalidate 같은 경우에는 반드시 504 에러를 보내줘야 합니다.

3. 요약

인프런에서 김영한님의 HTTP 메서드에 대한 강의를 총 정리했습니다...ㅎㅎ
뿌듯합니다.
왠지 모르지만, 정리하면서 들으니깐 요즘은 기억에 더 잘 남네요...
(예전엔 안 그랬는데,,)
여튼 좋습니다..!!

다음엔 다른 컨텐츠를 정리해서 오겠습니다..!

728x90

'CS > 네트워크' 카테고리의 다른 글

외워서 끝내는 네트워크 핵심이론 - 기초  (0) 2023.11.06
Comments