title: Script Component (스크립트 컴포넌트)
description: "Next.js 애플리케이션에서 내장된 next/script 컴포넌트를 사용하여 서드파티(제3자) 스크립트를 최적화해 보세요."
url: "https://nextjs.org/docs/app/api-reference/components/script"
version: 16.1.6
lastUpdated: 2026-02-27
prerequisites:
안녕하세요! 프론트엔드 개발의 세계로 오신 것을 환영합니다. 오늘은 Next.js에서 아주 중요한, 하지만 놓치기 쉬운 next/script 컴포넌트에 대해 함께 알아볼 거예요.
우리가 웹사이트를 만들다 보면 구글 애널리틱스나 카카오톡 공유하기, 결제 모듈 같은 외부 스크립트(서드파티 스크립트)를 불러와야 할 때가 정말 많죠? 그냥 HTML의 <script> 태그를 쓰면 되지 않나 싶겠지만, Next.js에서는 이 Script 컴포넌트를 사용해서 로딩 속도를 최적화하고 사용자 경험을 극대화할 수 있답니다.
이 API 참조 문서는 Script 컴포넌트에서 사용할 수 있는 다양한 props(속성들)을 이해하는 데 도움을 줄 거예요. 이 컴포넌트의 기능과 구체적인 사용법에 대해 더 깊이 알고 싶으시다면 Optimizing Scripts (스크립트 최적화) 페이지를 꼭 읽어보시는 것을 추천합니다!
import Script from 'next/script'
export default function Dashboard() {
return (
<>
<Script src="[https://example.com/script.js](https://example.com/script.js)" />
</>
)
}
import Script from 'next/script'
export default function Dashboard() {
return (
<>
<Script src="[https://example.com/script.js](https://example.com/script.js)" />
</>
)
}
💡 강사의 팁: Next.js를 쓸 때는 무조건
next/script를 쓰시는 습관을 들이는 게 좋습니다. 일반<script>태그를 사용하면 렌더링을 막아버려서 사이트가 버벅거리는(블로킹) 현상이 발생할 수 있거든요!
Script 컴포넌트에서 사용할 수 있는 속성(Props)들을 한눈에 알아보기 쉽게 정리해 드릴게요:
| 속성 (Prop) | 사용 예시 | 타입 (Type) | 필수 여부 (Required) |
|---|---|---|---|
src | src="http://example.com/script" | String | 인라인 스크립트(태그 내부에 직접 작성)가 아니라면 필수입니다 |
strategy | strategy="lazyOnload" | String | 선택 사항 (-) |
onLoad | onLoad={onLoadFunc} | Function | 선택 사항 (-) |
onReady | onReady={onReadyFunc} | Function | 선택 사항 (-) |
onError | onError={onErrorFunc} | Function | 선택 사항 (-) |
<Script /> 컴포넌트를 쓸 때 반드시 넣어야 하는 속성입니다.
src외부 스크립트의 URL을 지정하는 경로 문자열이에요. 완전한 외부 URL(절대 경로)을 적어도 되고, 프로젝트 내부의 경로를 적어도 됩니다. 스크립트 코드를 컴포넌트 안에 직접 작성하는 인라인 스크립트를 쓰는 경우가 아니라면, 이 src 속성은 무조건 넣어주셔야 해요!
<Script /> 컴포넌트는 필수 속성 외에도 정말 유용한 추가 속성들을 여러 개 제공합니다. 상황에 맞게 골라 쓰는 재미가 있죠.
strategy (로딩 전략)이 속성은 스크립트를 언제, 어떻게 불러올지 결정하는 아주 핵심적인 역할을 해요. 로딩 전략은 다음 네 가지 중에서 선택할 수 있답니다:
beforeInteractive: Next.js 코드가 실행되기 전, 그리고 페이지 하이드레이션(Hydration)이 일어나기 전에 스크립트를 불러옵니다.afterInteractive: (기본값) 일찍 불러오긴 하지만, 페이지의 하이드레이션이 어느 정도 진행된 후에 불러옵니다.lazyOnload: 브라우저가 한가할 때(idle time) 여유롭게 불러옵니다.worker: (실험적 기능) 메인 스레드가 아닌 웹 워커(web worker)에서 스크립트를 불러옵니다.💡 강사의 보충 설명: '하이드레이션(Hydration)'이란 서버에서 만들어진 뼈대(HTML)에 React의 생명력(JavaScript 기능)을 불어넣어 주는 과정이에요! 스크립트가 이 과정의 앞이나 뒤, 언제 실행되느냐에 따라 페이지 성능이 크게 달라지기 때문에
strategy속성이 무척 중요합니다.
beforeInteractivebeforeInteractive 전략을 사용하는 스크립트는 서버에서 내려주는 초기 HTML에 주입(inject)됩니다. 그래서 어떤 Next.js 모듈보다도 먼저 다운로드되고, 배치된 순서대로 실행돼요.
이 전략이 지정된 스크립트는 우리 사이트의 핵심 코드보다 먼저 미리 로드(preload)되고 가져와집니다. 하지만 정말 다행인 점은, 이 스크립트가 실행된다고 해서 페이지 하이드레이션 과정이 멈추거나 차단되지는 않는다는 거예요.
beforeInteractive 스크립트는 반드시 최상위 레이아웃 파일(app/layout.tsx) 안에 넣어야 합니다. 이 전략은 애플리케이션의 어떤 페이지에 들어가든 서버 사이드에서 스크립트가 미리 로드되어야 하는, '전체 사이트에 꼭 필요한 스크립트'를 위해 만들어졌거든요.
이 전략은 가능하면 최대한 빨리 가져와야 하는 '필수적인 스크립트'에만 제한적으로 사용해야 합니다. 남발하면 첫 화면 뜨는 속도가 느려질 수 있어요!
import Script from 'next/script'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
{children}
<Script
src="[https://example.com/script.js](https://example.com/script.js)"
strategy="beforeInteractive"
/>
</body>
</html>
)
}
import Script from 'next/script'
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
{children}
<Script
src="[https://example.com/script.js](https://example.com/script.js)"
strategy="beforeInteractive"
/>
</body>
</html>
)
}
알아두면 좋은 점 (Good to know):
beforeInteractive를 사용하는 스크립트는 컴포넌트 내의 어디에 배치하든 상관없이, 항상 HTML 문서의head태그 안에 주입된답니다.
beforeInteractive로 최대한 빨리 불러와야 하는 스크립트의 좋은 예시는 다음과 같아요:
afterInteractiveafterInteractive 전략을 사용하는 스크립트는 클라이언트 측에서 HTML에 주입되며, 페이지의 하이드레이션이 일부(또는 전부) 진행된 이후에 로드됩니다. 이것이 Script 컴포넌트의 기본 전략(Default) 이에요! 가급적 빨리 불러와야 하긴 하지만, 굳이 우리 사이트의 핵심 Next.js 코드보다 먼저 불러올 필요는 없는 스크립트들에 사용하시면 됩니다.
afterInteractive 스크립트는 어떤 페이지나 레이아웃 파일에든 넣을 수 있어요. 그리고 사용자가 브라우저에서 해당 페이지(또는 해당 그룹의 페이지들)를 열었을 때만 로드되고 실행된답니다.
import Script from 'next/script'
export default function Page() {
return (
<>
<Script src="[https://example.com/script.js](https://example.com/script.js)" strategy="afterInteractive" />
</>
)
}
afterInteractive를 사용하기 딱 좋은 스크립트의 예시는 이런 것들이 있어요:
lazyOnloadlazyOnload 전략을 사용하는 스크립트는 클라이언트 측에서 브라우저가 한가한 시간(idle time)에 HTML에 주입됩니다. 페이지의 모든 필수 리소스가 전부 다 불러와진 이후에나 로드되죠. 이 전략은 일찍 불러올 필요가 전혀 없는 백그라운드용 스크립트나 중요도가 낮은 스크립트에 사용해야 해요.
마찬가지로 어떤 페이지나 레이아웃에든 넣을 수 있고, 사용자가 브라우저에서 해당 페이지를 열었을 때만 실행됩니다.
import Script from 'next/script'
export default function Page() {
return (
<>
<Script src="[https://example.com/script.js](https://example.com/script.js)" strategy="lazyOnload" />
</>
)
}
당장 로드할 필요가 없어서 lazyOnload로 느긋하게 불러와도 되는 스크립트의 예시는 다음과 같습니다:
💡 강사의 팁: 실제 실무에서 렌더링 성능 최적화를 할 때 이
lazyOnload가 정말 큰 효자 노릇을 합니다! 사용자가 화면을 보자마자 채팅창을 누르진 않잖아요? 이런 것들은 무조건lazyOnload로 미뤄두면 초기 체감 속도가 확 빨라집니다.
worker주의 (Warning):
worker전략은 아직 불안정한 실험적 기능(not yet stable)이며, 현재 App Router에서는 작동하지 않습니다. 사용할 때 각별한 주의가 필요해요!
worker 전략을 사용하는 스크립트는 메인 스레드의 부담을 덜어주기 위해 웹 워커(web worker)로 분리되어 처리됩니다. 이렇게 하면 메인 스레드에서는 우리 웹사이트의 가장 중요한 필수 리소스들만 안전하게 처리할 수 있게 되죠. 어떤 스크립트든 이 전략을 적용해볼 수는 있지만, 모든 서드파티 스크립트가 지원된다고 보장할 수 없는 고급(advanced) 사용법이에요.
이 전략을 사용하려면 먼저 next.config.js 파일에서 nextScriptWorkers 플래그를 활성화해 주어야 합니다.
module.exports = {
experimental: {
nextScriptWorkers: true,
},
}
그리고 현재로서는 오직 pages/ 디렉토리 방식에서만 사용할 수 있답니다:
import Script from 'next/script'
export default function Home() {
return (
<>
<Script src="[https://example.com/script.js](https://example.com/script.js)" strategy="worker" />
</>
)
}
import Script from 'next/script'
export default function Home() {
return (
<>
<Script src="[https://example.com/script.js](https://example.com/script.js)" strategy="worker" />
</>
)
}
onLoad주의 (Warning):
onLoad는 아직 Server Components(서버 컴포넌트)에서 작동하지 않으므로 오직 Client Components(클라이언트 컴포넌트) 안에서만 사용해야 합니다. 또한onLoad는beforeInteractive전략과 함께 사용할 수 없어요. 이 경우에는 대신onReady를 사용하는 것을 고려해 보세요!
어떤 서드파티 스크립트들은 불러오기가 완료된 직후에, 콘텐츠를 세팅하거나 특정 함수를 호출하기 위해 우리가 직접 자바스크립트 코드를 한 번 실행해 주어야 할 때가 있습니다. 만약 여러분이 afterInteractive나 lazyOnload 전략으로 스크립트를 불러오고 있다면, onLoad 속성을 사용해서 스크립트 로드가 끝난 직후에 특정 코드를 실행시킬 수 있어요.
아래는 lodash 라이브러리가 완전히 로드된 이후에만 특정 메서드를 실행하는 예시입니다.
'use client'
import Script from 'next/script'
export default function Page() {
return (
<>
<Script
src="[https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js](https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js)"
onLoad={() => {
console.log(_.sample([1, 2, 3, 4]))
}}
/>
</>
)
}
'use client'
import Script from 'next/script'
export default function Page() {
return (
<>
<Script
src="[https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js](https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js)"
onLoad={() => {
console.log(_.sample([1, 2, 3, 4]))
}}
/>
</>
)
}
💡 강사의 팁: 실무에서 결제 모듈(예: 아임포트, 토스 등)을 붙일 때 "SDK가 로드되지 않았습니다" 같은 에러 많이 겪어보셨을 거예요. 스크립트가 다 받아지기도 전에 코드가 먼저 실행돼서 그런데요, 그럴 때 이
onLoad안에 결제 초기화 로직을 넣어주면 깔끔하게 해결된답니다! 파일 맨 위에 꼭'use client'적어주시는 것도 잊지 마시고요.
onReady주의 (Warning):
onReady역시 아직 서버 컴포넌트에서는 작동하지 않으며, 오직 클라이언트 컴포넌트에서만 사용할 수 있습니다.
일부 서드파티 스크립트는 스크립트 로드가 끝난 후뿐만 아니라, 컴포넌트가 마운트될 때마다(예를 들어 다른 페이지로 이동했다가 다시 돌아왔을 때) 자바스크립트 코드를 다시 실행해야 하는 경우가 있어요. onReady 속성을 사용하면, 스크립트가 처음 로드되었을 때는 물론이고 이후에 컴포넌트가 다시 마운트될 때마다 계속 코드를 실행할 수 있습니다.
아래는 컴포넌트가 마운트될 때마다 구글 지도(Google Maps)를 다시 인스턴스화하여 삽입하는 예시입니다:
'use client'
import { useRef } from 'react'
import Script from 'next/script'
export default function Page() {
const mapRef = useRef()
return (
<>
<div ref={mapRef}></div>
<Script
id="google-maps"
src="[https://maps.googleapis.com/maps/api/js](https://maps.googleapis.com/maps/api/js)"
onReady={() => {
new google.maps.Map(mapRef.current, {
center: { lat: -34.397, lng: 150.644 },
zoom: 8,
})
}}
/>
</>
)
}
'use client'
import { useRef } from 'react'
import Script from 'next/script'
export default function Page() {
const mapRef = useRef()
return (
<>
<div ref={mapRef}></div>
<Script
id="google-maps"
src="[https://maps.googleapis.com/maps/api/js](https://maps.googleapis.com/maps/api/js)"
onReady={() => {
new google.maps.Map(mapRef.current, {
center: { lat: -34.397, lng: 150.644 },
zoom: 8,
})
}}
/>
</>
)
}
💡 보충 설명:
onLoad와onReady의 차이가 헷갈리시죠?onLoad는 스크립트 파일을 다운받고 최초 1번만 실행됩니다. 반면에onReady는 스크립트가 이미 받아져 있더라도, 사용자가 메뉴를 클릭해서 이 컴포넌트가 화면에 다시 나타날 때마다(리마운트) 계속 실행됩니다. 지도를 그리는 코드는 화면에 다시 들어올 때마다 새로 그려줘야 하니까onReady가 찰떡이죠!
onError주의 (Warning):
onError기능도 서버 컴포넌트에서는 동작하지 않으며, 클라이언트 컴포넌트에서만 써야 합니다. 또한beforeInteractive전략과는 함께 쓸 수 없어요.
가끔 통신 문제나 서버 오류 등으로 스크립트를 불러오는 데 실패할 때가 있죠. 이렇게 에러가 났을 때를 캐치해서 대처하고 싶다면 onError 속성을 사용하시면 됩니다:
'use client'
import Script from 'next/script'
export default function Page() {
return (
<>
<Script
src="[https://example.com/script.js](https://example.com/script.js)"
onError={(e: Error) => {
console.error('Script failed to load', e)
}}
/>
</>
)
}
'use client'
import Script from 'next/script'
export default function Page() {
return (
<>
<Script
src="[https://example.com/script.js](https://example.com/script.js)"
onError={(e) => {
console.error('Script failed to load', e)
}}
/>
</>
)
}
💡 강사의 팁: 만약 광고 스크립트나 외부 폰트를 불러오는 게 실패했을 때, 이
onError를 이용해서 사용자에게 기본 UI(fallback)를 보여주거나 Sentry 같은 에러 로깅 툴로 에러를 전송하도록 구성하면 아주 튼튼한 웹 애플리케이션을 만들 수 있습니다.
Script 컴포넌트가 언제 어떻게 발전해왔는지 확인해 보세요:
| 버전 (Version) | 변경 사항 (Changes) |
|---|---|
v13.0.0 | beforeInteractive와 afterInteractive 전략이 App Router(app 폴더)를 지원하도록 수정되었습니다. |
v12.2.4 | onReady 속성이 새롭게 추가되었습니다. |
v12.2.2 | beforeInteractive 전략을 사용하는 next/script를 _document 안에도 넣을 수 있게 허용되었습니다. |
v11.0.0 | next/script 컴포넌트가 처음으로 세상에 소개되었습니다. |
모든 공식 문서의 체계적인 개요를 확인하고 싶으시다면, https://nextjs.org/docs/sitemap.md를 참고해 주세요.
또한 사용 가능한 모든 문서의 전체 인덱스를 보시려면, https://nextjs.org/docs/llms.txt를 확인해 주시면 됩니다.
공부하시느라 정말 고생 많으셨습니다! 직접 코드 에디터에서 다양한 전략(strategy)을 테스트해 보시는 걸 강력히 추천드려요. 화이팅!