HTTP Memo

Seoyeon Kim·2023년 5월 10일
1

Chapter 1. Internet Network

IP Packet

한계

  • 대상 서버가 패킷을 받을 수 있는 상태인지 모르고 보낼 수 있다.
  • 중간에 패킷이 소실될 수 있다.
  • 용량이 큰 패킷을 나눠서 보낼 때 전달 순서와 도착 순서가 같지 않을 수 있다.

출발지 IP, 목적지 IP ... 을 갖고 있다.

TCP & UDP

TCP (Transmission Control Protocol)

출발지 PORT, 목적지 PORT, 전송 제어, 순서, 검증 정보 ... 를 갖고 있다.

  1. 먼저 연결한 다음에 메시지를 보낸다 : 대상 서버가 패킷을 받을 수 있는 상태인지 모르고 보내던 IP의 한계 극복
  2. 중간에 소실된 경우 알 수 있다 : 중간에 패킷이 소실되었는지 확인이 불가하던 IP의 한계 극복
  3. 순서를 보장한다 : 올바른 데이터를 전달할 수 있다.

UDP (User Datagram Protocol)

생략

Port

항구라는 의미.

서버 안에서 동작하는 애플리케이션을 구분하기 위해 사용한다.
즉, PORT를 통해 같은 IP 내에서 프로세스를 구분한다.

DNS (Domain Name System)

기억하기 어렵고 변경 가능성이 있는 IP를 대신하여 Domain을 등록하여 사용한다.


Chapter 2. URI & Web Browser

URI (Uniform Resource Identifier)

  • resource locator : URL
  • resource name : URN

scheme://[userinfo@]host[:port][/path][?query][#fragment]

  1. scheme : 주로 프로토콜을 사용
  2. host : domain or IP
  3. port : 접속 포트
  4. path : 리소스 경로, 계층적 구조
  5. query : key=value 형태, ?로 시작 &으로 추가
  6. fragment : html 내부 북마크에 사용, 서버에 전송하지 않음

웹 브라우저 요청 흐름

  1. DNS 조회하여 IP를 찾는다.
  2. 웹 브라우저가 HTTP Request 메시지를 만든다.
  3. SOCKET 라이브러리를 통해 전달한다.
  4. HTTP 메시지를 포함하는 TCP/IP 패킷을 생성한다.
  5. 요청 패킷을 전달한다.
    ...

Chapter 3. HTTP

HyperText Transfer Protocol

HTTP/1.1 1997년 : 가장 많이 사용되며, 대부분의 스펙이 들어가 있다.
이후에 개발된 HTTP/2나 HTTP/3는 주로 성능 개선에 초점이 맞춰져 있다.

기반 프로토콜

  • TCP : HTTP/1.1, HTTP/2
  • UDP : HTTP/3

Stateful vs Stateless

Stateless

서버가 클라이언트의 상태를 유지하지 않는다.
무상태는 응답 서버를 쉽게 변경할 수 있다. 즉, 서버 증설을 쉽게 할 수 있다.
상태 유지는 최소한으로 사용하는 것이 좋다.

Connectionless & Persistent Connections

HTTP는 기본적으로 연결을 유지하지 않는 모델이다. 즉, 요청을 받고 응답을 전달한 뒤 연결을 끊는다.
연결을 유지하는 경우, 클라이언트가 일하지 않아도 서버는 연결을 계속 유지하며 자원을 소모하게 된다.

한계

  1. TCP/IP 연결을 새로 맺어야 한다. 즉, 3 way handshake 시간이 추가된다.
  2. html, js, css, img 등 많은 자원을 다시 함께 다운로드 한다.

해결

지금은 HTTP Persistent Connections로 문제를 해결

HTTP Message

구조

  1. start-line (요청 메시지 = request-line / 응답 메시지 = status-line)
  2. header
  3. empty line (CRLF)
  4. message body

참고 절대 경로 : "/"로 시작하는 경로


Chapter 4. HTTP Method

리소스와 행위를 분리하자.

  • URI는 리소스만 식별
  • 행위는 HTTP Method로 구분

주요 메서드

  • GET : 리소스 조회
  • POST : 요청 데이터 처리, 주로 등록에 사용
  • PUT : 리소스를 대체, 해당 리소스가 없으면 생성
  • PATCH : 리소스 부분 변경
  • DELETE : 리소스 삭제

GET & POST

GET를 사용하는 경우

조회

