HTTP

Khan·2024년 10월 30일
0

http?

웹 브라우저와 웹 서버가 통신하는 절차와 형식을 규정한 것.

특징

  • 확장이 쉽다
    • 헤더에 언제든 새로운 기능을 추가할 수 있음
    • 서버 개발자와 클라이언트 개발자가 합의만 하면 커스텀 헤더를 통해 필요한 정보를 주고 받을 수 있음
  • Connectionless
    • 클라이언트와 서버가 연결 후 한번 요청과 응답을 주고 받으면 연결을 지속하지 않는다.
      • HTTP는 불특정 다수와의 통신을 위해 만들어졌기 때문에 다수의 클라이언트와의 연결을 서버가 계속 유지하는 것은 부담이 되기 때문.
    • 그러나 동일한 클라이언트의 모든 요청마다 매번 새 연결을 시도, 해제해야하므로 비효율적이다
      • 요청헤더에 Connection: keep-alive 속성 사용!
        • http 1.0에서는 ‘Connection: close’가 디폴트
        • http 1.1에서는 ‘Connection: keep-alive’가 디폴트
  • Stateless
    • 서버는 클라이언트의 상태를 유지하지 않습니다.
    • 누가 언제 요청을 하더라도 요청이 같으면 결과가 같음.
    • 즉, 각 클라이언트에 맞는 리소스를 선별적으로 보내주는 것은 기본적으로 불가능함.
      • 이를 해결하기 위해 쿠키, 세션, 토큰등을 사용. (쿠키도 헤더를 바탕으로 만들어짐.)

HTTP 메시지

HTTP 메시지 구조
start-line 시작 라인
header 헤더
empty line 공백 라인
body
<StartLine> GET /index.html HTTP/1.1 </StartLine>
<Header>
	Host: www.example.com
	User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
 				AppleWebKit/537.36 (KHTML, like Gecko)
				Chrome/91.0.4472.124 Safari/537.36
	Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
	Accept-Language: en-US,en;q=0.5
	Accept-Encoding: gzip, deflate, br
	Connection: keep-alive
</Header>
**<Blank>**
<Body>
</Body>

StartLine

StartLine은 꼭 한 줄로만 작성되어야 한다. 절대 두 줄은 안 됨!

  • 요청 메시지

    • HTTP 메서드 : 서버가 수행해야 할 동작 지정
    • 요청 대상 : 절대경로 = "/" 로 시작하는 경로
    • HTTP 버전
  • 응답 메시지

    • HTTP 버전
    • HTTP 상태 코드
    • 상태에 대한 문구 : 사람이 이해할 수 있는 상태 코드 설명 글
  • HTTP 전송에 필요한 모든 부가정보
  • 위의 예시를 보면 Host, User-Agent, Accept 등등
  • Header에 들어갈 수 있는 정보는 수 백개 정도는 되고 그것들에 대한 정보는 여기서 참조
  • 중요한 헤더 몇 개만 예시:
    • Authorization: 사용자 인증 토큰, credentials 등을 전달. 주로 JWT 같은 걸 전달할 때 사용
    • Cookie: 클라이언트 로컬(메모리 혹은 보조기억장치)에 저장되는 키-값 형태의 데이터 파일
    • Accept: 요청을 보낸 클라이언트가 받을 수 있는 컨텐츠의 타입을 명시
    • Accept-Language: 선호 언어를 우선순위에 따라 지정
    • Origin: 요청이 시작된 출처
    • User-Agent: 클라이언트 정보
    • Content-length: 응답 길이
    • Content-Type: 응답 타입

Body

  • 실제 전송할 데이터
  • ex) HTML 문서, 이미지, 영상, JSON 등등

속도와 효율을 위한 노력들

캐시 (1.0)

  • 문제:
    • 접속할 때마다 파일을 다시 다운로드 하는 것은 부담
    • Contents가 바뀌지 않았다면 로컬에 저장된 것을 재사용하고 싶다
  • 해결 방안
    • Http1.0 시절에는 정적 컨텐츠 위주. → 콘텐츠가 갱신 됐는지만 체크하면 됨!
  • 작동 방식:
    1. 서버가 응답을 할 때 헤더에 Last-Modified에 수정 일시를 기록해서 응답함 (클라이언트는 캐시)
    2. 다음에 클라이언트가 재요청을 하면 last-modified에 있던 기록을 바탕으로 If-Modified-Since를 붙여서 요청함
    3. 만약 바뀐 것이 없다면 304 (Not modified)로 응답
    4. 바뀌었다면 200 응답, 다시 캐시

  • 다시 문제 및 해결 방안:
    • 근데 이러면 요청은 어쨌든 보내야 되잖아!
    • 그래서 Expires라는 헤더도 있습니다!
    • Expires 헤더에 설정된 기한 내라면 아예 서버에 요청을 보내지 않는다

캐시 (1.1)

  • 문제:
    • 근데 단순히 last-modified나 expires처럼 날짜, 시간으로만 캐시를 컨트롤하기는 어려워
    • 데이터가 복잡해지면서 캐시 여부가 단순 시간에 종속적이지 않기 때문
  • 해결 방안:
    • 파일 자체의 해시 값을 비교하기로 함 → Etag
      • Etag: 리소스의 특정 버전에 대한 고유한 식별자
  • 작동 방식:
    1. 서버는 리소스에 대한 ETag 값을 생성 (보통 컨텐츠의 해시값)
    2. 클라이언트는 요청 시 'If-None-Match' 헤더에 가지고 있는 ETag 값을 포함
    3. 서버는 현재 리소스의 ETag와 비교하여 변경 여부를 판단
    4. 일치하면 304 Not Modified 응답, 불일치하면 200 OK와 새로운 컨텐츠 전송
    • max-age: 캐시의 유효 시간
    • no-cache: 캐시는 저장하지만 항상 서버에 재검증
    • no-store: 캐시를 저장하지 않음
    • private: 브라우저만 캐시 가능
    • public: 중간 프록시도 캐시 가능

캐시 (2)

  • 문제:
    • http 1.0에는 요청에 대한 응답을 받아야 다음 요청을 할 수 있었음
    • Http 1.1로 들어오면서 pipelining이라는 기법을 사용해 요청을 연속적으로 보내 지연시간을 단축
    • 그러나 여전히 앞에 응답이 오래걸리면 뒤의 응답도 같이 지연되는 문제가 있었음
    • HOLB (Head Of Line Blocking)라고 부르는 문제
  • 해결 방안
    • 파이프라이닝은 http2에서 스트림이라는 구조로 다시 태어남!
    • 1.1까지 메시지를 기반으로 통신하던 것에 프레임이라는 새로운 단위가 추가되었음
    • 순차적인 처리가 필수적이었던 1.1에 반해 2는 순서가 상관없게 되었다고 함
profile
끄적끄적 🖋️

0개의 댓글