본문 바로가기

그 외

HTTP 스펙과 버전

728x90

HTTP(HyperText Transfer Protocol)란

웹 상에서 서버와 클라이언트간 통신의 하이퍼텍스트에 대한 프로토콜로, 하이퍼 텍스트는 웹에 표시되는 컨텐츠들을 말한다.

 

osi 7계층과 tcp/ip 4계층의 Application 계층에 해당하고, 신뢰성 있는 연결을 사용하기 때문에

통신을 위한 전송 프로토콜로 TCP를 사용한다. 따라서 TCP에 영향을 많이 받았다.

 

간단히 TCP (Transmission Control Protocol)에 대해

서버와 클라이언트간 신뢰성에 중심을 둔 전송 프로토콜.

3-way handshake로 연결, 4-way handshake로 연결 해제, 데이터 전송할때 응답에 따라 *패킷을 더 보내거나 안보내기 때문에 신뢰성이 높다.

 

*패킷 : 네트워크 데이터 블록

 

TCP와 UDP를 비교하자면

UDP(User Datagram Protocol)의 경우 양방향의 TCP와 다르게 데이터를 무조건 보내기 떄문에 비교적 신뢰성이 떨어지지만, 데이터 손실이 나도 패킷을 재전송 하지 않기 때문에 속도가 빠르다.

 

 

HTTP 요청/응답 스펙

http 요청과 응답 정보에 대해서는 크롬의 개발자도구나 fiddler 등으로 확인할 수 있다.

 

요청 Raw 정보

요청 구조

Reqeust-Line
Header

Body

 

Reqeust-Line

맨 첫줄 Request-Line을 보면 요청 메서드 (GET, POST, PUT, DELETE 등)와 요청URI, HTTP 버전으로 구성되어있다.

 

요청 메서드 종류

  • GET - 리소스 요청 : URI로 서버의 리소스(데이터)를 요청
  • HEAD - 문서 정보 요청 : GET과 동일한 요청을 하지만 본문(body)없이 응답을 받는다.
  • POST : 서버에 요청 바디에 데이터 담아서 전송한다
  • PUT : 서버에 데이터 수정을 위한 데이터 전송
  • DELETE : 데이터 제거 요청
  • CONNECT : 프록시 서버와 같은 중간 서버를 경유하기 위한 연결 요청
  • OPTIONS : 가능한 메서드에 대한 질의 요청, 응답 헤더에 allow 로 가능한 메서드가 담겨져 온다.
  • TRACE : 요청한 데이터의 수신되는 경로를 보여주는 요청 메소드
  • PATCH : PUT처럼 데이터 수정을 위한 요청 메소드이다. 다른점이라면 서버에 개발된 로직에 따라 다르겠지만 PUT은 데이터 전체적인 수정을 의미하고, PATCH는 데이터의 부분적인 수정을 의미한다.

참고 : https://developer.mozilla.org/ko/docs/Web/HTTP/Methods

 

요청 헤더

Host

- 서버의 도메인명

 

Connection : keep-alive

- http 1.1 이전 1.0에서는 1커넥션마다 1요청, 1응답만 가능했었다. 이런 비효율적인 커넥션 활용을 개선해서 나온것이 http 1.1인데 keep-alive가 디폴트 값으로 되어있다. 지속적인 커넥션을 의미한다. 간략한 추가 정보로 http 1.1의 지속적인 커넥션에도 병목현상이 일어나는 문제가 있는데 이를 개선한 버전이 http 2.0이다.

 

User-Agent

- 클라이언트의 환경(운영체제, 브라우저)에 대한 정보이다. 유용한 정보이지만 변경될 수 있는 헤더정보이기 무조건적 신뢰는 위험하다. 통계에 많이 사용된다.

 

Content-Length 

- 본문 (바디)의 크기를 바이트 단위로 표시해준다.

 

Pragma

- http 1.0에서 사용하던 Cache-Control의 역할

 

Cache-Control

- 캐시에 대한 설정으로 기본값은 no-cache이다. 