POST를 사용하는 경우

  1. 새로운 리소스 생성 및 등록
  2. 요청 데이터 처리 ex) 주문 → 결제완료 → 배달시작 → 배달완료 (POST의 결과로 새로운 리소스가 생성되지 않을 수도 있다)
  3. 다른 메서드로 처리하기 애매한 경우

PUT & PATCH & DELETE

PUT

  • 리소스를 완전히 대체한다.
  • 클라이언트가 리소스의 위치를 알고 URI를 지정한다. (POST와 차이점)

PATCH

  • 리소스를 부분 변경한다. (PUT과 차이점)

DELETE

  • 리소스를 제거한다.

Safe & Idempotent & Cacheable

안전 (Safe)

호출해도 리소스를 변경하지 않는다. ex) GET, HEAD

멱등 (Idempotent)

몇 번 호출하든 결과는 항상 동일하다. ex) GET, PUT, DELETE

POST, PATCH는 비멱등하다

캐시 가능 (Cacheable)

응답 결과 리소스를 캐시해서 사용해도 되는가? ex) GET, HEAD

HTTP METHOD 활용

클라이언트에서 서버로 데이터 전송하는 방식 2가지

  1. 쿼리 파라미터를 통한 데이터 전송
  2. 메시지 바디를 통한 데이터 전송

클라이언트에서 서버로 데이터 전송하는 상황 4가지

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

API 설계 - POST 기반 등록

  • 회원 목록 /members : GET
  • 회원 등록 /members : POST
  • 회원 조회 /members/{id} : GET
  • 회원 수정 /members/{id} : PATCH, PUT, POST
  • 회원 삭제 /members/{id} : DELETE

POST - 신규 자원 등록 특징

  • 클라이언트는 등록될 리소스의 URI를 모른다.
  • 서버가 새로 등록된 리소스 URI를 생성한다.
  • 컬렉션(Collection) : 서버가 관리하는 리소스 디렉토리

API 설계 - PUT 기반 등록

  • 파일 목록 /files : GET
  • 파일 조회 /files/{filename} : GET
  • 파일 등록 /files/{filename} : PUT
  • 파일 삭제 /files/{filename} : DELETE
  • 파일 대량 등록 /files : POST

PUT - 신규 자원 등록 특징

  • 클라이언트가 리소스 URI를 알고 있어야 한다.
  • 클라이언트가 직접 리소스의 URI를 지정한다.
  • 스토어(Store) : 클라이언트가 관리하는 리소스 저장소

대부분 POST 기반의 Collection 방식을 사용한다.

컨트롤 URI

HTML FORM은 GET, POST만 지원하므로 제약이 있음
이런 제약을 해결하기 위해 동사로 된 리소스 경로를 사용 → 컨트롤 URI
HTTP 메서드로 해결하기 애매한 경우 사용
ex) POST의 /new, /edit, /delete

참고하면 좋은 URI 설계 개념

  • 문서(document)
    - 단일 개념(파일 하나, 객체 인스턴스, 데이터베이스 row)
    • ex) /members/100, /files/star.jpg
  • 컬렉션(collection)
    - 서버가 관리하는 리소스 디렉터리
    • 서버가 리소스의 URI를 생성하고 관ㄹ
    • ex) /members
  • 스토어(store)
    - 클라이언트가 관리하는 자원 저장소
    • 클라이언트가 리소스의 URI를 알고 관리
    • ex) /files
  • 컨트롤러(controller) == 컨트롤 URI
    - 문서, 컬렉션, 스토어로 해결하기 어려운 추가 프로세스 실행
    • 동사를 직접 사용
    • ex) /memebers/{id}/delete

Chapter 5. HTTP Status

클라이언트가 인식할 수 없는 상태 코드를 서버가 반환한 경우, 상위 상태 코드로 해석해서 처리한다
ex) 299 → 2xx (Successful)
ex) 451 → 4xx (Client Error)

1xx (Informational)

요청이 수신되어 처리중이라는 의미
거의 사용하지 않아 생략

2xx (Successful)

요청 정상 처리

  • 200 OK : 요청 성공
  • 201 Created : 요청 성공 + 새로운 리소스가 생성됨 (생성된 리소스는 응답의 Location 헤더 필드로 식별)
  • 202 Accepted : 요청이 접수되었으나 처리가 완료되지 않았음
  • 204 No Content : 서버가 요청을 성공적으로 수행했지만 응답 Payload 본문에 보낼 데이터가 없음

3xx (Redirection)

요청을 완료하려면 추가 행동이 필요

redirection : 웹 브라우저는 3xx 응답의 결과에 Location 헤더가 있으면, Location 위치로 자동 이동

