Next.js 통합#
@snapkit-studio/nextjs 패키지는 Next.js와의 깊이 있는 통합을 제공하며, Next.js Image 컴포넌트 API와 완전히 호환되면서 Snapkit의 강력한 변환 기능을 추가합니다.
설치#
Next.js 프로젝트에 Snapkit을 설치하세요:
npm install @snapkit-studio/nextjs
# 또는
yarn add @snapkit-studio/nextjs
# 또는
pnpm add @snapkit-studio/nextjs빠른 시작#
환경 변수 설정#
먼저 .env.local에서 환경 변수를 설정하세요:
NEXT_PUBLIC_SNAPKIT_ORGANIZATION_NAME=your-organization-name
NEXT_PUBLIC_SNAPKIT_DEFAULT_QUALITY=85
NEXT_PUBLIC_SNAPKIT_DEFAULT_OPTIMIZE_FORMAT=autoApp Router 설정#
루트 레이아웃에서 Snapkit을 설정하세요:
// app/layout.tsx
import { SnapkitProvider } from "@snapkit-studio/nextjs";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ko">
<body>
<SnapkitProvider baseUrl="https://cdn.snapkit.studio/snapkit" organizationName="your-org" defaultQuality={85} defaultFormat="auto">
{children}
</SnapkitProvider>
</body>
</html>
);
}Pages Router 설정#
Pages Router의 경우, _app.tsx에 provider를 추가하세요:
// pages/_app.tsx
import type { AppProps } from "next/app";
import { SnapkitProvider } from "@snapkit-studio/nextjs";
export default function App({ Component, pageProps }: AppProps) {
return (
<SnapkitProvider baseUrl="https://cdn.snapkit.studio/snapkit" organizationName="your-org" defaultQuality={85} defaultFormat="auto">
<Component {...pageProps} />
</SnapkitProvider>
);
}주요 기능#
드롭인 교체#
설정 변경 없이 Next.js Image 컴포넌트를 교체하세요:
// 이전
import Image from "next/image";
// 이후
import { Image } from "@snapkit-studio/nextjs";
// 사용법은 동일하게 유지
<Image src="/hero.jpg" alt="히어로 이미지" width={800} height={600} priority />;향상된 변환#
Next.js 기능을 넘어서는 강력한 변환 기능을 추가하세요:
import { Image } from "@snapkit-studio/nextjs";
<Image
src="/product.jpg"
alt="제품 이미지"
width={400}
height={300}
transforms={{
format: "auto",
quality: 90,
sharpen: true,
blur: 0,
grayscale: false,
}}
className="rounded-lg shadow-md"
/>;자동 최적화#
포맷 선택#
브라우저 지원에 따라 자동으로 최신 포맷을 제공하세요:
<Image
src="/photo.jpg"
width={600}
height={400}
transforms={{
format: "auto", // WebP, AVIF 또는 원본 포맷 제공
}}
/>품질 조정#
네트워크 인식 품질 최적화:
<Image
src="/high-res.jpg"
width={1200}
height={800}
transforms={{
quality: "auto", // 연결 속도에 따라 조정
}}
/>Next.js 전용 기능#
이미지 최적화#
정적 Import#
빌드 타임 최적화와 함께 정적 이미지 import를 완전히 지원:
import heroImage from "@/public/hero.jpg";
<Image src={heroImage} alt="히어로" placeholder="blur" priority transforms={{ format: "auto" }} />;동적 Import#
동적으로 로드되는 이미지의 경우:
<Image
src={`/products/${productId}.jpg`}
width={500}
height={500}
transforms={{
format: "auto",
fit: "cover",
}}
/>반응형 이미지#
컨테이너 채우기#
반응형 컨테이너 기반 레이아웃의 경우:
<div className="relative aspect-video">
<Image src="/banner.jpg" alt="배너" fill sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw" className="object-cover" transforms={{ format: "auto" }} />
</div>아트 디렉션#
다양한 브레이크포인트를 위한 다른 이미지:
<picture>
<source media="(max-width: 768px)" srcSet="/mobile-hero.jpg" />
<Image src="/desktop-hero.jpg" width={1920} height={1080} alt="반응형 히어로" transforms={{ format: "auto" }} />
</picture>성능 기능#
우선순위 로딩#
LCP 최적화를 위해:
<Image
src="/above-fold.jpg"
width={1200}
height={600}
priority
transforms={{
format: "auto",
quality: 90,
}}
/>플레이스홀더와 함께 지연 로딩#
부드러운 로딩 경험:
<Image src="/gallery-image.jpg" width={400} height={300} placeholder="blur" blurDataURL="data:image/jpeg;base64,..." loading="lazy" />설정#
next.config.js 설정#
Snapkit을 이미지 최적화 솔루션으로 설정하세요:
// next.config.js
module.exports = {
images: {
domains: ["cdn.snapkit.studio/snapkit"],
loader: "custom",
loaderFile: "./snapkit-loader.js",
},
};커스텀 로더#
고급 사용 사례를 위한 커스텀 로더 생성:
// snapkit-loader.js
export default function snapkitLoader({ src, width, quality }) {
const url = new URL(`https://your-org-cdn.snapkit.studio/${src}`);
// Build transform string with colon-separated key:value pairs
const transforms = [`w:${width}`, `q:${quality || 75}`, "format:auto"];
url.searchParams.set("transform", transforms.join(","));
return url.href;
}App Router 기능#
서버 컴포넌트#
React Server Components를 완전히 지원:
// app/gallery/page.tsx
import { Image } from "@snapkit-studio/nextjs";
export default async function Gallery() {
const images = await fetchImages();
return (
<div className="grid grid-cols-3 gap-4">
{images.map((img) => (
<Image key={img.id} src={img.url} width={400} height={300} alt={img.alt} transforms={{ format: "auto" }} />
))}
</div>
);
}클라이언트 컴포넌트#
클라이언트 사이드 기능과의 원활한 통합:
"use client";
import { useState } from "react";
import { Image } from "@snapkit-studio/nextjs";
export default function InteractiveGallery() {
const [selectedImage, setSelectedImage] = useState(0);
return (
<Image
src={images[selectedImage]}
width={800}
height={600}
transforms={{
format: "auto",
quality: 90,
}}
/>
);
}고급 사용법#
메타데이터 생성#
SEO와 소셜 공유를 위해:
// app/products/[id]/page.tsx
import { Metadata } from "next";
export async function generateMetadata({ params }): Promise<Metadata> {
const product = await getProduct(params.id);
return {
openGraph: {
images: [
{
url: `https://your-cdn.snapkit.studio/${product.image}?transform=w:1200,h:630,fit:cover`,
width: 1200,
height: 630,
},
],
},
};
}ISR과 SSG#
Incremental Static Regeneration을 완전히 지원:
// app/blog/[slug]/page.tsx
export const revalidate = 3600; // 매 시간마다 재검증
export default async function BlogPost({ params }) {
const post = await getPost(params.slug);
return <Image src={post.featuredImage} width={1200} height={600} alt={post.title} priority transforms={{ format: "auto" }} />;
}Edge Runtime#
Edge runtime에 최적화:
export const runtime = "edge";
export default function EdgeOptimizedPage() {
return (
<Image
src="/edge-optimized.jpg"
width={600}
height={400}
transforms={{
format: "auto",
quality: 85,
}}
/>
);
}마이그레이션 가이드#
next/image에서#
최소한의 변경이 필요합니다:
// 1단계: import 업데이트
- import Image from 'next/image';
+ import { Image } from '@snapkit-studio/nextjs';
// 2단계: transforms 추가 (선택사항)
<Image
src="/photo.jpg"
width={500}
height={300}
+ transforms={{ format: 'auto' }}
/>레거시 Next.js에서#
Next.js 12 이하 버전의 경우:
// 이전 (Next.js 12)
<Image
src="/photo.jpg"
width={500}
height={300}
layout="responsive"
/>
// 이후 (Snapkit 사용)
<Image
src="/photo.jpg"
width={500}
height={300}
sizes="100vw"
style={{
width: '100%',
height: 'auto',
}}
transforms={{ format: 'auto' }}
/>성능 최적화#
빌드 타임 최적화#
빌드 중에 최적화된 이미지 생성:
// next.config.js
module.exports = {
experimental: {
optimizeImages: true,
},
};런타임 최적화#
사용자 컨텍스트에 기반한 동적 최적화:
<Image
src="/dynamic.jpg"
width={800}
height={600}
transforms={{
format: "auto",
quality: typeof window !== "undefined" ? (navigator.connection?.saveData ? 60 : 85) : 85,
}}
/>모범 사례#
-
App Router 사용: 더 나은 성능을 위해 React Server Components를 활용하세요.
-
캐싱 활성화: 최적화된 이미지를 위한 적절한 캐시 헤더를 설정하세요.
-
Above-the-fold 최적화: 중요한 이미지에는
priorityprop을 사용하세요. -
반응형 이미지: 반응형 레이아웃에는 항상
sizesprop을 제공하세요. -
자동 포맷: Snapkit이 자동으로 최적의 포맷을 선택하도록 하세요.
문제 해결#
일반적인 문제들#
-
Hydration 불일치: 서버와 클라이언트 간 일관된 렌더링을 확인하세요.
-
CORS 문제:
next.config.js에서 domains을 설정하세요. -
빌드 오류: 모든 정적 import가 유효한지 확인하세요.
-
성능 문제: 캐싱 설정을 확인하세요.
주요 기능 요약#
- 원활한 Next.js Image 컴포넌트 통합
- 자동 이미지 변환
- 동적 DPR 기반 srcset 생성
- 지능적 포맷 선택 (WebP, AVIF)
- 서버 및 클라이언트 컴포넌트 지원
- TypeScript 정의
- 90%+ 테스트 커버리지
