[Next.js] Next.js의 next/script에 대해서 (공식문서 및 최적화 테크닉)

Date:

카테고리:

태그:

Script Optimization

Application Scripts

전역에 스크립트 로드

  • 사용자 지정 _appnext/script 를 불러와 적용
  • 스크립트는 애플리케이션의 모든 경로에 액세스할 때 로드되고 실행
  • Next.js는 사용자가 여러 페이지를 탐색해도 스크립트를 한 번만 로드
❗ 성능 최적화를 위해서는 되도록 특정 페이지에만 스크립트를 포함해야 함
// pages/_app.js

import Script from 'next/script'

export default function **MyApp**({ Component, pageProps }) {
  return (
    <>
      <Component {...pageProps} />
      <Script src="경로명" />
    </>
  )
}

전략

  • strategy 속성을 사용하여 스크립트의 로드 동작을 조정할 수 있음

    전략명 동작
    afterInteractive [기본값] 페이지에 일부 또는 전체 하이드레이션 발생 후에 스크립트 로드
    beforeInteractive Next.js 코드 로딩과 페이지 하이드레이션 발생 전 스크립트 로드
    lazyOnload 브라우저 유휴 시간 동안 스크립트를 lazyload
    worker [실험 기능] 스크립트를 웹 워커에서 로드
  • [Appendix] 하이드레이션이란(Hydration)?

    • 페이지 내 HTML를 pre-loading 하고 이후에 자바스크립트 요소를 매칭시키는 과정
    • 사용자는 빠르게 화면 UI 컴포넌트를 볼 수 있고, 인터렉션에 필요한 JS는 추후 다운로드
    • 자바스크립트 요소가 DOM 요소에 찾아 들어가는 방식이라 repaint 되지 않음

전략별 자세한 내용은 아래 링크에서 확인

Script API (전략)

web worker에 스크립트 오프로드 (실험 기능)

❗ `worker` 전략은 stable 아님 /  앱 디렉토리에서 아직 작동하지 않음

[Appendix] 오프로드란(offload)?

  • 연산 작업을 외부로 전송해서 처리

    💡 계산 오프로딩은 리소스 집약적인 계산 작업을 하드웨어 가속기와 같은
    별도의 프로세서 또는 클러스터, 그리드 또는 클라우드와 같은
    외부 플랫폼으로 전송하는 것입니다. (…)
    

    [참고 자료] 위키피디아 - Computation offloading

  • worker 전략을 사용하는 스크립트는 파티타운이 있는 웹 워커에서 오프로드되고 실행
  • 메인 스레드를 나머지 애플리케이션 코드에 사용하여 사이트의 성능을 향상

적용 방법

  • next.config.js 에서 nextScriptWorkers 플래그 활성화

    module.exports = {
      experimental: {
        nextScriptWorkers: true,
      },
    };
    
  • npm run dev 실행시 Next.js 가 필요한 패키지 설치 과정 안내

    npm run dev
    (...)
    Please install Partytown by running npm install @builder.io/partytown
    
  • 설치 후 strategy="worker" 정의 시 Partytown이 인스턴스화되고 스크립트가 웹 워커로 오프로드

    // pages/home.tsx
    
    import Script from "next/script";
    
    export default function Home() {
      return (
        <>
          <Script src="https://example.com/script.js" strategy="worker" />
        </>
      );
    }
    
  • 웹 워커에서 스크립트 로드 시 트레이드오프에 대해 고려할 점 [참고 자료] Trade-Offs - Partytown

인라인 스크립트

  • 인라인 스크립트 또는 외부 파일에서 로드되지 않은 스크립트도 스크립트 컴포넌트에서 지원
    • 중괄호 안에 JavaScript 작성하는 방법
      <Script id="show-banner">
        {`document.getElementById('banner').classList.remove('hidden')`}
      </Script>
      
    • dangerouslySetInnerHTML 속성을 사용하는 방법
      <Script
        **id="show-banner"**
        dangerouslySetInnerHTML=
      />
      
❗ Next.js가 스크립트를 추적 및 최적화하려면 인라인 스크립트에 id 속성을 할당해야 함

추가 코드 실행 (후속 처리 메서드)

핸들러 명 실행 타이밍
onLoad 스크립트 로딩 완료 후 코드 실행
onReady 스크립트 로딩 완료 후 컴포넌트가 마운트될 때마다 코드 실행
onError 스크립트 로딩에 실패 시 코드를 실행
❗ "use client”가 정의된 클라이언트 컴포넌트 내부에서 사용할 때만 작동
"use client";

import Script from "next/script";

export default function Page() {
  return (
    <>
      <Script
        src="https://example.com/script.js"
        onLoad={() => {
          console.log("Script has loaded");
        }}
      />
    </>
  );
}

[참고 자료] Script API (후속처리 메서드)

추가 속성

  • nonce 또는 사용자 정의 데이터 속성 포함 시 <script> 요소로 자동 전달

    import Script from 'next/script'
    
    export default function Page() {
      return (
        <>
          <Script
            src="https://example.com/script.js"
            **id="example-script"
            nonce="XUENAJFW"
            data-test="script"**
          />
        </>
      )
    }
    

[Appendix] nonce 란?

  • ‘Number Used Once’의 약자로, 암호학적으로 사용되는 일회용 번호
  • Nonce는 주로 Content Security Policy (CSP)와 관련하여 사용
  • <script> , <style> nonce 속성을 추가하여 스크립트나 스타일에 대해 CSP가 적용

[참고 자료] nonce - HTML: HyperText Markup Language - MDN
[참고 자료] Content Security Policy (CSP) - Material UI

[Appendix] script 의 async , defer 의 과정을 도식화한 장표

Untitled

React 카테고리 내 다른 글 보러가기

댓글 남기기