generateViewport#
- 상위 메뉴: Functions
- 전체 목차: Next.js 학습 문서
학습 목표#
- 브라우저의 뷰포트(
<meta name="viewport">) 및 테마 색상(<meta name="theme-color">)을 동적으로 설정하는generateViewport함수의 역할을 이해한다. - 정적
viewport객체와 동적generateViewport함수의 차이를 파악한다. - 미디어 쿼리(
prefers-color-scheme) 기반의 다크 모드 및 라이트 모드themeColor를 구성한다. - 메타데이터 스트리밍과의 차이점 및 Cache Components 환경에서의 동작 제약을 고려한다.
핵심 개념 및 설명#
Next.js 14부터 뷰포트 및 테마 색상 관련 설정은 metadata 객체에서 분리되어, 정적 viewport 객체 또는 동적 generateViewport 함수를 통해 정의된다.
generateViewport는 오직 Server Component에서만 지원된다.
app/layout.tsxtsx
import type { Viewport } from 'next'
export const viewport: Viewport = {
themeColor: [
{ media: '(prefers-color-scheme: light)', color: '#ffffff' },
{ media: '(prefers-color-scheme: dark)', color: '#000000' },
],
width: 'device-width',
initialScale: 1,
maximumScale: 1,
}
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ko">
<body>{children}</body>
</html>
)
}app/layout.jsjsx
export const viewport = {
themeColor: [
{ media: '(prefers-color-scheme: light)', color: '#ffffff' },
{ media: '(prefers-color-scheme: dark)', color: '#000000' },
],
width: 'device-width',
initialScale: 1,
maximumScale: 1,
}
export default function RootLayout({ children }) {
return (
<html lang="ko">
<body>{children}</body>
</html>
)
}알아두면 좋은 점 (generateViewport 모범 사례 및 내부 동작):
- Server Component 전용:viewport객체와generateViewport함수는 오직 Server Component에서만 export할 수 있다. 한 파일에서 두 개를 동시에 export할 수 없다.
- 정적 vs 동적 선택: 요청 정보(파라미터 등)에 의존하지 않는 정적 뷰포트 설정은 성능 최적화를 위해 비동기 함수 대신 정적 viewport 객체로 export해야 한다.- 기본 뷰포트 태그 자동 주입: Next.js는 기본적으로 <meta name="viewport" content="width=device-width, initial-scale=1"> 태그를 자동 생성하므로, 기본 동작을 덮어쓰거나 테마 색상을 추가할 때만 명시적으로 설정하면 된다.- 라우트별 다이나믹 뷰포트 격리: 특정 라우트에서만 다이나믹 generateViewport가 필요하다면, Route Group 및 복수 루트 레이아웃을 사용하여 해당 라우트를 격리함으로써 다른 정적 페이지들이 불필요하게 다이나믹 렌더링으로 전환되는 것을 방지할 수 있다.- 일반metadata와 달리viewport는 브라우저의 초기 화면 레이아웃과 렌더링에 직접적인 영향을 주므로 스트리밍(Streaming)될 수 없다. 따라서generateViewport가 지연되면 초기 페이지 응답이 블로킹될 수 있다.
- 동적 데이터가 필요하지만 런타임 요청 데이터가 아니라면 'use cache'를 함께 활용하는 것이 권장된다.주요 뷰포트 필드 (Viewport Fields)#
1. themeColor#
- 단일 색상 문자열 또는 미디어 쿼리 배열을 지정한다.
layout.tsxtsx
themeColor: [
{ media: '(prefers-color-scheme: light)', color: '#0ea5e9' },
{ media: '(prefers-color-scheme: dark)', color: '#0f172a' },
]2. colorScheme#
- 지원 색상 테마 (
'light','dark','light dark').
3. 모바일 뷰포트 크기 및 스케일 제어#
width:'device-width'또는 숫자.initialScale: 초기 배율 (기본값:1).maximumScale: 최대 확대 배율.userScalable: 사용자 확대/축소 허용 여부 (boolean).
동적 generateViewport 함수 예제#
app/category/[id]/page.tsxtsx
import type { Viewport } from 'next'
type Props = {
params: Promise<{ id: string }>
}
export async function generateViewport({ params }: Props): Promise<Viewport> {
const { id } = await params
const category = await db.category.findUnique({ where: { id } })
return {
themeColor: category?.brandColor || '#000000',
}
}
export default async function CategoryPage({ params }: Props) {
const { id } = await params
return <div>카테고리: {id}</div>
}app/category/[id]/page.jsjsx
export async function generateViewport({ params }) {
const { id } = await params
const category = await db.category.findUnique({ where: { id } })
return {
themeColor: category?.brandColor || '#000000',
}
}
export default async function CategoryPage({ params }) {
const { id } = await params
return <div>카테고리: {id}</div>
}Version History#
| 버전 | 변경 사항 |
|---|---|
v14.0.0 | viewport 및 generateViewport 도입 (metadata에서 분리) |
예제 및 데모 설계#
- OS 다크 모드 전환 시 브라우저 상단 주소창 테마 색상이 라이트(#ffffff)와 다크(#000000)로 자동 반응하는지 모바일 및 데스크톱 브라우저에서 검증한다.
generateViewport에 카테고리별 브랜드 색상을 매핑하여 라우트 전환에 따른 메타 태그 변화를 확인한다.width=device-width,initial-scale=1등의 기본 뷰포트 메타 태그가 올바르게 주입되는지 확인한다.
연습 문제#
- Next.js에서 다크 모드와 라이트 모드에 따라 브라우저 주소창 테마 색상을 다르게 지정하는 올바른
themeColor설정 방식은?
- A.
themeColor: 'auto' - B.
themeColor: [{ media: '(prefers-color-scheme: light)', color: '#fff' }, { media: '(prefers-color-scheme: dark)', color: '#000' }] - C.
metadata.theme = { dark: '#000', light: '#fff' } - D.
next.config.js의themeColor배열
정답 보기
정답: B
해설: Viewport 인터페이스의 themeColor는 prefers-color-scheme 미디어 쿼리 조건 객체들의 배열을 지원하여 시스템 테마에 맞는 색상을 동적으로 제공한다.
generateMetadata와 비교하여generateViewport가 가지는 주요 차이점은?
- A.
generateViewport는 Client Component에서만 실행된다. - B.
generateViewport는 초기 화면 렌더링에 즉시 필요하므로 메타데이터처럼 스트리밍될 수 없다. - C.
generateViewport는 비동기 호출을 지원하지 않는다. - D.
generateViewport는 TypeScript를 지원하지 않는다.
정답 보기
정답: B 해설: 뷰포트는 초기 브라우저 렌더링 영역 크기와 직결되므로 스트리밍으로 지연 주입될 수 없으며 초기 HTML과 함께 즉시 해석되어야 한다.
챕터 요약#
generateViewport와viewport는 브라우저 뷰포트 및 테마 색상을 정의하는 Server Component 전용 API다.- Next.js 14부터 기존
metadata객체에서 독립되었다. - 다크/라이트 모드별
themeColor설정을 지원한다. - 초기 렌더링 특성상 스트리밍이 불가능하므로 불필요한 동적 요청 지연을 피해야 한다.