no-cache : 캐시 하지 말라는 의미가 아닌 캐시를 사용하기전 서버에 확인받는 설정

no-store : 캐시를 사용하지 않는 설정

must-revalidate : 만료된 캐시만 서버에 확인받는 설정

public : 어떤 요청이든 공유 캐시(혹은 중개 서버)에 캐시가 저장되는것

private : 공유 캐시같은 공유되는 서버에 캐시를 저장하지 않고 사용자의 사설 환경에만 캐싱

max-age : 캐시에 유효시간을 초단위로 설정하는 값. ex) max-age=3600

 

Accept

- 클라이언트가 허용할 수 있는 파일형식 MIME Type에 대한 설정, 클라이언트가 요청한 Accept 설정에 따라 서버가 Content에 대해 설정을 해서 응답한다.

 

Accept-Encoding

- Accept 압축형식 설정

Accept-Language

- Accept 언어 설정

 

Content-Type

- 전송하는 데이터 형식에 대한 정보 (요청, 응답 모두)

 

MIME type에 대해 참고 : https://developer.mozilla.org/ko/docs/Web/HTTP/Basics_of_HTTP/MIME_types

 

Origin

- 요청이 시작된 주소, 출처를 말한다. origin이 다른 경우 CORS문제가 발생한다.

 

Referer

- 이전 페이지에 대한 주소 정보가 담겨있다. 원래 스펠링은 referrer로 알고 있는데 referer이기 때문에 주의할 것.

 

Cookie

- 서버에 의해 클라이언트에 저장되어있는 쿠키 정보

 

요청 본문 (바디)

바디에는 요청에 필요한 데이터(파라미터 등) 값이 담겨져 개발된 로직에 따라 서버에서 처리된다.

 

 

응답 Raw 정보

응답 구조

Status-Line
Header

Body

 

Status-Line

맨 첫줄 Status Line에는 응답 상태에 대한 정보가 있다. Http 버전, Status code, Status text로 구성되어있다.

 

Status Code - 응답 상태에 대해 숫자로 나타낸 코드

상태 코드에 대해서는 문서를 참고하면 좋다.

https://developer.mozilla.org/ko/docs/Web/HTTP/Status

대략적으로 나타낸다면

  • 2XX : 요청이 정상적으로 이루어짐 - 200 OK, 201 Created, 202 Accepted 등
  • 3XX : 리다이렉션, 요청이 정상적으로 이루어 지기 위해 다른 주소로 이동해야함 - 
  • 4XX : 올바르지 않은 클라이언트의 요청 - 400 Bad Request, 404 Not Found 등
  • 5XX : 올바른 클라이언트 요청에 대한 서버 측 오류 - 500 Internal Server Error, 502 Bad Gateway, 503, Servcie Unavailable, 504 Time out 등

Status Text - 응답 상태에 대해 간략한 설명 텍스트

 

응답 헤더

Server

- 웹서버에 대한 정보, 보안상 안나오게 하는 경우가 많다.

 

Date

- 응답 시간 정보

 

Content-Type 

- 공통헤더로, 요청과 마찬가지로 전송하는 데이터에 대한 콘텐츠의 타입(MIME)이다.

 

X-Powered-By

- 어떤 기술로 개발되었는지에 대한 정보, Server정보와 마찬가지로 보안상 안나오게 하는 경우가 많다.

 

X-XSS-Protection

- 스크립트를 변경해서 공격하는 XSS에 대해 필터링 설정 정보. 0은 비활성화 1은 활성화를 의미한다

ex)

X-XSS-Protection: 1 : XSS 필터링 사용, 공격이 탐지되면 안전하지 않은 영역 제거 후 페이지 렌더링

X-XSS-Protection: 1; mode=block : XSS 필터링 사용, 공격이 탐지되면 페이지 렌더링을 중단

X-XSS-Protection: 1; report=<reporting-uri> : XSS 필터링 사용, 공격이 탐지되면 페이지 렌더링 중단, 보고

 

