HTTP 1.1 - 같은 서버(도메인)에 관한 동시 연결 제한
HTTP 1.1의 동시성
예전에 HTTP 1.1은 같은 도메인에 관해서는 만들 수 있는 연결의 제한이 있어서 Domain Sharding을 해야 한다고 들은적이 있다.
연결 제한으로 인해 느려질 수 있는 경우
쉽게 이해하기 위해 다음과 같은 상황을 생각해보자.
내가 웹 페이지에 접속하며 매우 큰 리소스인 이미지 파일 A, B, C를 example.com 서버로부터 불러와야 한다고 해보자.
이미지는 다음과 같은 경로에 호스팅되어 있다.
- A.png: example.com/img/A.png
- B.png: example.com/img/B.png
- C.png: example.com/img/C.png
이렇게 생긴 웹사이트일 것이다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Coding Groot의 Head-of-Line Blocking 실험!</title>
</head>
<body>
<h1>Coding Groot의 Head-of-Line Blocking 실험!</h1>
<p>example.com으로부터 큰 이미지를 불러와보자</p>
<img src="https://example.com/img/A.png" alt="Image A">
<img src="https://example.com/img/B.png" alt="Image B">
<img src="https://example.com/img/C.png" alt="Image C">
</body>
</html>
처음 브라우저가 example.com 서버에 A.png(example.com/img/A.png)를 요청한다. 이 이미지 파일은 매우 크기 때문에 다운로드하는 데 상당한 시간이 소요된다.
HTTP/1.1에서는 동일한 연결에서 여러 요청을 처리할 수 있지만, A.png가 완전히 다운로드될 때까지 이 연결이 바쁘기 때문에, 같은 연결에서 B.png(example.com/img/B.png)와 C.png(example.com/img/C.png)에 대한 요청은 대기 상태에 머무르게 된다.
결국, 브라우저는 A.png를 계속 다운로드하느라 연결을 차지하고 있어서 B.png와 C.png에 대한 요청은 처리되지 않고 전체 다운로드 시간이 길어지게 된다.
실제 RFC
가장 최신의 RFC가 정확하지 않을까 싶어서 찾아봤다.
다음은 2022년에 발행된 HTTP1.1의 RFC이다. RFC 9112의 "9.4. Concurrency"를 읽어보면 된다.
[GPT 번역]
9.4. 동시성
클라이언트는 특정 서버에 대해 동시에 유지하는 연결의 수를 제한해야 합니다.
이전의 HTTP 버전에서는 연결 수에 대한 특정 상한선을 제시했지만, 이는 많은 애플리케이션에 비실용적인 것으로 밝혀졌습니다. 그 결과, 이 명세서는 특정 연결 수의 최대치를 강제하지 않으며, 대신 클라이언트가 다중 연결을 열 때 보수적으로 접근할 것을 권장합니다.
다중 연결은 주로 “헤드 오브 라인 블로킹”(head-of-line blocking) 문제를 피하기 위해 사용됩니다. 이 문제는 서버 측에서 처리 시간이 많이 소요되거나 매우 큰 콘텐츠를 전송하는 요청이 동일한 연결에서 후속 요청들을 차단하는 상황을 말합니다. 그러나 각 연결은 서버 자원을 소비합니다.
또한, 다중 연결 사용은 혼잡한 네트워크에서 바람직하지 않은 부작용을 초래할 수 있습니다. 큰 수의 연결을 사용하는 것은 혼잡하지 않은 네트워크에서도 부작용을 초래할 수 있는데, 이는 이러한 연결들이 집합적이고 초기에는 동기화된 전송 행위를 통해 더 적은 병렬 연결을 사용할 경우 발생하지 않았을 혼잡을 유발할 수 있기 때문입니다.
서버는 과도한 수의 열린 연결과 같은, 서비스 거부 공격으로 간주될 수 있는 트래픽을 거부할 수 있다는 점에 유의하십시오.
읽어보면 동시 연결 제한은 한다. 그런데 예전에는 동시 연결 수에 구체적인 상한을 뒀지만 지금은 현실적인 이유로 강제하지 않는다고 한다.
따라서 브라우저에 따라 내가 예시로 제시한 이미지 3개 정도 같은 도메인에 다운 받아서 병목이 걸리는 상황이 안 발생할 수도 있다.
참고 - 이전 RFC 2616의 "8.1.4 Practical Considerations"
[GPT 번역]
지속적인 연결을 사용하는 클라이언트는 특정 서버에 대해 유지하는 동시 연결의 수를 제한해야 합니다(SHOULD). 단일 사용자 클라이언트는 어떤 서버나 프록시에 대해 2개 이상의 연결을 유지해서는 안 됩니다(SHOULD NOT). 프록시는 다른 서버나 프록시에 대해 최대 2*N개의 연결을 사용해야 합니다(SHOULD), 여기서 N은 동시에 활동 중인 사용자 수를 나타냅니다. 이러한 지침은 HTTP 응답 시간을 개선하고 혼잡을 방지하기 위한 것입니다.
그럼 예전에는 동시 연결이 몇 개로 제한되어 있었는지 궁금해서 찾아봤다. 읽어보면 2개 이상의 연결을 유지하지 않게 했었다.
Chrome에서 실험해보기
그럼 크롬은 한 도메인에 최대 몇 개의 연결을 유지하는지 여러 사이트를 둘러 봤는데 3개까지 동시 연결되는 걸 봤는데 나머지는 직접 실행하려 하는데 시간이 없어서 나중에 다시 남기로 오겠다..!
(준비중)
해결법
Domain Sharding
이런 동일 서버에 의한 blocking 문제는 Domain Sharding으로 해결 할 수 있다. 같은 서버를 쓰는 것이 아니라, CDN과 같은 다른 서버에 정적 이미지를 배포해서 리소스 요청을 여러 도메인에 분산시켜 브라우저가 동시에 더 많은 연결을 열 수 있도록 하는 기법을 Domain sharding이라고 한다.
HTTP/2
HTTP/2에서는 단일 연결에서 여러 스트림이 독립적으로 처리되므로, Head-of-Line Blocking 문제가 발생하지 않는다.
따라서 HTTP/2를 사용하는 경우에는 도메인 샤딩이 필요하지 않을 수 있다. 의도적으로 스트림 병목을 제거하기 위해 하는 도메인 샤딩은 주로 HTTP/1.1 환경에서 주로 사용되는 기법이라 한다.
댓글
이 글 공유하기
다른 글
-
CertBot 인증서가 만료가 되었다
CertBot 인증서가 만료가 되었다
2024.01.21 -
CloudFront에 올린 Font(woff, woff2)가 CORS 때문에 차단되는 경우
CloudFront에 올린 Font(woff, woff2)가 CORS 때문에 차단되는 경우
2022.08.21 -
웹 문서를 만들기 전에 고민해볼 것들
웹 문서를 만들기 전에 고민해볼 것들
2022.04.17 -
Flask를 CLI에서 실행해야 하는 이유와 환경 세팅하기
Flask를 CLI에서 실행해야 하는 이유와 환경 세팅하기
2021.06.08