Section 10. 최적화와 배포

OlMinJe·2025년 10월 23일

Next.js

목록 보기
20/20
post-thumbnail

1. 이미지 최적화(Image Optimization)

이미지는 웹 성능에서 생각보다 큰 비중을 차지한다.

대표적인 이미지 최적화 기법

  • WebP, AVIF 등 차세대 포맷으로 변환
  • 디바이스 해상도에 맞는 이미지 제공
  • Lazy Loading 적용 (보이는 순간에만 로드)
  • Blur Placeholder로 깔끔한 로딩 연출

Next.js는 성능 향상을 위해 Image 컴포넌트를 제공한다.

즉, 단순히 <img> 대신 <Image>를 사용하기만 해도
자동으로 리사이징, 포맷 변환, Lazy Loading, CDN 캐싱이 적용된다.
이미지 최적화에는 다양한 기법이 존재한다.

import Image from 'next/image';
//...
export default function BookItem({
  id,
  title,
  subTitle,
  description,
  author,
  publisher,
  coverImgUrl,
}: BookData) {
  return (
    <Link href={`/book/${id}`} className={style.container}>
      <Image src={coverImgUrl} width={80} height={105} alt={`도서 ${title}의 표시 이미지`} />
      <div>
        <div className={style.title}>{title}</div>
        <div className={style.subTitle}>{subTitle}</div>
        <br />
        <div className={style.author}>
          {author} | {publisher}
        </div>
      </div>
    </Link>
  );
}

⚠️ Invalid src prop 오류 해결하기

Next.js의 Image는 보안상 외부 도메인의 이미지를 기본적으로 차단한다.
그래서 외부 이미지를 사용하려면 next.config.js에 허용 도메인을 명시해야 한다.

import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  logging: {
    fetches: {
      fullUrl: true,
    },
  },
  images: {
    domains: ['shopping-phinf.pstatic.net'], // 외부 이미지 도메인 등록
  },
};

export default nextConfig;

설정 후 빌드하면, Next.js가 자동으로 해당 이미지를 프록시 캐싱 및 최적화해서 제공해준다!


SEO (Search Engine Optimization) — 검색 엔진 최적화

Next.js는 SEO를 위해 metadata라는 정식 속성을 제공한다.

페이지의 제목(title), 설명(description), OG 태그(Open Graph) 등을 손쉽게 설정할 수 있음


기본 메타데이터 설정하기

검색된 약속어 metadata를 사용하여 설정을 진행하면,

export const metadata: Metadata = {
  title: '한입 북스',
  description: '한입 북스에 등록된 도서를 만나보세요.',
  openGraph: {
    title: '한입 북스',
    description: '한입 북스에 등록된 도서를 만나보세요.',
    images: ['/thumbnail.png'],
  },
};

페이지가 검색 엔진에 더 잘 노출괴도, SNS 공유 시 썸네일이 깔끔하게 표시된다.


동적인 메타 데이터 설정하기

Next.js는 정적인 메타데이터뿐만 아니라,
페이지별 데이터에 따라 동적으로 메타정보를 설정할 수 있게 해준다.

export async function generateMetadata({
  searchParams,
}: {
  searchParams: Promise<{ q?: string }>;
}) {
  // 현재 페이지의 메타 데이터를 동적으로 생성하는 역할
  const { q } = await searchParams;

  return {
    title: `${q}: 한입북스 검색`,
    description: `${q}의 검색 결과입니다.`,
    openGraph: {
      title: `${q}: 한입북스 검색`,
      description: `${q}의 검색 결과입니다.`,
      images: ['/thumbnail.png'],
    },
  };
}

export default async function Page({ searchParams }: { searchParams: Promise<{ q?: string }> }) {
  const { q } = await searchParams;

이렇게 하면 검색 결과 페이지의 쿼리(q) 값에 따라
브라우저 탭 제목, 설명, OG 메타데이터가 동적으로 변한다.


API 기반 메타데이터 생성

도서 상세 페이지의 경우, 책 정보를 API로 불러와서 그 데이터를 기반으로 SEO 메타를 생성할 수 있다. (따봉)

export async function generateMetadata({ params }: { params: Promise<{ id: string }> }) {
  const { id } = await params;

  const response = await fetch(`${process.env.NEXT_PUBLIC_API_SERVER_URL}/book/${id}`);

  if (!response.ok) {
    throw new Error(response.statusText);
  }

  const book: BookData = await response.json();

  return {
    title: `${book.title} - 한입북스`,
    description: `${book.description}`,
    openGraph: {
      title: `${book.title} - 한입북스`,
      description: `${book.description}`,
      images: [book.coverImgUrl],
    },
  };
}

export default async function Page({ params }: { params: Promise<{ id: string }> }) {
  const { id } = await params;
//...

✅ API를 메타데이터 내부에서 직접 호출해도 안전한 이유는? Request Memoization

같은 페이지 내에서 동일한 API를 여러 번 호출하더라도 자동으로 한 번만 요청하고 캐싱해주는 아름다운 친구,
덕분에 generateMetadate()와 실제 페이지 렌더링에서 같은 데이터를 불러와도 불필요한 중복 요청이 발생하지 않는다.


✅ 정리하며

구분기능설명
Image 컴포넌트이미지 최적화WebP 변환, 리사이징, Lazy Loading 자동 적용
next.config.js외부 이미지 도메인 등록외부 리소스 접근 허용
MetadataSEO 설정페이지의 메타 정보 정의
generateMetadata동적 SEO검색어·데이터 기반 메타데이터 자동 생성
Request MemoizationAPI 중복 방지동일 요청을 한 번만 수행, 자동 캐싱

https://onebite-books-page-eta-flax.vercel.app/

profile
큐트걸

0개의 댓글