Redirection 종류

  • 영구 리다이렉션 : 특정 리소스의 URI가 영구적으로 이동
    - ex) /members → /users
    • ex) /event → /new-event
  • 일시 리다이렉션 : 일시적인 변경
    - 주문 완료 후 주문 내역 화면으로 이동
    • PRG : Post/Redirect/Get
  • 특수 리다이렉션
    - 결과 대신 캐시를 사용하라고 전달

영구 리다이렉션

  • 리소스의 URI가 영구적으로 이동
  • 원래의 URL를 사용하지 않음
  • 검색 엔진 등에서 URL을 반영
  • 301 Moved Permanently
    - 리다이렉트 시 요청 메서드가 GET으로 변하고 본문이 제거될 수 있음
  • 308 Permanent Redirect
    - 301과 기능은 같음
    • 리다이렉트 시 요청 메서드와 본문 유지

일시적 리다이렉션

  • 리소스의 URI가 일시적으로 변경
  • 따라서 검색 엔진 등에서 URL을 변경하면 안됨
  • 302 Found
    - 리다이렉트 시 요청 메서드가 GET으로 변하고 본문이 제거될 수 있음
  • 307 Temporary Redirect
    - 302와 기능은 같음
    • 리다이렉트 시 요청 메서드와 본문 유지
  • 303 See Other
    - 302와 기능은 같음
    • 리다이렉트 시 요청 메서드가 GET으로 변경

기타 리다이렉션

  • 300 Multiple Choices : 미사용
  • 304 Not Modified : 클라이언트에게 리소스가 수정되지 않았음을 알려준다. 따라서 클라이언트는 캐시를 재사용 한다. 응답에 메시지 바디를 포함하지 않는다.

4xx (Client Error)

클라이언트 오류, 잘못된 문법 등으로 서버가 요청을 수행할 수 없음

  • 400 Bad Request : 클라이언트의 잘못된 요청을 처리할 수 없음
  • 401 Unauthorized : 클라이언트가 해당 리소스에 대한 인증이 필요함
  • 403 Forbidden : 서버가 요청을 이해했지만 승인을 거부함, 접근 권한이 불충분한 경우
  • 404 Not Found : 요청 리소스를 찾을 수 없음, 요청 리소스가 서버에 없음

5xx (Server Error)

서버 오류, 서버가 요청을 정상적으로 처리하지 못함

  • 500 Internal Server Error : 서버 내부 문제로 오류 발생
  • 503 Service Unavailable : 서비스 이용 불가, 서버가 일시적인 과부하 또는 예정된 작업으로 잠시 요청을 처리할 수 없음

Chapter 6. HTTP Header Part 1

1999년 RFC2616 : 폐기됨
2014년 RFC7230~7235 등장

RFC723x 변화

  • 엔티티 → 표현 (Entity → Representation)
  • Representation = Representation Metadata + Representation Data
  • 표현 = 표현 메타데이터 + 표현 데이터

HTTP BODY - RFC7230

  • 메시지 본문(message body)을 통해 표현 데이터 전달
  • 메시지 본문 = 페이로드(payload)
  • 표현은 요청이나 응답에서 전달할 실제 데이터
  • 표현 헤더표현 데이터를 해석할 수 있는 정보를 제공 ex) 데이터 유형, 데이터 길이, 압축 정보 등

예를 들어 회원이라는 리소스는 html로 표현해서 전달할 수도 있고, json으로 표현해서 전달할 수도 있다. 이와 같은 이유로 표현이라고 부르도록 정의했다.

Representation Header

  • Content-Type : 표현 데이터의 형식, 미디어 타입, 문자 인코딩 ex) text/html; charset=utf-8
  • Content-Encoding : 표현 데이터의 압축 방식, 데이터를 전달하는 곳에서 압축 후 인코딩 헤더 추가, 데이터를 읽는 쪽에서 인코딩 헤더의 정보로 압축 해제
  • Content-Language : 표현 데이터의 자연 언어 ex) ko, en, en-US
  • Content-Length : 표현 데이터의 길이, 바이트 단위

Content Negotiation 협상

클라이언트가 선호하는 표현 요청
협상 헤더는 요청 시 사용

  • Accept : 클라이언트가 선호하는 미디어 타입 전달
  • Accept-Charset : 클라이언트가 선호하는 문자 인코딩
  • Accept-Encoding : 클라이언트가 선호하는 압축 인코딩
  • Accept-Language : 클라이언트가 선호하는 자연 언어

