Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(ko) part 6, 12 Translated in Korean #217

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
* [대기시간의 고통을 극복하기 위해 한일](ko/part3.md)
* [HTTP 업데이팅](ko/part4.md)
* [http2 컨셉](ko/part5.md)
* [http2 프로토콜 (번역되지 않은)](ko/part6.md)
* [http2 프로토콜](ko/part6.md)
* [연장선 (번역되지 않은)](ko/part7.md)
* [http2 세계 (번역되지 않은)](ko/part8.md)
* [Firefox에서의 http2](ko/part9.md)
Expand Down
9 changes: 9 additions & 0 deletions ko/part12.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ HTTP2는 HTTP1와 HTTP2 사이의 통신을 프록시 할 수 있도록 하기

## 12.1. QUIC

(이 챕터는 2015년에 쓰여졌는데, 그때는 여전히 QUIC 은 초기 시절이었습니다. 저는 독자들에게 그 당시에 우리가 미래를 어떻게 보았는지 가늠할 수 있도록 이 챕터를 그대로 남기기로 결정했습니다. 2022년의 의견은 다음 챕터를 보시길 바랍니다.)
Google의 [QUIC](https://www.chromium.org/quic)( Quick UDP Internet Connections )은 흥미로운 실험입니다. 그것은 SPDY 때와 유사한 스타일과 정신으로 이루어지고 있습니다.
QUIC은 TCP + TLS + HTTP/2의 대안이며 UDP를 사용하여 구현되었습니다.

Expand All @@ -21,3 +22,11 @@ QUIC은 연결을 빠르게 할 수 있습니다. HTTP/2는 패킷 손실에

QUIC은 현재 Google이 Chrome과 Google 서버에만 구현 되어 있습니다. 코드는 쉽게 재사용 할 수 있는 형태가 되어 있지 않습니다.
libquic라는 프로젝트가 그것을 실현 하려고 하고 있습니다. 프로토콜은 초안으로 [libquic](https://github.com/devsisters/libquic) 전송 워킹 그룹에 [제출](https://tools.ietf.org/html/draft-tsvwg-quic-protocol-01) 되었습니다 .

## 12.2 HTTP/3

**QUIC** 은 더이상 두문자어가 아닙니다. 그것은 전송 프로토콜의 이름으로 UDP 위에 동작하며 네개의 명세 사항에 문서화되어 있습니다: RFC 8999 부터 RFC 9002 까지. 위 12.1 에서 기술된 것은 Google QUIC 프로토콜이고, 지금 스탠더드로 만들어진 것은 비록 이름은 그대로 유지되지만 다른 QUIC 프로토콜이라는 것을 알아두십시오.

HTTP/3 는 진행 중인 새로운 HTTP 버전입니다. 그것은 QUIC 프로토콜 위에서 동작하도록 설계되어 있습니다.

HTTP/3 와 QUIC 의 자세한 내용은 [HTTP/3 해설](https://http3-explained.haxx.se/)를 살펴보시길 바랍니다.
92 changes: 89 additions & 3 deletions ko/part6.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,91 @@
#6. http2 프로토콜
# 6. http2 프로토콜

(번역되지 않은)
지금까지 http2 가 탄생한 배경 설명, 그 간의 역사와 정치적인 일은 충분히 다루었다. 이제는 프로토콜의 스펙에 대해 자세히 알아보자. http2 를 구성하는 요소와 개념은 무엇일까.

[영어](../en/part6.md)
## 6.1. 바이너리

http2 는 바이너리 프로토콜(Binary Protocol)이다.

잠시 이게 무슨 뜻인지 생각해보자. 만일 당신이 이전에 인터넷 프로토콜에 관여해봤다면 당신은 지금쯤 본능적으로 이 결정에 반대할 가능성이 높다. 텔넷(telnet) 을 통한 요청들은 사람들이 수작업할 수 있다는 이유 등을 들면서 텍스트/아스키(text/ascii) 에 기반을 둔 프로토콜이 우수하다는 주장을 펼치면서 말이다.

http2 는 바이너리이기에 프레임 작업(framing)을 훨씬 손쉽게 한다. 프레임의 시작 지점과 종료 지점을 알아내기란 HTTP 1.1 에서는 정말로 복잡한 일 중 하나다. 그리고 사실 대개 그것은 텍스트 기반의 프로토콜이 그렇다. 선택적인 공백 문자와, 동일한 것을 작성하는 여러 방법들이 있다는 것으로부터 벗어남으로써 구현은 간단해진다.

또 프로토콜이 바이너리인 점은 프레임 작업(framing)으로부터 실제 프로토콜 부분을 분리하는 것을 훨씬 간단하게 만들어 준다. - HTTP1 에서는 혼란스럽게도 서로 섞여 있다.

프로토콜이 압축 기능을 제공하고 TLS 상에서 자주 사용되는 사실은 텍스트의 가치를 감소시킨다. 왜냐하면 어쨋건 당신은 텍스트를 볼 수 없을 것이기 때문이다. 우리는 와이어샤크(Wireshark) 와 같은 도구를 이용하는 아이디어에 익숙해져서 http2 상에서는 프로토콜 층위에서 실제로 어떤 일이 이뤄지고 있는지 살펴보아야 한다.

이 프로토콜을 디버깅하는 것은 아마도 컬(curl) 과 같은 도구를 사용하거나 와이어샤크(Wireshark) 의 http2 dissector 와 같은 도구로 네트워크 스트림을 분석하는 방식으로 이뤄져야 할 것이다.

## 6.2. 바이너리 형식

<img style="float: right;" src="https://raw.githubusercontent.com/bagder/http2-explained/master/images/frame-layout.png" />

http2 는 바이너리 프레임(binary frames)들을 전송한다. 서로 다른 타입의 프레임이 존재하고, 그들은 모두 구성이 같다. 길이, 타입, 플래그, 스트림 식별자(Stream Identifier), 그리고 프레임 페이로드(frame payload).

http2 스펙에 서로 다른 10 개의 프레임 타입이 정의되어 있고, 아마도 HTTP 1.1 기능에 대응하는 가장 주요한 타입은 DATA 와 HEADERS 일 것이다. 더 자세한 내용은 앞으로 진행하면서 설명하도록 하겠다.

## 6.3. 다중화 스트림

이전 섹션에서 언급된 스트림 식별자(Stream Identifier)는 하나의 "스트림"이 http2 를 통해 전송된 개개의 프레임과 관련이 있다. 하나의 스트림은 하나의 독립적이며, 양방향으로 전송되는 프레임들의 나열이고, 그 프레임들은 하나의 http2 연결 속에서 클라이언트와 서버 사이에 교환된다.

단일 http2 연결은 동시에 열린 다중 스트림들을 가질 수 있고, 이 다중 스트림들로부터 각각의 엔드포인트로 프레임들을 보낼 수 있다. 스트림들은 일방적으로 형성되거나 사용될 수 있고, 클라이언트 또는 서버에 의해 공유될 수 있다. 그리고 그들은 각각의 엔드포인트에 의해 닫힐 수 있다. 프레임들이 하나의 스트림 안에서 보내지는 순서는 상당히 중요하다. 프레임 수신자들은 그들이 전달받은 순서대로 프레임을 처리한다.

스트림을 다중화(Multiplexing)하는 것은 여러 스트림으로부터 받은 패키지들이 동일 연결 상에서 섞인다는 것을 의미한다. 두 개(혹은 그 이상) 정보를 가진 개별 기차가 단일의 기차로 합쳐지고, 그리고 다시 반대편에서 쪼개진다. 여기 두 개의 기차가 있다.

![one train](https://raw.githubusercontent.com/bagder/http2-explained/master/images/train-justin.jpg)
![another train](https://raw.githubusercontent.com/bagder/http2-explained/master/images/train-ikea.jpg)

동일 연결 상에서 두 기차가 다중화(multiplexed)되어 있다.

![multiplexed train](https://raw.githubusercontent.com/bagder/http2-explained/master/images/train-multiplexed.jpg)

## 6.4. 우선 순위와 의존 관계

개별 스트림 역시 우선 순위(혹은 "중요도")를 가지고 있다. 그리고 그것은 상대에게 어떤 스트림이 가장 중요하게 여겨져야 할지를 알려준다. 자원 제약이 있을 때 서버가 어떤 스트림을 가장 먼저 보낼지 선택하는 상황을 대비하기 위해서다.
우선순위(PRIORITY) 프레임을 이용하여 클라이언트 역시 서버에게 이 스트림이 어떤 다른 스트림에 의존하고 있는지를 알려 줄 수 있다. 클라이언트가 우선 순위 "나무"(tree)를 만들 수 있게 해주고, 몇몇의 "자식 스트림"이 "부모 스트림"의 완료에 의존성이 있을지에 대한 정보를 담고 있다.

우선 순위 중요도와 의존 관계는 실행 시간에 동적으로 바뀔 수 있다. 사용자가 이미지로 가득찬 페이지를 스크롤 할 때 어떤 이미지들이 가장 중요한지 브라우저가 특정할 수 있게 해주거나, 브라우저 탭을 바꿔 갑자기 집중되는 스트림을 새롭게 우선 순위를 높일 수 있게 할 수 있어야 한다.

## 6.5. 헤더 압축

HTTP 는 상태가 없는 프로토콜이다. 요약하자면, 모든 요청은 서버가 그 요청을 처리하는 데 필요한 가능한 한 세부적인 정보를 전달해야 한다는 것을 뜻한다. 서버가 이전 요청들로부터 얻은 정보와 메타 정보를 저장할 필요가 없다. http2 는 이 패러다임을 고수하기 때문에 이와 마찬가지로 동작해야 한다.

이는 HTTP 를 반복적이게 만든다. 클라이언트가 같은 서버로부터 웹 페이지의 이미지들과 같은 많은 자원을 요청할 때, 거의 동일하게 생긴 수많은 요청이 생길 것이다. 거의 동일한 것들이 연속된다면 압축이 절실하다.

(이전에 언급한 것처럼) 웹 페이지 별 객체의 수가 증가해 올 때, 시간이 지남에 따라 쿠키의 사용과 요청의 크기 또한 증가해 왔다. 쿠키는 모든 요청에 포함되어야 되고, 종종 여러 요청 사이에서 쿠키는 동일하다.

HTTP 1.1 요청 크기는 사실 너무 비대해진 나머지 종종 초기 TCP 윈도우(window)보다 커지는 상황에 이르기도 했다. 때문에 전송하기에 너무 느려져 버렸다. 그들은 서버로부터 완전한 요청이 보내지기 전에 ACK 응답을 받기 위해서라도 온전히 완복 여행(round-trip) 을 해야한다. 이것은 압축이 필요한 또 다른 이유다.

### 6.5.1. 압축은 까다로운 주제다

HTTPS 와 SPDY 압축은 [BREACH](https://en.wikipedia.org/wiki/BREACH_%28security_exploit%29) 와 [CRIME](https://en.wikipedia.org/wiki/CRIME) 공격에 취약점이 있다고 밝혀졌다. 알려진 텍스트를 스트림에 삽입하고, 그에 따른 결과가 어떻게 바뀌는지 확인함으로써 공격자는 암호화된 페이로드 안에 무엇이 전송되었는지 알 수 있다.

프로토콜 안에서 동적으로 생성된 컨텐츠를 압축하는 것 - 위와 같은 공격들에 취약점을 노출하지 않으면서 - 은 여러 고민과 섬세한 고려들이 필요하다. 이것이 HTTPbis 팀이 하려는 것이다.

HTTP/2 를 위한 헤더 압축 기술인 [HPACK](https://www.rfc-editor.org/rfc/rfc7541.txt) 을 살펴 보아라. 이 기술은 이름을 통해 알 수 있듯이 http2 헤더를 위해 특별히 고안된 압축 형식이다. 그리고 이는 하나의 분리된 인터넷 초안으로 명세되어 가는 중이다. 이 새로운 압축 형식은 다른 보조 장치(하나의 비트로 중간자에게 특정 헤더와 프레임의 추가 패딩을 압축하지 말라고 요청하는 것과 같은)와 함께 압축된 내용을 파헤치기 어렵게 만들 것이다.

HPACK 창시자 중 한 명인 Roberto Peon 의 말을 인용한다:

> "HPACK 은 구현 방식을 제대로 따를 경우 정보 누출을 어렵게 만들고, 인코딩과 디코딩을 빠르고 쉽게 만들고,
> 수신자가 압축 맥락 크기(compression context size) 에 대한 통제권을 제공하고, 프록시의 재 인덱싱
> (re-indexing)이 가능하도록 허용해주고, (예를 들면, 프론트엔드와 백엔드 사이의 프록시 안에서 공유 상태),
> 그리고 호프만 인코딩된 문자열의 빠른 비교 등이 가능하도록 디자인되었다"


## 6.6. 재설정 - 당신의 생각을 바꿔라

HTTP 1.1 의 단점 중 하나는 특정 크기로 Content-Length 를 지정하여 HTTP 메시지 전송했으면, 그 전송을 쉽게 중지하지 못한다는 것이다. 당연히도, 당신은 종종 (항상은 아니지만) TCP 연결을 끊을 수 있다. 그러나 이로 인해 다시금 새로운 TCP 핸드쉐이크(TCP handshake)를 수립해야하는 비용을 지불해야 한다.

더 나은 해법은 해당 메시지를 중지하고 새롭게 시작하는 것이 될 수 있다. 이것은 http2 의 RST_STREAM 프레임으로 이루어질 수 있고, 그것은 대역폭을 낭비하거나 연결을 분해해야하는 어려움을 방지할 수 있다.

## 6.7. 서버 푸시

이것은 "캐시 푸시(cache push)" 로도 알려진 기능이다. 클라이언트가 자원 X 를 요청하고, 서버는 클라이언트가 아마도 자원 Z 또한 필요할 수 있다는 사실을 안다면, 클라이언트가 요청하지 않아도 자원 Z 를 클라이언트에게 보내는 것이 아이디어의 골자다. 자원 Z 를 캐쉬에 저장함으로써 언제든 필요로할 때 사용할 수 있게 클라이언트에 도움을 준다.

서버 푸시(Server push)는 클라이언트가 반드시 서버에게 이 기능을 사용해도 된다고 명시적으로 허용해줘야 하는 것이다. 더 나아가 클라이언트는 특정 자원을 원하지 않다면 재빠르게 푸시된 스트림을 RST_STREAM 을 사용해 언제든 종료시킬 수 있다.

## 6.8. 흐름 통제(flow control)

각 개별 http2 스트림은 각자가 공표(advertised)하는 전송량(flow window) 허용 범위가 있어서 상대가 그 만큼의 데이터만 보낼 수 있도록 허용된다. 당신이 SSH 가 어떻게 작동하는지 알고 있다면, 이것은 그것과 스타일과 정신이 매우 비슷하다.

모든 스트림 양 말단은 상대에게 들어오는 데이터를 처리할 충분한 여력이 있는지 알려줘야 한다. 그리고 상대방은 허용 범위(window)가 늘어지기 전까지는 그 만큼의 데이터만을 보내도록 허용된다. 오직 DATA 프레임들만이 흐름 통제(flow controlled)된다.