이미지는 웹사이트 페이지 로딩에 있어 상당히 큰 부분을 차지합니다. 이는 초기 페이지 로딩 속도에 있어서도 영향을 미치게됩니다. Next의 Image 컴포넌트는 html의 img 태그를 확장해서 자동으로 이미지 최적화를 합니다.
Image 컴포넌트에 width, height 값을 미리 제공하면 가로 세로 비율을 파악해서 layout shift를 피할 수 있습니다. width, height로 제공한 값은 비율 계산에 사용되고 실제 이미지 사이즈를 결정하지는 않습니다.
src의 실제 경로 매핑을 위해서 loader 함수가 사용됩니다. loader는 사이즈별로 url을 여러개 만듭니다. 기본적으로 loader는 최적화한 이미지를 Next js 서버에 저장해둡니다. 만약 CDN이나 이미지 서버에서 직접 사진을 로딩하려면 커스텀 loader를 사용해야 합니다.
스크롤 하지 않고 페이지의 처음부터 사용자에게 보여줘야 하는 이미지가 있다면 priority 속성을 줘서 더 빠른 로딩을 시도할 수 있습니다.
레이아웃 이동을 막기위해 항상 이미지의 사이즈를 제공하는 것이 좋습니다.
1. next js에 소스 코드와 같이 저장한 로컬 이미지의 경우 자동으로 사이즈가 적용됩니다.
2. 명시적으로 width, height를 지정하는 방법이 있습니다.
3. fill 옵션을 사용하여 부모 엘리먼트의 크기만큼 차지할 수 있습니다. 부모 엘리먼트는 display: block; position: relative로 설정되어 있어야합니다.
next.config.js에서 원격 이미지 허용, 이미지 크기 breakpoint 설정, 캐싱 전략 수정을 할 수 있습니다.
next/font는 자동으로 폰트를 최적화하고 외부 네트워크로의 요청을 제거합니다. 빌드 시 폰트 파일을 자체적으로 호스팅, CSS의 size-adjust 속성을 사용해서 레이아웃 이동을 막습니다.
import { Roboto } from 'next/font/google'
const roboto = Roboto({
weight: ['400', '700'],
style: ['normal', 'italic'],
subsets: ['latin'],
display: 'swap',
})
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en" className={roboto.className}>
<body>{children}</body>
</html>
)
}
위와 같이 구글 폰트에서 필요한 옵션을 넣고 변수로 정의해서 사용할 수 있습니다.
const roboto = localFont({
src: [
{
path: './Roboto-Regular.woff2',
weight: '400',
style: 'normal',
},
{
path: './Roboto-Italic.woff2',
weight: '400',
style: 'italic',
},
{
path: './Roboto-Bold.woff2',
weight: '700',
style: 'normal',
},
{
path: './Roboto-BoldItalic.woff2',
weight: '700',
style: 'italic',
},
],
})
구글 폰트가 아니더라도 경로를 지정하여 폰트 변수를 만들 수 있습니다.
또한 css 변수로 정의하여 css에서 var(--font-name)과 같이 사용할 수도 있습니다.
써드파티 스크립트를 가져올 때 Next의 Script 태그를 사용할 수 있습니다. 레이아웃 파일에 적용한다고 하면 여러 url 경로를 오갈 때 한 번만 로딩되도록 보장합니다.
인라인 스크립트 작성 시 중괄호 안에 js 코드를 넣거나 dangerouslySetInnerHTML 속성을 통해서 코드를 넣을 수 있습니다. 이 때 Script 태그에 id 속성 값을 필수로 제공해야합니다.
onLoad, onReady(스크립트 로드 + 컴포넌트 마운트), onError와 같은 이벤트 핸들러를 설정할 수 있습니다.
Metadata API로 html head 태그에 들어가 meta, link 태그를 설정할 수 있습니다. Metadata API는 서버 컴포넌트에서만 사용할 수 있습니다.
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: '...',
description: '...',
}
export default function Page() {}
import type { Metadata, ResolvingMetadata } from 'next'
type Props = {
params: { id: string }
searchParams: { [key: string]: string | string[] | undefined }
}
export async function generateMetadata(
{ params, searchParams }: Props,
parent: ResolvingMetadata
): Promise<Metadata> {
// read route params
const id = params.id
// fetch data
const product = await fetch(`https://.../${id}`).then((res) => res.json())
// optionally access and extend (rather than replace) parent metadata
const previousImages = (await parent).openGraph?.images || []
return {
title: product.title,
openGraph: {
images: ['/some-specific-page-image.jpg', ...previousImages],
},
}
}
export default function Page({ params, searchParams }: Props) {}
app 폴더 안에 다음과 같은 파일을 저장하면 메타 데이터로 사용됩니다.
다음 두 태그는 Next에서 기본적으로 제공해줍니다.
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
JSON-LD는 검색 엔진에 의해 인식되는 구조화된 데이터 포맷입니다. script 태그에 innerHTML로 제공하는 것을 추천합니다.
Next는 public 폴더 안에 있는 파일을 정적 컨텐츠로 사용할 수 있습니다. 기본적으로 /인 루트 경로에 파일 경로를 추가해서 url로 접근할 수 있습니다.