React에서는 index.html이 있기 때문에, 그냥 html,css,js 배울 때 처럼 body 내부에 script 태그를 집어넣어주면 됩니다.
하지만, Next.js에서는 눈씻고 찾아봐도 index.html은 보이지 않죠.
대신 layout.tsx에서 익숙한 코드를 볼 수 있습니다.
<html lang="en">
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
<Header />
{children}
</body>
</html>
하지만 이 코드에서 바로 <script>
태그로 외부 스크립트 로딩을 직접 넣는 것은 권장되지 않습니다.
Next.js에서 외부 스크립트를 불러올 때에는 next/script 컴포넌트를 사용해야합니다.
즉, 다음과 같이 사용해야합니다.
return (
<html lang="en">
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
<Header />
{children}
{/* ❌ 잘못된 예시 */}
<script
type="text/javascript"
src="//dapi.kakao.com/v2/maps/sdk.js?appkey=발급받은 APP KEY를 넣으시면 됩니다.&libraries=services,clusterer"
></script>
{/*✅ 잘된 예시*/}
<Script
strategy="beforeInteractive"
src={`//dapi.kakao.com/v2/maps/sdk.js?appkey=발급받은APPKEY&libraries=services,clusterer`}
/>
</body>
</html>
);
Next.js처럼 SSR + CSR이 혼합된 환경에서는 스크립트 로딩을 안전하고 최적화된 방식으로 관리하기 위해 반드시 next/script 컴포넌트를 사용하는 것이 좋습니다.
React는 라이브러리라 자율성이 높지만, Next.js는 프레임워크인 만큼 성능 최적화를 위해 공식적으로 권장하는 방법을 따르는 게 가장 안전하고 베스트겠죠?!
중복 로딩 방지
Next.js는 동일한 레이아웃에서 사용자가 여러 경로를 이동하더라도 스크립트가 한 번만 로드되도록 보장합니다. 따라서 불필요하게 중복되는 작업을 방지할 수 있습니다.
Next.js는 동일한 문서 내에서 같은 외부 스크립트를 여러 번 렌더해도 중복 삽입을 방지합니다.
따라서 전역이 아닌 필요한 페이지(또는 해당 세그먼트의 layout.tsx)에만 스크립트를 포함하면, 사용하지 않는 페이지에서의 불필요한 로드를 피할 수 있어 성능상 이점이 큽니다.
로딩 순서 제어 (strategy)
next/script는 strategy prop으로 스크립트 실행 시점을 제어할 수 있습니다.
일반 <script>
태그는 이런 제어가 불가능하기 때문에 블로킹 문제가 발생할 수 있습니다.
👉🏻 여기서 ‘블로킹 문제’란?
브라우저가 HTML을 파싱하다가<script>
태그를 만나면 해당 스크립트를 다 가져와서 실행할 때까지 렌더링을 멈추는 현상입니다. 즉, 사용자 입장에서는 화면이 늦게 뜨는 것처럼 보이게 되기 때문에 UX 측면에서 별로 좋지 않은 현상이겠죠 !!
SSR 호환성
Next.js는 서버에서 먼저 HTML을 렌더한 뒤 클라이언트에서 hydration을 하는데, <script>
를 직접 넣으면 hydration과 실행 타이밍이 꼬일 수 있습니다. next/script는 Next.js가 hydration 순서와 충돌하지 않게 자동 관리해줍니다.
👉🏻 hydration이란?
SSR로 그려진 정적인 HTML에 React의 동적인 기능을 주입하는 단계입니다.
서버에서 HTML 파일을 보내주면, 브라우저 쪽에서 React가 다시 동작하면서 HTML에 이벤트 핸들러(클릭, 입력 등)를 붙이는 작업을 hydration이라고 합니다.
그 외에도 next/script 컴포넌트를 사용할 경우, Next.js가 스크립트를 병렬로 preload하거나, 필요한 순간에만 로드하는 최적화를 진행해주고, React 컴포넌트로 관리되기 때문에 코드 일관성과 유지보수가 용이하다는 장점이 있습니다.