2021년 Chrome Aurora팀은 Next.js에서 서드 파티 스크립트의 로드 성능을 개선하기 위해 스크립트 구성요소를 도입했습니다. 출시 이후 Google은 개발자가 서드 파티 리소스를 더 쉽고 빠르게 로드할 수 있도록 기능을 확장해 왔습니다.
이 블로그 게시물에서는 출시된 최신 기능, 특히 @next/third-parties 라이브러리에 대한 개요와 향후 로드맵에 포함된 계획의 개요를 제공합니다.
서드 파티 스크립트의 성능 영향
Next.js 사이트의 모든 서드 파티 요청의 41%는 스크립트입니다. 다른 콘텐츠 유형과 달리 스크립트를 다운로드하고 실행하는 데 상당한 시간이 걸릴 수 있으며, 이로 인해 렌더링이 차단되고 사용자 상호작용이 지연될 수 있습니다. Chrome 사용자 환경 보고서 (CrUX)의 데이터에 따르면 서드 파티 스크립트를 더 많이 로드하는 Next.js 사이트는 Interaction to Next Paint(INP) 및 최대 콘텐츠 페인트(LCP) 통과율이 낮습니다.
이 차트에서 관찰된 상관관계는 인과관계를 의미하지 않습니다. 하지만 로컬 실험에서는 서드 파티 스크립트가 페이지 성능에 상당한 영향을 미친다는 추가 증거를 제공합니다. 예를 들어 아래 차트는 무작위로 선택된 18개의 태그로 구성된 Google 태그 관리자 컨테이너를 인기 있는 Next.js 예시 앱인 Taxonomy에 추가할 때의 다양한 실험실 측정항목을 비교합니다.
WebPageTest 문서에서 이러한 타이밍이 측정되는 방식을 자세히 알아보세요. 한눈에 봐도 이러한 실험실 측정항목은 모두 GTM 컨테이너의 영향을 받는 것이 분명합니다. 예를 들어 INP에 가까운 유용한 실습 프록시인 총 차단 시간 (TBT)은 거의 20배 증가했습니다.
스크립트 구성요소
Next.js에 <Script>
구성요소를 제공할 때 기존 <script>
요소와 매우 유사한 사용자 친화적인 API를 통해 도입해야 했습니다. 개발자는 이 라이브러리를 사용하여 애플리케이션의 모든 구성요소에 서드 파티 스크립트를 같은 위치에 배치할 수 있으며, 중요한 리소스가 로드된 후 Next.js가 스크립트의 순서를 지정합니다.
<!-- By default, script will load after page becomes interactive -->
<Script src="https://example.com/sample.js" />
<!-- Script is injected server-side and fetched before any page hydration occurs -->
<Script strategy=”beforeInteractive” src="https://example.com/sample.js" />
<!-- Script is fetched later during browser idle time -->
<Script strategy=”lazyOnload” src="https://example.com/sample.js" />
Patreon, Target, Notion과 같은 인기 사이트를 비롯한 수만 개의 Next.js 애플리케이션에서 <Script>
구성요소를 사용합니다. 효과적임에도 불구하고 일부 개발자는 다음과 같은 문제에 관해 우려를 제기했습니다.
- 다양한 서드 파티 제공업체의 다양한 설치 안내를 준수하면서 Next.js 앱에
<Script>
구성요소를 배치할 위치(개발자 환경) - 다양한 서드 파티 스크립트에 사용하기에 가장 적합한 로드 전략(사용자 환경)
이러한 두 가지 문제를 모두 해결하기 위해 Google에서는 인기 있는 서드 파티에 맞게 최적화된 구성요소 및 유틸리티 세트를 제공하는 전문 라이브러리인 @next/third-parties
를 출시했습니다.
개발자 환경: 서드 파티 라이브러리를 더 쉽게 관리할 수 있도록 함
많은 서드 파티 스크립트가 상당수의 Next.js 사이트에서 사용되고 있으며, 그중 Google 태그 관리자가 가장 인기가 높아 사이트의 66%에서 사용되고 있습니다.
@next/third-parties
는 이러한 일반적인 사용 사례의 사용을 간소화하도록 설계된 상위 수준 래퍼를 도입하여 <Script>
구성요소를 기반으로 빌드됩니다.
import { GoogleAnalytics } from "@next/third-parties/google";
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
<GoogleTagManager gtmId="GTM-XYZ" />
</html>
);
}
널리 사용되는 또 다른 서드 파티 스크립트인 Google 애널리틱스(Next.js 사이트의 52%)에도 자체 전용 구성요소가 있습니다.
import { GoogleAnalytics } from "@next/third-parties/google";
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
<GoogleAnalytics gaId="G-XYZ" />
</html>
);
}
@next/third-parties
는 널리 사용되는 스크립트를 로드하는 프로세스를 간소화하지만 삽입과 같은 다른 서드 파티 카테고리의 유틸리티를 개발하는 기능도 확장합니다. 예를 들어 Google 지도 및 YouTube 삽입은 각각 8% 및 4%의 Next.js 웹사이트에서 사용되며, 더 쉽게 로드할 수 있도록 구성요소도 제공되었습니다.
import { GoogleMapsEmbed } from "@next/third-parties/google";
import { YouTubeEmbed } from "@next/third-parties/google";
export default function Page() {
return (
<>
<GoogleMapsEmbed
apiKey="XYZ"
height={200}
width="100%"
mode="place"
q="Brooklyn+Bridge,New+York,NY"
/>
<YouTubeEmbed videoid="ogfYd705cRs" height={400} params="controls=0" />
</>
);
}
사용자 환경: 서드 파티 라이브러리 로드 속도 개선
이상적인 환경에서는 널리 채택된 모든 서드 파티 라이브러리가 완전히 최적화되어 성능을 개선하는 추상화가 필요하지 않습니다. 하지만 그때까지는 Next.js와 같은 널리 사용되는 프레임워크를 통해 통합할 때 사용자 환경을 개선해 볼 수 있습니다. 다양한 로드 기법을 실험해 보고, 스크립트가 올바른 방식으로 시퀀싱되었는지 확인하고, 궁극적으로는 서드 파티 제공업체와 의견을 공유하여 업스트림 변경을 장려할 수 있습니다.
YouTube 삽입을 예로 들 수 있습니다. 일부 대체 구현이 기본 삽입보다 훨씬 우수한 성능을 제공하는 경우 현재 @next/third-parties
가 내보낸 <YouTubeEmbed>
구성요소는 lite-youtube-embed를 사용합니다. 'Hello, World' Next.js 비교로 표시하면 훨씬 더 빠르게 로드됩니다.
마찬가지로 Google 지도의 경우 지도 표시 영역에서 일정 거리에 있을 때만 로드되도록 삽입의 기본 속성으로 loading="lazy"
를 포함합니다. 특히 Google 지도 문서의 예시 코드 스니펫에 포함되어 있으므로 포함해야 하는 명백한 속성처럼 보일 수 있지만, Google 지도를 삽입하는 Next.js 사이트의 45%만 loading="lazy"
를 사용하고 있습니다.
웹 워커에서 서드 파티 스크립트 실행
@next/third-parties
에서 살펴보고 있는 한 가지 고급 기법은 서드 파티 스크립트를 웹 워커로 더 쉽게 오프로드하는 것입니다. Partytown과 같은 라이브러리에서 널리 사용되는 이 방법은 서드 파티 스크립트를 기본 스레드 외부로 완전히 재배치하여 페이지 성능에 미치는 서드 파티 스크립트의 영향을 크게 줄일 수 있습니다.
다음 애니메이션 GIF는 Next.js 사이트 내의 GTM 컨테이너에 다양한 <Script>
전략을 적용할 때 긴 작업과 기본 스레드 차단 시간의 변동을 보여줍니다. 전략 옵션 간에 전환하면 이러한 스크립트가 실행되는 시점이 지연될 뿐이지만 웹 워커로 이전하면 기본 스레드에서 걸리는 시간이 완전히 사라집니다.
이 특정 예에서는 GTM 컨테이너 및 관련 태그 스크립트의 실행을 웹 작업자로 이동하여 TBT를 92%줄였습니다.
주의 깊게 관리하지 않을 경우 이 기법으로 인해 많은 서드 파티 스크립트가 자동으로 중단되어 디버깅이 어려워질 수 있습니다. 앞으로 몇 개월 내에 @next/third-parties
에서 제공하는 서드 파티 구성요소가 웹 워커에서 실행될 때 올바르게 작동하는지 확인할 예정입니다. 그렇다면 개발자가 이 기법을 사용할 수 있는 간단한 방법(선택사항)을 제공하기 위해 노력할 것입니다.
다음 단계
이 패키지를 개발하는 과정에서 다른 프레임워크에서도 동일한 기본 기술을 활용할 수 있도록 서드 파티 로드 권장사항을 중앙 집중화해야 한다는 것이 분명해졌습니다. 이를 통해 JSON을 사용하여 서드 파티 로드 기법을 설명하는 라이브러리인 서드 파티 Capital을 빌드하게 되었습니다. 이 라이브러리는 현재 @next/third-parties
의 기반 역할을 합니다.
다음 단계로, Next.js에 제공되는 구성요소를 개선하는 데 계속 집중하고 다른 인기 프레임워크 및 CMS 플랫폼에 유사한 유틸리티를 포함하기 위한 노력을 확대할 예정입니다. 현재 Nuxt 유지보수자와 협력하고 있으며 가까운 시일 내에 Nuxt 생태계에 맞게 조정된 유사한 서드 파티 유틸리티를 출시할 계획입니다.
Next.js 앱에서 사용하는 서드 파티 중 하나가 @next/third-parties
에서 지원되는 경우 패키지를 설치하고 사용해 보세요. GitHub에 관한 의견을 보내주세요.