HTTP의 새로운 상태 코드: 103 Early Hints

HTTP の新しいステータスコード 103 Early Hints의 번역글입니다.

HTTP에 새로운 상태 코드인 103 Early Hints가 추가되려 하고 있습니다. HTTP/1.1 및 HTTP2 통신에서의 리소스 배포 최적화를 위해 추가되는데 왜 필요한지, 어떤 장점이 있는지를 이 글에서 설명합니다.

HTTP2 Push에 대한 복습

우선 HTTP2 Push에 대해 복습해봅시다.

H2 Push는 간단히 말해 PUSH_PROMISE 프레임을 사용하여 페이지 응답보다 먼저 해당 페이지에 있는 리소스를 반환하는 스펙입니다.

예로 /users 응답은 script.jsstyle.css를 포함하고 있다고 가정해보면, HTTP2에서는 SQL 쿼리를 날리고 Users를 가져오는 동안 script.js, style.js를 클라이언트에 먼저 Push하는 것입니다. Push된 리소스는 브라우저의 캐시에 먼저 들어가 /users 응답이 끝난 후 HTML을 파싱하여 두 리소스가 필요하다고 서버로 요청을 보내기 전에 cache hit를 유도합니다.

이에 따라 다음 장점을 얻습니다:

  • DB 접근 시간을 효율적으로 사용
  • 두 개의 하위 리소스에 대한 요청(request)이 없어져 0.5 RTT씩 이득

이것이 H2 Push의 기본적인 부분입니다.

Reverse Proxy

일반적으로 웹 서비스를 제공하는 서버에서 실제 서버 앞에 Reverse Proxy 서버를 두는 경우가 많습니다. 이때 만약 실제 서버에서 H2로 응답하고 Reverse Proxy 또한 H2로 응답한다면 H2 Push를 그대로 클라이언트로 전달할 수 있습니다.

하지만 구성에 따라 Reverse Proxy가 H2를 H1.1로 풀어(downgrade) 응답을 보내는 경우도 있는데 이 경우 H2 frame을 사용할 수 없기 때문에 Push를 사용할 수 없습니다. 그래서 HTTP의 Link 헤더 등을 이용해 Reverse Proxy 하위 리소스의 존재를 알리고 해당 리소스들은 H2 Push로 변환되어 전달하는 방법도 존재합니다.

하지만 이 경우 HTTP/1.1 통신의 특성으로 인해 DB 접근 시간을 효율적으로 사용하는 등의 장점을 얻을 수 없게 됩니다.

상태 코드와 헤더

텍스트 기반 프로토콜인 HTTP/1.1 응답은 다음과 같이 구성되어 있습니다:

200 OK
Content-Length: 100
Content-Type: text/html
Link: </style.css>; rel=preload
Link: </script.js>; rel=preload

{response body}

이 바이트는 소켓에 순서대로 쓰여질 수밖에 없기 때문에 Link 헤더를 보내고 싶어도 상태 코드가 정해진(decide) 이후에만 보낼 수 있게 됩니다. 여기서 상태 코드는 서버에서 DB 질의를 하는 등 모든 작업이 끝나기 전까지 200인지 404인지 500인지 확정지을 수 없게 됩니다. 따라서 DB 질의를 하는 동안 Link 헤더를 보내는 것은 기존 H1.1 범위 내에서는 불가능한 일입니다.

이 제한으로 인해 H1.1을 H2로 변환하여 클라이언트에 보내는 경우에도 Push의 이점을 얻을 수 없습니다.

103 Early Hints

이러한 문제를 해결하기 위해 제안된 것이 h2o의 개발자인 @kazuho씨가 제안한 상태 코드 103입니다.

103은 헤더만 먼저 보내고 응답은 나중에 온다는 의미로 사용됩니다. 앞의 예와 연관지어 보면 DB 질의를 하는 동안 Link만 103 헤더에 포함하여 보내고 나머지는 나중에 보내는 식입니다.

103 Early Hints
Link: </style.css>; rel=preload
Link: </script.js>; rel=preload


200 OK
Content-Length: 100
Content-Type: text/html

{response body}

실서버는 요청을 받은 후 처리가 끝나야 상태 코드가 결정되기 때문에 하위 자원의 존재를 103으로 응답하면 Reverse Proxy 서버가 103을 받고 H2 Push로 대체하여 클라이언트에 Push를 보내는 식으로 작동하게 할 수 있습니다. 이후 실서버는 모든 처리가 끝난 후 상태 코드 및 응답이 결정된 다음 응답을 반환합니다.

이러한 방법을 이용하면 H2 Push의 장점을 모두 활용할 수 있게 됩니다.

정적 파일(static files)

만약 Reverse Proxy가 H2로 변환하지 않고 실서버가 직접 Push를 보내도 Early Hints는 도움이 됩니다. 일반적으로 정적 파일 전송은 실서버 대신 Reverse Proxy 서버가 콘텐츠 서버 역할로 전송되는 경우가 많습니다. 그래서 실서버가 하위 리소스를 Push하고 싶을 때 Push Promise를 클라이언트에 전송하는 대신 H2 프레임 내에 Early Hints를 보내는 식으로 이용할 수 있습니다. 이때 Reverse Proxy가 해당 헤더를 H2 Push로 변환하고 클라이언트로 정적 파일을 Push하는 방향으로 유도할 수 있게 됩니다.

결과로 실서버는 정적 파일을 직접 갖고있을 필요가 없게 됩니다.

정리

정리하여 103 Early Hints는 알려진 메타 데이터알려지지 않은 콘텐츠를 분리하여 비동기적으로 전달할 수 있는 것이라고 볼 수 있습니다.