images
Next.js 내장 이미지 최적화 API 대신 클라우드 제공업체를 사용하여 이미지를 최적화하려면 next.config.js
를 다음과 같이 구성할 수 있습니다:
next.config.js
module.exports = {
images: {
loader: "custom",
loaderFile: "./my/image/loader.js",
},
};
이 loaderFile
은 Next.js 애플리케이션의 루트를 기준으로 한 파일을 가리켜야 합니다. 이 파일은 문자열을 반환하는 기본 함수를 내보내야 합니다. 예를 들면:
my/image/loader.js
"use client";
export default function myImageLoader({ src, width, quality }) {
return `https://example.com/${src}?w=${width}&q=${quality || 75}`;
}
또는 loader
prop을 사용하여 각 next/image
인스턴스에 함수를 전달할 수도 있습니다.
알아두면 좋은 점: 함수를 받아들이는 이미지 로더 파일을 사용자 정의하려면 제공된 함수를 직렬화하기 위해 클라이언트 컴포넌트를 사용해야 합니다.
내장 이미지 최적화 API와 Image 컴포넌트의 동작을 구성하는 방법에 대해 자세히 알아보려면 사용 가능한 옵션에 대한 이미지 구성 옵션을 참조하세요.
로더 구성 예시
- Akamai
- AWS CloudFront
- Cloudinary
- Cloudflare
- Contentful
- Fastly
- Gumlet
- ImageEngine
- Imgix
- PixelBin
- Sanity
- Sirv
- Supabase
- Thumbor
Akamai
// 문서: https://techdocs.akamai.com/ivm/reference/test-images-on-demand
export default function akamaiLoader({ src, width, quality }) {
return `https://example.com/${src}?imwidth=${width}`;
}
AWS CloudFront
// 문서: https://aws.amazon.com/developer/application-security-performance/articles/image-optimization
export default function cloudfrontLoader({ src, width, quality }) {
const url = new URL(`https://example.com${src}`);
url.searchParams.set("format", "auto");
url.searchParams.set("width", width.toString());
url.searchParams.set("quality", (quality || 75).toString());
return url.href;
}
Cloudinary
// 데모: https://res.cloudinary.com/demo/image/upload/w_300,c_limit,q_auto/turtles.jpg
export default function cloudinaryLoader({ src, width, quality }) {
const params = ["f_auto", "c_limit", `w_${width}`, `q_${quality || "auto"}`];
return `https://example.com/${params.join(",")}${src}`;
}
Cloudflare
// 문서: https://developers.cloudflare.com/images/transform-images
export default function cloudflareLoader({ src, width, quality }) {
const params = [`width=${width}`, `quality=${quality || 75}`, "format=auto"];
return `https://example.com/cdn-cgi/image/${params.join(",")}/${src}`;
}
Contentful
// 문서: https://www.contentful.com/developers/docs/references/images-api/
export default function contentfulLoader({ src, width, quality }) {
const url = new URL(`https://example.com${src}`);
url.searchParams.set("fm", "webp");
url.searchParams.set("w", width.toString());
url.searchParams.set("q", (quality || 75).toString());
return url.href;
}
Fastly
// 문서: https://developer.fastly.com/reference/io/
export default function fastlyLoader({ src, width, quality }) {
const url = new URL(`https://example.com${src}`);
url.searchParams.set("auto", "webp");
url.searchParams.set("width", width.toString());
url.searchParams.set("quality", (quality || 75).toString());
return url.href;
}
Gumlet
// 문서: https://docs.gumlet.com/reference/image-transform-size
export default function gumletLoader({ src, width, quality }) {
const url = new URL(`https://example.com${src}`);
url.searchParams.set("format", "auto");
url.searchParams.set("w", width.toString());
url.searchParams.set("q", (quality || 75).toString());
return url.href;
}
ImageEngine
// 문서: https://support.imageengine.io/hc/en-us/articles/360058880672-Directives
export default function imageengineLoader({ src, width, quality }) {
const compression = 100 - (quality || 50)
const params = [`w_${width}`, `cmpr_${compression}`)]
return `https://example.com${src}?imgeng=/${params.join('/')`
}
Imgix
// 데모: https://static.imgix.net/daisy.png?format=auto&fit=max&w=300
export default function imgixLoader({ src, width, quality }) {
const url = new URL(`https://example.com${src}`);
const params = url.searchParams;
params.set("auto", params.getAll("auto").join(",") || "format");
params.set("fit", params.get("fit") || "max");
params.set("w", params.get("w") || width.toString());
params.set("q", (quality || 50).toString());
return url.href;
}
PixelBin
// 문서 (리사이즈): https://www.pixelbin.io/docs/transformations/basic/resize/#width-w
// 문서 (최적화): https://www.pixelbin.io/docs/optimizations/quality/#image-quality-when-delivering
// 문서 (자동 포맷 전달): https://www.pixelbin.io/docs/optimizations/format/#automatic-format-selection-with-f_auto-url-parameter
export default function pixelBinLoader({ src, width, quality }) {
const name = "<your-cloud-name>";
const opt = `t.resize(w:${width})~t.compress(q:${quality || 75})`;
return `https://cdn.pixelbin.io/v2/${name}/${opt}/${src}?f_auto=true`;
}
Sanity
// 문서: https://www.sanity.io/docs/image-urls
export default function sanityLoader({ src, width, quality }) {
const prj = "zp7mbokg";
const dataset = "production";
const url = new URL(`https://cdn.sanity.io/images/${prj}/${dataset}${src}`);
url.searchParams.set("auto", "format");
url.searchParams.set("fit", "max");
url.searchParams.set("w", width.toString());
if (quality) {
url.searchParams.set("q", quality.toString());
}
return url.href;
}
Sirv
// 문서: https://sirv.com/help/articles/dynamic-imaging/
export default function sirvLoader({ src, width, quality }) {
const url = new URL(`https://example.com${src}`);
const params = url.searchParams;
params.set("format", params.getAll("format").join(",") || "optimal");
params.set("w", params.get("w") || width.toString());
params.set("q", (quality || 85).toString());
return url.href;
}
Supabase
// 문서: https://supabase.com/docs/guides/storage/image-transformations#nextjs-loader
export default function supabaseLoader({ src, width, quality }) {
const url = new URL(`https://example.com${src}`);
url.searchParams.set("width", width.toString());
url.searchParams.set("quality", (quality || 75).toString());
return url.href;
}
Thumbor
// 문서: https://thumbor.readthedocs.io/en/latest/
export default function thumborLoader({ src, width, quality }) {
const params = [`${width}x0`, `filters:quality(${quality || 75})`];
return `https://example.com${params.join("/")}${src}`;
}