HTTP

HTTP/1.1, HTTP/2 그리고 HTTP/3

5 minute read

그림 이름 바꾸고 다시 넣을것
P-message
= start-line
*( header-field CRLF )
CRLF
[ message-body ]
https://tools.ietf.org/html/rfc7230#section-3
공식 스펙

헤더부분에 임의의 헤더 추가가 가능하다(노란색부분)
helloworld: hihi
=> 로그인 등에도 여기에 유저정보라던지 인터셉터에서 넣어서 전달하거나 이런거 가능

HTTP 메소드의 속성

  • 안전(Safe Methods) : 호출해도 리소스를 변경하지 않는다.
  • 멱등(Idempotent Methods) : f(f(x)) = f(x)
    • 활용 : 자동복구 메커니즘, 서버가 타임아웃 등으로 정상 응답을 못주었을 때, 클라이언트가 같은 요청을 다시 해도 되는가 같은 판단 근거가 된다.
  • 캐시가능(Cacheable Methods) : 응답결과 리소스를 캐시해서 사용해도 되는가?

파일업로드

  • Content-Type: multipart/form-data
    ```
    POST /save HTTP/1.1
    Host: localhost:8080
    Content-Type: multipart/form-data; boundary=——-XXX

——-XXX
Content-Disposition: form-data; name=”username”

——-XXX
Content-Disposition: form-data; name=”file1”; filename=”intro.png”
Content-Type: image/png

1092342abddd21342348989234…
——-XXX—

  
- 끝에는 —이 추가되어야 한다.  
  
HTTP2 3 점유율 그림  
  
  
### 헤더  
header-field = field-name ":" OWS field-value OWS (OWS:띄어쓰기 허용)  
   
### 옛날 RFC2616(1999년 나온거고 2014년 7230~7235로 대체)  
  
![](https://develup4.github.io/bear_to_github_blog_template/assets/images/293c9ea246ff9985dc6f62a650f78986/httpscdn.inflearn.compublicc-326277-attach3cdcf7e5-951d-4a2d-abd4-886f118ba860HTTP%E1%84%8B%E1%85%B0%E1%86%B8_%E1%84%80%E1%85%B5%E1%84%87%E1%85%A9%E1%86%AB%E1%84%8C%E1%85%B5%E1%84%89%E1%85%B5%E1%86%A8_20201226.pdf%203.png)  
  
General 헤더: 메시지 전체에 적용되는 정보, 예) Connection: close  
Request 헤더: 요청 정보, 예) User-Agent: Mozilla/5.0 (Macintosh; ..)  
Response 헤더: 응답 정보, 예) Server: Apache  
Entity 헤더: 엔티티 바디 정보, 예) Content-Type: text/html, Content-Length: 3423  
  
### RFC723X  
- Entity => Representation  
- Representation = representation Metadata + representation Data  
- REST의 영향 아닐까  
  
#### Representation  
Content-Type: 표현 데이터의 형식 Content-Encoding: 표현 데이터의 압축 방식 Content-Language: 표현 데이터의 자연 언어 Content-Length: 표현 데이터의 길이  
  
  
### Content Negotiation  
클라이언트가 선호하는 표현 요청  
Accept: 클라이언트가 선호하는 미디어 타입 전달 Accept-Charset: 클라이언트가 선호하는 문자 인코딩 Accept-Encoding: 클라이언트가 선호하는 압축 인코딩 Accept-Language: 클라이언트가 선호하는 자연 언어  
협상 헤더는 요청시에만 사용  
  
#### Quality Values(협상시 가중치, 생략하면 1이다, 구체적인것이 우선한다)  

GET /event
Accept: text/, text/plain, text/plain;format=flowed, */ => 가장 구체적인 것이 우선한다
Accept-Language: ko-KR, ko;q=0.9, en-US;q=0.8
```

Content-Encoding(전송방법)

일반 => 헤더에 아무것도 없을때 => 그냥전송
Content-Encoding: gzip => 압축전송

범위전송

일반정보

From: 유저 에이전트의 이메일 정보
Referer: 이전 웹 페이지 주소
User-Agent: 유저 에이전트 애플리케이션 정보(어떤 종류의 브라우저에서 장애가 발생하는지 파악가능)
Server: 요청을 처리하는 오리진 서버의 소프트웨어 정보 Date: 메시지가 생성된 날짜

