[번역] webpack & HTTP/2

전병민·2023년 5월 20일
0

번역

목록 보기
1/1

이 글은 webpack & HTTP/2 를 번역한 글 입니다. 오래 전 글이라 지금과는 다를 수 있습니다.


HTTP/2에 대한 미신으로 시작하겠습니다.

HTTP/2를 사용하면 더 이상 모듈을 번들로 묶을 필요가 없다.

HTTP/2는 모든 모듈을 동시에 병렬로 하나의 연결에서 다중화(multiplex) 할 수 있습니다. 따라서 많은 요청에 대한 추가적인 왕복이 없습니다. 각 모듈은 개별적으로 캐시될 수 있습니다.

안타깝게도 실제로는 그렇게 간단하지 않습니다.

과거 관련 연구

다음 기사들을 읽어보시면, 모든 것을 자세히 설명하고 실험을 통해 확인하는 내용을 볼 수 있습니다(혹은 건너뛰고 요약을 읽으셔도 됩니다).

Forgo JS packaging? Not so fast

The Right Way to Bundle Your Assets for Faster Sites over HTTP/2

기사들의 요지는 다음과 같습니다

  • 단일 연결된 파일과 비교하여 각 요청마다 여전히 프로토콜 오버헤드가 있습니다.
  • 단일 큰 파일의 압축이 여러 작은 파일보다 더 우수합니다.
  • 서버는 많은 작은 파일을 제공하는 데 더 느립니다.

따라서 우리는 양쪽 모두에게 최상의 결과를 얻기 위해 중간 지점을 찾아야 합니다. (역자주: 캐싱과 압축 사이에 존재하는 상충관계(trade-off)를 의미하는듯) 우리는 모듈을 n개의 번들에 넣습니다. 여기서 n은 1보다 크고 모듈의 개수보다 작습니다. 하나의 모듈을 변경하면 전체 애플리케이션의 일부일 뿐인 한 번들의 캐시가 무효화됩니다. 남은 응용 프로그램은 여전히 캐시됩니다.

더 많은 번들은 더 나은 캐싱 능력을 의미하지만, 더 적은 압축을 의미하기도 합니다.


AggressiveSplittingPlugin

AggressiveSplittingPlugin 은 웹팩 2에서 제공하는 도구입니다. 대부분의 웹팩 내부 기능은 이미 구현되어 있습니다. 이미 모듈의 그룹으로 구성된 청크가 존재하며, 이들은 출력 파일을 형성합니다. 또한 청크를 변경할 수 있는 최적화 단계도 있습니다. 이 최적화를 수행하기 위해 플러그인이 필요합니다.

AggressiveSplittingPlugin 은 원래 청크를 더 작은 청크로 분할합니다. 원하는 청크 크기를 지정할 수 있습니다. 이렇게 하면 캐싱은 향상되지만 압축(그리고 HTTP/1의 전송)은 약화됩니다.

유사한 모듈을 결합하기 위해 해당 모듈들은 분할하기 전에 알파벳순으로 (경로 기준) 정렬됩니다. 동일한 폴더에 있는 모듈들은 서로 관련이 있고 압축 관점에서 유사합니다. 이 정렬을 통해 이러한 모듈들은 동일한 청크에 포함됩니다.

이제 우리는 HTTP/2을 위한 효율적인 청킹을 가지고 있습니다.


응용 프로그램 변경사항

이게 끝이 아닙니다. 응용 프로그램이 업데이트되면, 이전에 생성된 청크를 재사용하기 위해 노력해야 합니다. 따라서 AggressiveSplittingPlugin 은 좋은 크기의 청크를 찾을 때마다 해당 청크의 모듈과 해시를 레코드에 저장합니다.

Records 는 웹팩의 상태 개념으로, 컴파일 사이에 유지되는 상태입니다. 이는 JSON 파일에 저장되고 읽힙니다.

AggressiveSplittingPlugin 이 다시 호출될 때, 먼저 records 에서 청크를 복원한 후 남은 모듈을 분할하려고 시도합니다. 이를 통해 캐시된 청크가 재사용되도록 보장합니다.


부트스트랩과 서버

이 기법을 사용하는 응용 프로그램은 더 이상 HTML 파일에 포함될 수 있는 단일 파일을 생성하지 않습니다. 대신 여러 개의 청크(chunk)가 생성되고 모두 로드되어야 합니다. 이 최적화를 사용하는 응용 프로그램에서는 모든 청크를 로드하기 위해 여러 개의 script 태그가 사용될 수 있습니다 (병렬로 로드됩니다). 아마도 다음과 같이 사용될 것입니다:


<script src="1ea296932eacbe248905.js"></script>
<script src="0b3a074667143853404c.js"></script>
<script src="0dd8c061aff2a2791815.js"></script>
<script src="191b812fa5f7504151f7.js"></script>
<script src="08702f45497539ef6ea6.js"></script>
<script src="195c9326275620b0e9c2.js"></script>
<script src="19817b3a0378aedb2143.js"></script>
<script src="0e7a65e649387d773247.js"></script>
<script src="13167c9702de79d2f4fd.js"></script>
<script src="1154be40ff0e8dd16e9f.js"></script>
<script src="129ce3c198a25d9ace74.js"></script>
<script src="032d1fc9a213dfaf2c79.js"></script>
<script src="07df084bbafc95c1df47.js"></script>
<script src="15c45a570bb174ae448e.js"></script>
<script src="02099ada43bbf02a9f73.js"></script>
<script src="17bc99aaed6b9a23da78.js"></script>
<script src="02d127598b1c99dcd2d0.js"></script>

웹팩은 이러한 청크를 생성일 순서대로 정렬됩니다. 가장 오래된 파일이 가장 먼저 실행되고, 가장 최근의 파일은 마지막에 실행됩니다. 브라우저는 가장 최근 파일을 다운로드하는 동안 캐시에 있는 파일을 실행할 수 있습니다. 오래된 파일은 이미 캐시에 있을 가능성이 더 높습니다.

HTTP/2 서버 푸시는 HTML 페이지를 요청할 때 이러한 청크를 클라이언트에게 보내는 데 사용할 수 있습니다. 가장 최근 파일을 먼저 푸시하는 것이 가장 좋습니다. 왜냐하면 오래된 파일은 이미 캐시에 있을 가능성이 높기 때문입니다. 클라이언트는 이미 가지고 있는 파일에 대한 푸시 응답을 취소할 수 있지만, 이는 왕복 시간이 소요됩니다.

on demand loading 을 위해 코드 분할을 사용할 때, 웹팩은 병렬 요청을 자동으로 처리합니다.


결론

webpack 2는 HTTP/2를 사용할 때 응용 프로그램의 캐싱과 전송을 개선하기 위한 도구를 제공합니다. 여러분의 스택이 미래 지향적이지 않을까 걱정하지 마세요.

AggressiveSplittingPlugin은 여전히 실험적인 기능입니다.

여러분의 경험에 대해서 매우 흥미롭게 생각합니다...

profile
JavaScript/React 개발자

0개의 댓글