전송 방식

  • 단순 전송 : 한번에 요청하고 한번에 받음
  • 압축 전송 : 압축해서 전송, Content-Encoding에 압축 형식 표기
  • 분할 전송 : Transfer-Encoding (Content-Length를 사용하면 안됨)
  • 범위 전송 : Range - Content-Range 사용

일반 정보

  • From : 유저 에이전트의 이메일 정보, 요청에서 사용
  • Referer : 이전 웹 페이지 주소, 요청에서 사용 (referer는 단어 referrer의 오타)
  • User-Agent : 클라이언트의 애플리케이션 정보, 어떤 종류의 브라우저에서 장애가 발생하는지 파악 가능, 요청에서 사용
  • Server : 요청을 처리하는 ORIGIN 서버의 소프트웨어 정보, 응답에서 사용
  • Date : 메시지가 발생한 날짜와 시간, 응답에서 사용

특별한 정보

  • Host : 요청한 호스트 정보, 필수, 요청에서 사용
  • Location : 201의 경우 Location 값은 요청에 의해 생성된 리소스 URI, 3xx의 경우 Location 값은 요청을 자동으로 리다이렉션하기 위한 대상 리소스를 가리킴
  • Allow : 허용 가능한 HTTP 메서드, 405에서 응답에 포함해야 함
  • Retry-After : 서비스가 언제까지 불능인지 알려줄 수 있음

인증

  • Authorization : 클라이언트 인증 정보를 서버에 전달
  • WWW-Authenticate : 리소스 접근 시 필요한 인증 방법 정의, 401 Unauthorized 응답과 함께 사용

쿠키

  • Set-Cookie : 서버에서 클라이언트로 쿠키 전달(응답)

  • Cookie : 클라이언트가 서버에서 받은 쿠키를 저장하고, HTTP 요청 시 서버로 전달

  • 사용처 : ex) 사용자 로그인 세션 관리, 광고 정보 트래킹

  • 쿠키 정보는 항상 서버에 전송됨
    - 네트워크 트래픽 추가 유발

    • 최소한의 정보만 사용(세션 id, 인증 토큰)
    • 서버에 전송하지 않고, 웹 브라우저 내부에 데이터를 저장하고 싶으면 웹 스토리지 (localStorage, sessionStorage) 참고
  • 주의 : 보안에 민감한 데이터는 저장하면 안됨

생명주기

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

도메인

  • 명시한 경우 : 명시한 문서 기준 도메인 + 서브 도메인 포함
    - ex) domain=example.org를 지정해서 쿠키 생성
    - example.org는 물론이고
    - dev.example.org도 쿠키 접근
  • 생략한 경우 : 현재 문서 기준 도메인만 적용
    - ex) example.org에서 쿠키를 생성하고 domain 지정을 생략
    - example.org에서만 쿠키 접근
    - dev.example.org는 쿠키 미접근

경로

  • ex) path=/home
  • 이 경로를 포함한 하위 경로 페이지만 쿠키 접근
  • 일반적으로 path=/ 루트로 지정

보안

  • Secure
    - 쿠키는 http, https를 구분하지 않고 전송
    • Secure를 적용하면 https인 경우에만 전송
  • HttpOnly
    - XSS 공격 방지
    • 자바스크립트에서 접근 불가(document.cookie)
    • HTTP 전송에만 사용
  • SameSite
    - XSRF 공격 방지
    • 요청 도메인과 쿠키에 설정된 도메인이 같은 경우만 쿠키 전송

Chapter 7. HTTP Header Part 2

캐시 기본 동작

캐시가 없을 때

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

캐시 적용 시

최초 요청 시 받은 응답 결과를 캐시에 저장 → 두 번째 요청 시 캐시에서 먼저 찾는다.

  • 캐시 덕분에 캐시 가능 시간동안 네트워크를 사용하지 않아도 된다.
  • 비싼 네트워크 사용량을 줄일 수 있다.
  • 브라우저 로딩 속도가 매우 빠르다.
  • 빠른 사용자 경험
  • 캐시 유효 시간이 초과하면, 서버를 통해 데이터를 다시 조회하고 캐시를 갱신한다.
  • 이때 다시 네트워크 다운로드가 발생한다.

검증 헤더와 조건부 요청

  • 검증 헤더
    - 캐시 데이터와 서버 데이터가 같은지 검증하는 데이터
    • Last-Modified, ETag
  • 조건부 요청 헤더
    - 검증 헤더로 조건에 따른 분기
    • If-Modified-Since : Last-Modified 사용
    • If-None-Match : ETag 사용
    • 조건을 만족하면 200 OK
      - 조건을 만족하지 않으면 304 Not Modified