특별한 정보

Host: 요청한 호스트 정보(도메인) - 필수
Location: 페이지 리다이렉션(201의 경우에는 생성된 uri)
Allow: 허용 가능한 HTTP 메서드
Retry-After: 유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간

인증

Authorization: 클라이언트 인증 정보를 서버에 전달 WWW-Authenticate: 리소스 접근시 필요한 인증 방법

Response

상태코드

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

만약 모르는 상태 코드가 나타나면?
• • • •
• • •
클라이언트가 인식할 수 없는 상태코드를 서버가 반환하면? 클라이언트는 상위 상태코드로 해석해서 처리
미래에 새로운 상태 코드가 추가되어도 클라이언트를 변경하지 않아도 됨 예)
299 ??? -> 2xx (Successful) 451 ??? -> 4xx (Client Error) 599 ??? -> 5xx (Server Er

1xx : 거의 사용하지 않음

2xx

201 Created

  • 202 Accepted : 요청이 접속되었으나 처리가 완료되지 않았음
    • 배치 처리 같은 곳에서 사용 (예) 요청 접수 후 1시간 뒤에 배치 프로세스가 요청을 처리함
  • 204 No Content
    • 예를 들어 웹 문서 편집기의 세이브 버튼. 결과 내용없이도 성공을 인식할 수 있다.

3xx Redirection

웹 브라우저는 300대 응답의 결과에 로케이션 헤더가 있으면 로케이션 위치로 자동 이동한다

  • 영구 리다이렉션
    • 301 Moved Permanently : 리다이렉트시 요청 메서드가 겟으로 변하고 본문이 제거될’수도’ 있음
    • 308 Permanent Redirect : 301과 기능은 같지만 메소드와 본문이 유지된다.
  • 일시 리다이렉션 : 리소스의 유알아이가 일시적으로 변경 => 검색엔진 등에서도 저장하지 않는다.
    • 302 Found : 301처럼 GET으로변하고 본문제거가능
    • 307 Temporary Redirect : 308처럼 메소드와 본문 유지
    • 303 See Other 302와 같은데 GET으로변함

    • PRG: Post/Redirect/Get
      • 포스트로 주문 후에 웹 브라우저를 새로고침하면? 새로고침은 다시 요청-=>중복주문 가능
      • PRG를 이용한 일시적인 리다이렉션
        • POST로주문 후에 주문 결과 화면을 GET메소드로 리다이렉트한다.
        • 새로고침해도 GET으로조회될뿐이다.

리다이렉트는 307, 303을 권장하지만 많은 라이브러리들이 302를 기본값으로 사용한다
그래서 GET으로바뀌는 경우를 주의해야한다.

300 Multiple Choices 안쓴다
304 Not Modified
- 캐시를 목적으로 사용한다.
- 클라이언트에게 리소스가 수정되지 않았음을 알려준다. 따라서 클라이언트는 로컬 피씨에 저장된 캐시를 재사용(리다이렉트) 한다
- 304는 응답에 메시지 바디를 포함하면 안된다.

  • 400 Bad Request
    • 클라이언트의 잘못된 요청(파라미터나 에이피아이 스펙에 안맞을때)
  • 401 Unauthorized
    • 응답에 WWW-Authenticate 헤더와 함께 인증방법을 설명해야 한다.
  • 403 Forbidden
    • 인증은 됐지만 인가가 되지 않은 경우
  • 503 Service Unavailable
    • 서비스이용불가
    • Retry-After 헤더 필드로 얼마뒤에 복귀되는지 보낼수도 있음

쿠키(요청 응답 외 카테고리로 뺒)

예) set-cookie: sessionId=abcde1234; expires=Sat, 26-Dec-2020 00:00:00 GMT; path=/; domain=.google.com; Secure

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

특정 도메인 설정
domain=example.org
=> 도메인을 지정해서 쿠키 생성 => 서브 도메인에서도 쿠키 포함
=> 도메인을 생략하면 현재 문서 기준 도메인에서만 적용
path => 하위 경로 페이지에서만 쿠키 접근

Secure => https일때만 전송(HttpOnly나 SameSite(xsrf공격방지) 옵션도 있음)

캐시

데이터가 수정되지 않아야 캐시를 쓸텐데 어떻게 알지?