ETag

- 응답 받은 리소스의 고유한 해시값이다. 캐시되어있는 리소스의 Etag 값과 응답의 Etag값이 다르면 

캐싱 되어있는 데이터는 만료시간이 지나면 다시 요청으로 리소스를 받는데, Cache-Control의 max-age 값으로만 데이터를 판단해서 새로 리소스를 받을 경우 비효율적인 네트워크 자원활용이 일어나기 때문에 Etag 값을 비교하여 데이터 캐싱을 처리한다. W/는 약한검사라는 의미 (정확히 어떤 기능인지는 잘모르겠다)

 

ETag 좀 더 자세한 설명

서버로 부터 응답 리소스를 받으면 캐싱을 하는데 max-age, etag 등의 값을 받는다.

max-age가 만료되면 서버로 재요청을 해서 리소스를 받고 다시 캐싱하게 되는데 리소스가 그대로라면 비효율적인 요청이 되는것이다.

따라서 리소스의 고유값인 etag로 리소스가 바뀌었는지 판단하는데 max-age가 다되어 재요청 할때 요청값의 Etag는

If-None-Match(또는 If-Match) : 캐싱되어있는 리소스 Etag값의 형태로 요청하고 리소스가 그대로인경우 304 Not Modified, 새로운 리소스의 경우 200 ok와 함께 새로운 Etag 값을 응답받는다.

 

Content-Security-Policy

- 외부 파일에 대한 보안 정책 설정, 줄여서 CSP라고 한다.

default-src, script-src, img-src 등과 같은 타겟에 대해서 정책 값을 설정한다.

 

ex) Content-Security-Policy : default-src 'self'

'self'는 자신의 도메인의 파일만, 'none'은 파일을 못가져오게 하는 설정이다.

http나 https로 설정하면 그에 해당하는 프로토콜을 통해서만 가져올 수 있다.

 

 

HTTP 버전

 

HTTP 0.9

Http의 초기 버전으로 원-라인 프로토콜이라고 불리는데 그 이유는 요청이 1줄이기 때문이다.

GET /mypage.html

 

응답의 구조도 파일 내용만 존재하는 단순한 구조로 html파일만 전송이 가능했다.

<HTML>
A very simple HTML page
</HTML>

 

 

HTTP 1.0

제한적인 0.9버전에서 확장된 버전으로 버전, 상태값, 헤더 등의 정보가 더 추가된 버전이다.

 

요청과 응답

GET /mypage.html HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)

200 OK
Date: Tue, 15 Nov 1994 08:12:31 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: text/html
<HTML>
A page with an image
  <IMG SRC="/myimage.gif">
</HTML>

버전, User-Agent, 상태값, 서버, Content-Type 등 정보를 가지고 있는 헤더가 생겨 유연하고 확장된 프로토콜이 되었고,

Content-type 덕분에 html 외에 다른 파일 전송이 가능해졌다.

 

 

또 다른 특징으로 Http 1.0은 커넥션당 1요청 1응답의 단기 커넥션 방식이기 때문에 요청마다 매번 새로운 연결이 필요했고 이는 비효율적이기 때문에 비용이 올라가고 성능이 저하되는 방식이었다.

 

 

HTTP 1.1 

표준 프로토콜로 1.0의 단기 커넥션 방식을 보완하기위해 나온 Persistent Connection의 방식이 도입 되었다.

지정한 시간동안 Connection을 닫지 않아 하나의 커넥션에 여러 요청과 응답을 하기 때문에 이전보다 시간을 줄일 수 있었다. 처리를 완료한 유휴상태일때도 서버 리소스를 소비한다는 단점이 있다

 

이 방식에 더해서 파이프라인 기법이 도입이 되었다.

이전 요청에 대한 응답이 와야만 새로운 요청을 보냈던 동기적 방식에서 보완되어 하나의 커넥션에 이전 요청에 대한 응답을 기다리지 않고 순차적으로 여러 요청을 보내고, 그 순서에 맞춰 응답을 받아 지연시간을 줄이는 방식이다. 