캐시 시간 초과

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

  1. 서버에서 기존 데이터를 변경함
  2. 서버에서 기존 데이터를 변경하지 않음

요청 시 If-Modified-Since : 조건부 요청
응답 시 Last-Modified : 검증 헤더

데이터가 아직 수정되지 않은 경우 → 304 Not Modified와 Last-Modified 응답 (HTTP Body가 없음) → 응답 결과를 재사용, 헤더 데이터 갱신

정리

  • 캐시 유효 시간이 초과해도, 서버의 데이터가 갱신되지 않으면 304 Not Modified + 헤더 메타 정보만 응답(Body X)
  • 클라이언트는 서버가 보낸 응답 헤더 정보로 캐시의 메타 정보를 갱신
  • 클라이언트는 캐시에 저장되어 있는 데이터 재활용
  • 결과적으로 네트워크 다운로드가 발생하지만 용량이 적은 헤더 정보만 다운로드
  • 실용적인 해결책

If-Modified-Since, Last-Modified 단점

  • 1초 미만 단위로 캐시 조정이 불가
  • 날짜 기반의 로직 사용
  • 데이터를 수정해서 날짜가 다르지만, 같은 데이터를 수정해서 데이터 결과가 똑같은 경우
  • 서버에서 별도의 캐시 로직을 관리하고 싶은 경우 ex) 스페이스나 주석처럼 크게 영향이 없는 변경에서 캐시를 유지하고 싶은 경우

ETag, If-None-Match

  • ETag(Entity Tag)
  • 캐시용 데이터에 임의의 고유한 버전을 설정함
    - ex) ETag: "v1.0", ETag: "asdkjweo32"
  • 데이터가 변경되면 이 이름을 변경함 (Hash를 다시 생성)
    - ex) ETag: "aaaaa", ETag: "bbbbb"
  • 즉, ETag만 보내서 같으면 유지, 다르면 다시 받기
  • 캐시 제어 로직은 완전히 서버에서 관리
  • 클라이언트는 단순히 이 값을 서버에 제공(클라이언트는 캐시 메커니즘을 모름)
  • ex) 서버는 배타 오픈 기간인 3일 동안 파일이 변경되어도 ETag를 동일하게 유지, 애플리케이션 배포 주기에 맞춰 ETag 모두 갱신

캐시와 조건부 요청 헤더

캐시 제어 헤더

  • Cache-Control : 캐시 제어
  • Pragma : 캐시 제어(HTTP 1.0 하위 호환)
  • Expires : 캐시 유효 기간(HTTP 1.0 하위 호환, 지금은 더 유연한 Cache-Control : max-age 권장)

Cache-Control

캐시 지시어(directives)

  • Cache-Control : max-age - 캐시 유효 시간, 초 단위

  • Cache-Control : no-cache - 데이터는 캐시해도 되지만, 항상 origin 서버에 검증하고 사용

  • Cache-Control : no-stroe - 데이터에 민감한 정보가 있으므로 저장하면 안됨(메모리에서 사용하고 최대한 빨리 삭제)

  • Cache-Control : must-revalidate - 캐시 만료 후 최초 조회 시 origin 서버에 검증해야 함

  • Cache-Control : public - 응답이 public 캐시에 저장되어도 됨 ex) 프록시 캐시

  • Cache-Control : private - 응답이 해당 사용자만을 위한 것, private 캐시에 저장해야 함(기본 값)

  • Cache-Control : s-maxage - 프록시 캐시에만 적용되는 max-age

  • Age(HTTP Header) : 60 - origin 서버에서 응답 후 프록시 캐시 내에 머문 시간(초)

검증 헤더와 조건부 요청 헤더 정리

  • 검증 헤더 (Validator)
    - ETag
    • Last-Modified
  • 조건부 요청 헤더
    - If-Match, If-None-Match : ETag 값 사용
    • If-Modified-Since, If-Unmodified-Since : Last-Modified 값 사용

캐시 무효화

확실한 캐시 무효화 응답

아래의 내용을 모두 넣어야 함

  • Cache-Control : no-cache, no-store, must-revalidate
  • Pragma : no-cache (HTTP 1.0 하위 호환을 위해)

no-cache 사용 시 origin 서버에 접근 불가한 경우, 캐시 서버 설정에 따라 캐시 데이터를 반환할 수 있다. 그러나 must-revalidate는 origin 서버에 접근할 수 없는 경우, 항상 오류를 발생한다. (504 Gateway Timeout)

2개의 댓글

comment-user-thumbnail
2023년 5월 15일

요즘 포스팅 폼 미쳤다...

1개의 답글