마지막 수정시간(캐시 저장시간)을 본내고 서버는 저 시간으로 확인해서 수정이 없었다면 스테이터스 코드에서 설명한거처럼 304에 빈 바디로 응답을 준다. 그러면 캐시를 사용하면 된다.

캐시를 사용한다면 헤더만 다운받으면 되므로 효율적

조건부 요청 헤더
검증 헤더로 조건에 따른 분기 If-Modified-Since: Last-Modified 사용 If-None-Match: ETag 사용
조건이 만족하면 200 OK
조건이 만족하지 않으면 304 Not Modified

etag는 entity tag => 고유한 이름을 붙여서 변경됐는지 확인 => 같으면 유지 다르면 다시 받기

받는 정보로 캐시 제어 로직을 서버에서 관리할 수 있다.

Cache-Control

ache-Control 캐시 지시어(directives)

캐시 유효 시간, 초 단위


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

Pragma

캐시 제어(하위 호환)
• •
Pragma: no-cache
HTTP 1.0 하위 호환함을 말함’

Expires

캐시 만료일을 정확한 날짜로 지정하는건데 지금은 잘 안쓴다함(Cache-Control: max-age를 쓰면 무시됨)

프록시 캐시

Cache-Control: public
응답이 public 캐시에 저장되어도 됨
Cache-Control: private
응답이 해당 사용자만을 위한 것임, private 캐시에 저장해야 함(기본값) Cache-Control: s-maxage
프록시 캐시에만 적용되는 max-age
Age: 60 (HTTP 헤더)
오리진 서버에서 응답 후 프록시 캐시 내에 머문 시간(초)

캐시 무효화

Cache-Control: no-cache
데이터는 캐시해도 되지만, 항상 원 서버에 검증하고 사용(이름에 주의!) Cache-Control: no-store
데이터에 민감한 정보가 있으므로 저장하면 안됨
(메모리에서 사용하고 최대한 빨리 삭제)
Cache-Control: must-revalidate
캐시 만료후 최초 조회시 원 서버에 검증해야함
원 서버 접근 실패시 반드시 오류가 발생해야함 - 504(Gateway Timeout) must-revalidate는 캐시 유효 시간이라면 캐시를 사용함
Pragma: no-cache
HTTP 1.0 하위 호환


YouTube

전송할 리소스가 증가했다

(옛날 야후 요즘 야후, 이미지나 동영상)

http/1.0에서는 매 요청마다 커넥션을 열었다 닫았다

1.1에서는 persistent connection 개념이 생겼다

(무선통신 스펙의 keep alive같은 개념)

그리고 http pipelining이라는 개념으로 요청들을 큐에 버퍼링했다가

한번 커넥션열때 같이 처리하는 개념도 있다

위 두개는 그림 첨부하자

근데 파이프라인에서 처리하다가 특정 요청에 문제가 발생하면 뒤 요청들이 줄줄이 처리되지 못하고 블로킹되는 병목 문제가 있다.

이를 막기위해 분산된 도메인으로 요청과 페이지를 나누는 방식등을 쓰기도 하는데,

어찌되었건 아직 문제가

도메인마다 커넥션을 맺고 끊음

상당한 시간과 대역폭을 소모

연결할 수 있는 커넥션 수의 제한

2.0 => 근본적인 해결을 위해 멀티플렉싱(latency 줄이기), 헤더압축(오버헤드 최소화), 서버푸시 기능 지원

멀티플렉싱

=> 프레임(2.0에서의 통신최소단위, 최소 하나의 프레임헤더, 바이너리로 인코딩)

프레임들로 메시지 구성

메시지는 요청 응답의 단위

=> 여기까지는 1.1고 ㅏ크게 다른건 없지만

스트림(양방향 통신을 통해 전달되는 한개 이상의 메시지)이라는 개념이 생겨서

(유튜브 그림들 찾아서 다 첨부하자)

헤더압축은 hpack방식

서버푸시는

기존에 방식이 html 요청, tag파싱, 리소스 재요청(css, js, png등), 완성 이런단계였는데,

그림첨부

한방에 요청으로 가능해짐

이렇게함에도 2.0은 tcp의 한계가 아직 있어서

3.0에서는 udp채용

https://www.youtube.com/watch?v=xcrjamphIp4&list=WL&index=5

근데 http/2를 쓰려면 어떻게 해야하는데?