단점으로 병목현상이 발생할 수 있는데, 요청1, 2, 3 순이라고 가정한다면, 1의 처리시간이 길고 2와 3의 처리시간은 짧은 요청인 경우 1의 긴 처리시간에 의해 2, 3 또한 막힐 수 있는 현상이 발생할 수 있다.

이를 Head Of Line Blocking 문제라고 한다.

 

이 외에도 1.1의 단점에는

응답 실패 시 처음부터 다시 보내야 한다는 점,

연속된 요청의 경우 동일한 헤더 구조가 대부분이어서 크기가 큰 헤더 중복이 발생한다는 점 등의 몇몇의 추가적인 단점들이 있다고 한다.

 

HTTP 1.1의 단점 보완

파이프라인기법의 보완을 위해 여러개의 커넥션을 늘려서 멀티플렉싱을 흉내내는 방식이 생겼다.

 

하지만 이는 커넥션 관리를 위한 오버헤드 현상과 대역폭 경쟁이 심해지는 단점이 있다.

 

또한 서브도메인으로 여러개의 도메인을 사용해 정적파일들을 빠르게 받는 도메인 샤딩 방법도 존재한다.

단순히 커넥션을 늘린것 처럼, 서버를 향한 도메인을 늘린 방법이라고 생각하면 된다.

 

HTTP 2.0

HTTP 2.0에서는 스트림, 프레임의 개념이 생겨 메세지 전송 방식의 변화가 이루어졌다.

 

기존 1.1에서는 줄바꿈으로 구분된 text형식의 메세지였다면,

2.0에선 헤더와 데이터를 frame 단위로 나누고, 바이너리로 인코딩하여 다수의 프레임으로 구성된 메세지를 전달하는 방식이다.

 

 

추가적으로 2.0에선 스트림의 개념이 생기는데 다수의 메세지로 구성되어 있고, 양방향의 특성을 가진 스트림을 여러개 두어 서버와 클라이언트간에 통신하여 멀티플렉싱을 구현하는 것이다.

http 2.0에서는 스트림에 우선순위와 고유 식별자를 부여하여 원하는 순서의 조립이 가능하다고 한다.

 

헤더 압축

 

http 2.0에서는 이미 중복된 헤더에 대해서는 변화된 부분만 전송이 가능해져서 헤더의 크기를 상당히 줄일 수 있다.

 

HTTP 2.0에서는 헤더를 압축하는 방식으로 HPACK 압축 방식을 사용한다.

HPACK방식은, 헤더 정보를 Header Table로 관리하여 중복된 헤더는 인덱스 값만 전송하고, 새롭게 추가되거나 변경된 헤더는 Huffmann 인코딩이 되어 전송하는 방식을 말한다.

 

서버 푸시

기존의  HTTP 1.x의 웹페이지 렌더링 과정은

HTML 요청 > HTML 태그 파싱 > 필요한 리소스(css, js, images 등) 재요청 > 웹페이지 완성

과정이었다면

 

HTTP 2.0 에서는

HTML 요청 > 웹페이지 완성

과정이 가능해졌다.

 

좀 더 자세하게 말하면 HTTP 2.0에서는 클라이언트가 요청하지 않은 리소스 전송이 가능한데 이 리소스들은 PUSH_PROMISE 라는 약속된 프레임안에 구성되어있다. 클라이언트는 PUSH_PROMISE을 수신 후 RST_STREAM 스트림을 통해 PUSH_PROMISE에 대한 거부 옵션을 설정 할 수 있어 효율적인 리소스 관리가 가능하다.

 

 

 

HTTP 2.0의 한계

결론적으로는 이러한 HTTP 2.0도 결국 TCP를 통해 사용하기 때문에 TCP의 신뢰성을 위해 발생하는 단점에 대해서는 극복하지 못한다는 한계가 있다.

구글에서는 이를 극복한 UDP 기반의 QUIC이라는 전송계층 프로토콜을 개발한다.

728x90