[HTTP 완벽 가이드] 10장 HTTP 2.0

June Lee·2022년 7월 12일
0

네트워크

목록 보기
22/28

10.1 HTTP/2.0의 등장 배경

HTTP/1.1구현의 단순성과 접근성에 주안점을 둠
-> 성능이 희생됨 (ex. 응답을 받아야만 그 다음 요청을 보낼 수 있음)
-> 이런 문제를 해결하기 위해 병렬 커넥션(커넥션을 동시에 여러개 맺는건데, 근본적인 해결책은 아님), 파이프라인 커넥션(사용되지 않음) 등이 도입되었지만 해결되지 않음


이런 이유로 등장한 것이 구글의 SPDY(스피디) 프로토콜
-> 하나의 TCP 커넥션에서 여러 요청을 동시에 보낼 수 있음(멀티플렉싱 가능) & 서버 푸시 가능
-> 2012년 10월 3일, HTTP 작업 그룹은 SPDY를 기반으로 HTTP/2.0 프로토콜을 설계하기로 결정함




10.3 HTTP/1.1과의 차이점

10.3.1 프레임

HTTP/2.0은 모든 메시지를 프레임에 담아 전송



10.3.2 스트림과 멀티플렉싱

스트림은 HTTP/2.0 커넥션을 통해 클라이언트와 서버 사이에서 교환되는 프레임들의 독립된 양방향 시퀀스이다.
한쌍의 HTTP 요청과 응답은 하나의 스트림을 통해 이루어진다.


HTTP/1.1의 특징
하나의 TCP 커넥션을 통해 요청을 보냈을 때, 그에 대한 응답이 도착하고 나서야 같은 TCP 커넥션으로 다시 요청을 보낼 수 있다
-> 그래서 보통 한번에 여러개의 TCP 커넥션을 만들어 동시에 여러 개의 요청을 보낸다.
-> 그렇지만 TCP 커넥션을 무한정 만들 수는 없고, 오늘날의 웹 페이지는 한번에 수십 수백건의 요청을을 보내야한다.
(-> 파이프라인 커넥션이 있지만, 이건 단점이 있어 널리 사용되지 않는다.)


HTTP/2.0의 특징

  • 하나의 커넥션에서 여러 개의 스트림이 동시에 열릴 수 있다(멀티 플렉싱)
  • 스트림은 우선순위를 가질 수도 있다(보다 중요한 리소스, 예를 들어 이미지보다는 html 파일에 더 높은 우선순위를 줄 수 있다. 그러나 우선순위에 따르는 것은 의무사항은 아님)
  • 모든 스트림은 31비트의 무부호 정수로 된 고유한 식별자를 갖는다 (스트림이 클라이언트에 의해 초기화되었다면 이 식별자는 반드시 홀수, 서버라면 반드시 짝수 / 새로 생성되는 스트림의 식별자는 이전 스트림 혹은 예약된 스트림보다 커야함 -> 규칙을 어기는 식별자를 받으면 PROTOCOL_ERROR라는 응답 코드의 커넥션 에러로 응답)
  • 서버와 클라이언트는 협상 없이 스트림을 만듦 (ACK 필요 없음)
  • 한번 사용된 스트림 식별자는 다시 사용될 수 없음 -> 식별자가 고갈될 때에는 커넥션을 다시 맺으면 됨
  • 동시에 여러개의 스트림을 이용하면 스트림이 블록될 우려가 있음 -> WINDOW_UPDATE 프레임을 이용한 흐름제어를 통해 스트림이 서로 간섭해서 망가지는 것을 막아줌


10.3.3 헤더 압축

HTTP/2.0은 1.1과 달리 헤더를 압축 -> 예전과 달리 하나의 웹페이지가 요청을 수십 수백개 보내기 때문에 헤더의 크기가 크면 회전 지연, 대역폭에 영향
HAPCK 명세에 정의된 헤더 압축 방법으로 압축한 후 헤더 블록 조각들로 쪼개져서 전송됨 -> 받는 쪽에서 복원 (헤더를 쓰지 않는 경우라도 무조건 압축 해제를 수행해야함. 그럴 수 없다면 COMPRESSION_ERROR와 함께 커넥션을 끊어야함)



10.3.4 서버 푸시

  • HTTP/2.0에서 서버는 클라이언트가 요청하기 전에 리소스를 클라이언트에 푸시할 수 있다(예를 들어 html 문서를 요청받았다면 해당 문서가 링크하고 있는 이미지, css, javascript 파일 등을 푸시)
  • 리소스를 푸시하려는 서버는 먼저 클라이언트에 PUSH_PROMISE 프레임을 보내 푸시할 것임을 알려야 한다(클라이언트가 해당 자원을 별도로 요청하는 상황을 막기 위해) -> 클라이언트가 이를 받으면 해당 프레임의 스트림은 클라이언트 입장에서 'reserved(remote)' 상태가 된다. -> 클라이언트는 RST_STREAM 프레임을 보내 푸시를 거절할 수 있다.
  • 서버 푸시를 사용하기로 했더라도, 중간의 프록시가 훼방을 놓을 수 있다
  • 서버는 오직 안전하고, 캐시 가능하고, 본문을 포함하지 않는 요청에 대해서만 푸시를 할 수 있다
  • 푸시할 리소스는 클라이언트가 명시적으로 보낸 요청과 연관된 것이어야 한다 -> 원 요청을 위해 만들어진 스트림을 통해 PUSH_PROMISE 프레임을 보냄
    클라이언트는 반드시 서버가 푸시한 리소스를 CORS 정책에 따라 검사해야 한다.
  • 서버 푸시를 끄고 싶다면 SETTING_ENABLE_PUSH를 0으로 설정



10.4 알려진 보안 이슈

10.4.1 중개자 캡슐화 공격(Intermediary Encapsulation Attacks)

HTTP/2.0은 헤더 필드로 어떤 문자열이든 허용한다. -> 따라서 HTTP/2.0 메시지를 중간의 프록시가 HTTP/1.1로 변환할 때 메시지가 위조될 가능성이 있다 (반대로 HTTP/1.1 -> 2.0으로 변환할 때는 이런 문제가 없음)



10.4.2 긴 커넥션 유지로 인한 개인정보 누출 우려

HTTP/2.0은 1.1보다 훨씬 긴 시간 커넥션을 유지한다. 어떤 사용자가 브라우저를 사용할 때 그 사용자는 이전에 브라우저를 사용했던 사용자가 무엇을 했는지 알아낼 가능성이 있음

profile
📝 dev wiki

0개의 댓글