Next.js ์ด๋ฏธ์ง ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ ๋น ๋ฅด๊ณ ๋ฐ์์ฑ์ด ๋ฐ์ด๋ ์น์ฌ์ดํธ๋ฅผ ์ํ ๊ณ ๊ธ ์ต์ ํ ๊ธฐ์ ์ ํ์ํ๊ณ , ์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ์ํ ์ต์ ์ ์ฑ๋ฅ์ ๋ณด์ฅํ์ธ์.
Next.js ์ด๋ฏธ์ง ์ปดํฌ๋ํธ: ๊ธ๋ก๋ฒ ์น์ ์ํ ๊ณ ๊ธ ์ต์ ํ ๊ธฐ๋ฅ
์ค๋๋ ์ ๋์งํธ ํ๊ฒฝ์์ ์ด๋ฏธ์ง๋ ์น์ฌ์ดํธ ์ฝํ
์ธ ์ ์ค์ํ ๋ถ๋ถ์ผ๋ก, ์ฌ์ฉ์ ๊ฒฝํ๊ณผ ์ฐธ์ฌ๋๋ฅผ ํฅ์์ํต๋๋ค. ๊ทธ๋ฌ๋ ์ต์ ํ๋์ง ์์ ์ด๋ฏธ์ง๋ ์น์ฌ์ดํธ ์ฑ๋ฅ์ ์ฌ๊ฐํ ์ํฅ์ ๋ฏธ์ณ ๋ก๋ฉ ์๊ฐ์ ๋ฆ์ถ๊ณ , ํนํ ๋์ญํญ์ด ์ ํ์ ์ด๊ฑฐ๋ ์ง๋ฆฌ์ ์ผ๋ก ๋ฉ๋ฆฌ ๋จ์ด์ง ๊ณณ์์ ์ ์ํ๋ ์ฌ์ฉ์์๊ฒ ์ข์ง ์์ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํ ์ ์์ต๋๋ค. ์ธ๊ธฐ ์๋ React ํ๋ ์์ํฌ์ธ Next.js๋ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ค๊ณ๋ ๊ฐ๋ ฅํ <Image>
์ปดํฌ๋ํธ๋ฅผ ์ ๊ณตํ๋ฉฐ, ๊ณ ๊ธ ์ด๋ฏธ์ง ์ต์ ํ ๊ธฐ๋ฅ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํฉ๋๋ค.
์ด ํฌ๊ด์ ์ธ ๊ฐ์ด๋์์๋ Next.js ์ด๋ฏธ์ง ์ปดํฌ๋ํธ์ ๊ณ ๊ธ ๊ธฐ๋ฅ์ ๋ํด ์์ธํ ์์๋ณด๊ณ , ์ด๋ฅผ ํ์ฉํ์ฌ ์ ์ธ๊ณ ์ฌ์ฉ์์๊ฒ ์ต์ ํ๋ ์ด๋ฏธ์ง๋ฅผ ์ ๊ณตํจ์ผ๋ก์จ ๋ ๋น ๋ฅธ ๋ก๋ฉ ์๊ฐ, ๋์ญํญ ์๋น ๊ฐ์ ๋ฐ ์ ๋ฐ์ ์ธ ์ฌ์ฉ์ ๊ฒฝํ ๊ฐ์ ์ ๋ณด์ฅํ๋ ๋ฐฉ๋ฒ์ ํ๊ตฌํฉ๋๋ค. ๋ฐ์ํ ์ด๋ฏธ์ง ํฌ๊ธฐ ์กฐ์ ๋ฐ ํ์ ์ต์ ํ๋ถํฐ ์ง์ฐ ๋ก๋ฉ ๋ฐ ๊ณ ๊ธ ๊ตฌ์ฑ ์ต์ ์ ์ด๋ฅด๊ธฐ๊น์ง ๋ค์ํ ์ฃผ์ ๋ฅผ ๋ค๋ฃฐ ๊ฒ์ ๋๋ค.
ํต์ฌ ์ด์ ์ดํดํ๊ธฐ
๊ณ ๊ธ ๊ธฐ๋ฅ์ ๋ํด ์์๋ณด๊ธฐ ์ ์ Next.js ์ด๋ฏธ์ง ์ปดํฌ๋ํธ ์ฌ์ฉ์ ํต์ฌ ์ด์ ์ ์์ฝํด ๋ณด๊ฒ ์ต๋๋ค:
- ์๋ ์ด๋ฏธ์ง ์ต์ ํ: ํ์์ ๋ฐ๋ผ ์ด๋ฏธ์ง๋ฅผ ์ต์ ํํ๊ณ , ๋ธ๋ผ์ฐ์ ์ง์์ ๋ฐ๋ผ WebP ๋๋ AVIF์ ๊ฐ์ ์ต์ ํ์์ผ๋ก ํฌ๊ธฐ๋ฅผ ์กฐ์ ํ๊ณ ๋ณํํฉ๋๋ค.
- ๋ฐ์ํ ์ด๋ฏธ์ง: ๋ค์ํ ํ๋ฉด ํฌ๊ธฐ์ ๊ธฐ๊ธฐ ํด์๋์ ๋ง์ถฐ ์ฌ๋ฌ ์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ ์๋์ผ๋ก ์์ฑํ์ฌ ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ์์์ ์ฑ๋ฅ์ ํฅ์์ํค๊ณ ๋์ญํญ ์ฌ์ฉ๋์ ์ค์ ๋๋ค.
- ์ง์ฐ ๋ก๋ฉ(Lazy Loading): ์ด๋ฏธ์ง๊ฐ ๋ทฐํฌํธ์ ๋ค์ด์ฌ ๋๋ง ๋ก๋ํ์ฌ ์ด๊ธฐ ํ์ด์ง ๋ก๋ ์๊ฐ์ ์ค์ด๊ณ ์ฒด๊ฐ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค.
- ๋ด์ฅ๋ ์ฑ๋ฅ: ํ๋ฉด ์๋จ(above-the-fold) ์ด๋ฏธ์ง ์ฌ์ ๋ก๋ฉ ๋ฐ ์๋ ์ด๋ฏธ์ง ํฌ๊ธฐ ์กฐ์ ๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ผ๋ก ์ฑ๋ฅ์ ์ต์ ํ๋์ด ์์ต๋๋ค.
- ๋ ์ด์์ ์ด๋ ๋ฐฉ์ง:
width
์height
๋ฅผ ์ง์ ํ๊ฑฐ๋fill
prop์ ์ฌ์ฉํ์ฌ, Core Web Vitals์ ํต์ฌ ์งํ์ธ ๋์ ๋ ์ด์์ ์ด๋(CLS)์ ๋ฐฉ์งํฉ๋๋ค.
๊ณ ๊ธ ์ต์ ํ ๊ธฐ๋ฒ
1. ์ ์ํ ์ด๋ฏธ์ง๋ฅผ ์ํ `sizes` Prop ๋ง์คํฐํ๊ธฐ
sizes
prop์ ๋ค์ํ ํ๋ฉด ํฌ๊ธฐ์ ๋ทฐํฌํธ ๋๋น์ ์ ์ํ๋ ์ง์ ํ ๋ฐ์ํ ์ด๋ฏธ์ง๋ฅผ ๋ง๋๋ ๊ฐ๋ ฅํ ๋๊ตฌ์
๋๋ค. ๋ฏธ๋์ด ์ฟผ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ค์ํ ์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ ์ ์ํ ์ ์์ด ๋ธ๋ผ์ฐ์ ๊ฐ ์ฌ์ฉ์์ ๊ธฐ๊ธฐ์ ๊ฐ์ฅ ์ ํฉํ ์ด๋ฏธ์ง๋ฅผ ๋ก๋ํ๋๋ก ๋ณด์ฅํฉ๋๋ค.
์์:
์์ ๊ธฐ๊ธฐ์์๋ ํ๋ฉด ์ ์ฒด ๋๋น๋ฅผ, ์ค๊ฐ ํฌ๊ธฐ ๊ธฐ๊ธฐ์์๋ ๋๋น์ ์ ๋ฐ์, ํฐ ๊ธฐ๊ธฐ์์๋ ๋๋น์ 3๋ถ์ 1์ ์ฐจ์งํด์ผ ํ๋ ์ด๋ฏธ์ง๊ฐ ์๋ค๊ณ ์์ํด ๋ณด์ธ์. sizes
prop์ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค:
<Image
src="/my-image.jpg"
alt="My Responsive Image"
width={1200}
height={800}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
์ค๋ช :
(max-width: 768px) 100vw
: ์ต๋ ๋๋น๊ฐ 768px์ธ ํ๋ฉด(์ผ๋ฐ์ ์ผ๋ก ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ)์์๋ ์ด๋ฏธ์ง๊ฐ ๋ทฐํฌํธ ๋๋น์ 100%๋ฅผ ์ฐจ์งํฉ๋๋ค.(max-width: 1200px) 50vw
: ์ต๋ ๋๋น๊ฐ 1200px์ธ ํ๋ฉด(์ค๊ฐ ํฌ๊ธฐ ๊ธฐ๊ธฐ)์์๋ ์ด๋ฏธ์ง๊ฐ ๋ทฐํฌํธ ๋๋น์ 50%๋ฅผ ์ฐจ์งํฉ๋๋ค.33vw
: 1200px๋ณด๋ค ํฐ ํ๋ฉด์์๋ ์ด๋ฏธ์ง๊ฐ ๋ทฐํฌํธ ๋๋น์ 33%๋ฅผ ์ฐจ์งํฉ๋๋ค.
sizes
prop์ width
๋ฐ height
prop๊ณผ ํจ๊ป ์๋ํ์ฌ ๋ธ๋ผ์ฐ์ ๊ฐ ์ฌ๋ฐ๋ฅธ ์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ ๋ก๋ํ๋๋ก ๋ณด์ฅํฉ๋๋ค. ์ ์ ์๋ sizes
prop์ ์ ๊ณตํจ์ผ๋ก์จ ๋ค์ํ ๊ธฐ๊ธฐ์ ํ๋ฉด ํฌ๊ธฐ์ ๋ง๊ฒ ์ด๋ฏธ์ง ์ ๋ฌ์ ์ต์ ํํ์ฌ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ต๋๋ค.
๊ธ๋ก๋ฒ ์ ์ฉ: ์ ๋ฝ๊ณผ ์์์ ์ฌ์ฉ์๋ฅผ ๋ชจ๋ ๋์์ผ๋ก ํ๋ ์ ์์๊ฑฐ๋ ์ฌ์ดํธ๋ฅผ ์๊ฐํด ๋ณด์ธ์. ๊ธฐ๊ธฐ ์ฌ์ฉ ํจํด์ ํฌ๊ฒ ๋ค๋ฅผ ์ ์์ต๋๋ค. ์ ๋ฝ ์ฌ์ฉ์๋ ์ฃผ๋ก ๋ฐ์คํฌํฑ์ ์ฌ์ฉํ๋ ๋ฐ๋ฉด, ์์์ ์ฌ์ฉ์๋ ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ์ ๋ ๋ง์ด ์์กดํ ์ ์์ต๋๋ค. sizes
๋ก ์ต์ ํํ๋ฉด ๊ธฐ๊ธฐ์ ๊ด๊ณ์์ด ๋ชจ๋ ์ฌ์ฉ์์๊ฒ ๋น ๋ฅธ ๋ก๋ฉ ์๊ฐ์ ๋ณด์ฅํ ์ ์์ต๋๋ค.
2. ์ค์๋๊ฐ ๋์ ์๋จ ์ด๋ฏธ์ง์ `priority` ํ์ฉํ๊ธฐ
priority
prop์ ์ด๊ธฐ ํ์ด์ง ๋ก๋์ ์ค์ํ ์ด๋ฏธ์ง, ์ผ๋ฐ์ ์ผ๋ก ์คํฌ๋กค ์์ด ๋ณด์ด๋ ๋ถ๋ถ(above the fold)์ ํ์๋๋ ์ด๋ฏธ์ง์ ๋ก๋ฉ ์ฐ์ ์์๋ฅผ ์ง์ ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ด๋ฌํ ์ด๋ฏธ์ง์ priority={true}
๋ฅผ ์ค์ ํ๋ฉด Next.js์ ํด๋น ์ด๋ฏธ์ง๋ฅผ ๋ฏธ๋ฆฌ ๋ก๋ํ๋๋ก ์ง์ํ์ฌ ๋น ๋ฅด๊ฒ ๋ก๋๋๊ณ ํ์๋๋๋ก ํจ์ผ๋ก์จ ์ฌ์ฉ์์ ์ฒด๊ฐ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค.
์์:
<Image
src="/hero-image.jpg"
alt="Hero Image"
width={1920}
height={1080}
priority={true}
/>
์ฌ์ฉ ์์ :
- ํ์ด๋ก ์ด๋ฏธ์ง: ํ์ด์ง ์๋จ์์ ์ฆ์ ์ฌ์ฉ์์ ์ฃผ์๋ฅผ ๋๋ ๋ฉ์ธ ์ด๋ฏธ์ง.
- ๋ก๊ณ : ์ผ๋ฐ์ ์ผ๋ก ํค๋์ ํ์๋๋ ์น์ฌ์ดํธ์ ๋ก๊ณ .
- ํต์ฌ ์๊ฐ ์์: ์ด๊ธฐ ์ฌ์ฉ์ ๊ฒฝํ์ ํ์์ ์ธ ๊ธฐํ ๋ชจ๋ ์ด๋ฏธ์ง.
์ค์ ๊ณ ๋ ค์ฌํญ:
- ๋๋ฌด ๋ง์ ์ด๋ฏธ์ง๋ฅผ ๋ฏธ๋ฆฌ ๋ก๋ํ๋ฉด ์ ์ฒด ํ์ด์ง ๋ก๋ ์๊ฐ์ ๋ถ์ ์ ์ธ ์ํฅ์ ์ค ์ ์์ผ๋ฏ๋ก
priority
prop์ ์ ์คํ๊ฒ ์ฌ์ฉํด์ผ ํฉ๋๋ค. - ์ฐ์ ์์๋ฅผ ์ง์ ํ๋ ์ด๋ฏธ์ง๊ฐ ํ์ผ ํฌ๊ธฐ๋ฅผ ์ต์ํํ๋๋ก ์ ์ ํ ์ต์ ํ๋์๋์ง ํ์ธํ์ธ์.
๊ธ๋ก๋ฒ ์ ์ฉ: ์ ์ธ๊ณ ๋
์๋ฅผ ๋ณด์ ํ ๋ด์ค ์น์ฌ์ดํธ๋ฅผ ์์ํด ๋ณด์ธ์. ํํ์ด์ง์ ๋ฉ์ธ ๋ด์ค ์ด๋ฏธ์ง๋ priority
๋ฅผ ํตํด ํฐ ์ด์ ์ ์ป์ ์ ์์ผ๋ฉฐ, ํนํ ๊ฐ๋ฐ๋์๊ตญ์ ์ธํฐ๋ท ์ฐ๊ฒฐ์ด ๋๋ฆฐ ๋
์์๊ฒ ๋์ฑ ๊ทธ๋ ์ต๋๋ค. ์ด๋ ์ค์ํ ์๊ฐ์ ์์๊ฐ ๋น ๋ฅด๊ฒ ๋ก๋๋๋๋ก ๋ณด์ฅํ์ฌ ์ฐธ์ฌ๋๋ฅผ ๋์
๋๋ค.
3. ์ปค์คํ ์ด๋ฏธ์ง ๋ก๋ ๊ตฌ์ฑํ๊ธฐ
๊ธฐ๋ณธ์ ์ผ๋ก Next.js ์ด๋ฏธ์ง ์ปดํฌ๋ํธ๋ ๋ด์ฅ๋ ์ด๋ฏธ์ง ์ต์ ํ ์๋น์ค๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ปค์คํ ์ด๋ฏธ์ง ๋ก๋๋ฅผ ์ ๊ณตํ์ฌ ์ด ๋์์ ์ฌ์ฉ์ ์ ์ํ ์ ์์ต๋๋ค. ์ด๋ Cloudinary, Imgix์ ๊ฐ์ ํ์ฌ ์ด๋ฏธ์ง ์ต์ ํ ์๋น์ค๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ์ด๋ฏธ์ง ์ต์ ํ ๊ธฐ๋ฅ์ด ์๋ ์ฝํ ์ธ ์ ์ก ๋คํธ์ํฌ(CDN)๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ํนํ ์ ์ฉํฉ๋๋ค.
์์: Cloudinary ์ฌ์ฉํ๊ธฐ
๋จผ์ Cloudinary SDK๋ฅผ ์ค์นํฉ๋๋ค:
npm install cloudinary-core
๊ทธ๋ฐ ๋ค์ ์ปค์คํ ๋ก๋ ํจ์๋ฅผ ๋ง๋ญ๋๋ค:
// utils/cloudinaryLoader.js
import { Cloudinary } from 'cloudinary-core';
const cloudinary = new Cloudinary({
cloud_name: 'your_cloud_name',
});
export function cloudinaryLoader({ src, width, quality }) {
const params = ['f_auto', 'c_limit', `w_${width}`, 'q_auto'];
if (quality) {
params.push(`q_${quality}`);
}
return cloudinary.url(src, { transformation: params });
}
๋ง์ง๋ง์ผ๋ก, next.config.js
ํ์ผ์์ loader
prop์ ๊ตฌ์ฑํฉ๋๋ค:
// next.config.js
module.exports = {
images: {
loader: 'custom',
loaderFile: './utils/cloudinaryLoader.js',
},
}
๊ทธ๋ฆฌ๊ณ ์ปดํฌ๋ํธ์์ ์ฌ์ฉํฉ๋๋ค:
<Image
src="/my-image.jpg"
alt="My Image"
width={600}
height={400}
loader={cloudinaryLoader}
/>
์ปค์คํ ๋ก๋ ์ฌ์ฉ์ ์ด์ :
- ์ ์ฐ์ฑ: ์ ํธํ๋ ์ด๋ฏธ์ง ์ต์ ํ ์๋น์ค์ ํตํฉํ ์ ์์ต๋๋ค.
- ๊ณ ๊ธ ์ต์ ํ: ํ์ฌ ์๋น์ค์์ ์ ๊ณตํ๋ ๊ณ ๊ธ ์ต์ ํ ๊ธฐ๋ฅ์ ์ ๊ทผํ ์ ์์ต๋๋ค.
- CDN ํตํฉ: ์ ํํ ์๋น์ค์ ๊ธ๋ก๋ฒ CDN ์ธํ๋ผ๋ฅผ ํ์ฉํ ์ ์์ต๋๋ค.
๊ธ๋ก๋ฒ ์ ์ฉ: ๊ธ๋ก๋ฒ ์ฌํ ์์ฝ ํ๋ซํผ์ Akamai๋ Cloudflare์ ๊ฐ์ CDN๊ณผ ํจ๊ป ์ปค์คํ ๋ก๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ์ฌ์ฉ์๊ฐ ๋์ฟ, ๋ฐ๋, ๋ด์ ์ด๋์ ์๋ ๊ฐ์ฅ ๊ฐ๊น์ด ์๋ฒ์์ ์ด๋ฏธ์ง๊ฐ ์ ๊ณต๋๋ฏ๋ก ์ง์ฐ ์๊ฐ์ ๋ํญ ์ค์ด๊ณ ๋ก๋ฉ ์๊ฐ์ ๊ฐ์ ํ ์ ์์ต๋๋ค.
4. ์ด๋ฏธ์ง ํฌ๋งท ์ต์ ํ: WebP์ AVIF
WebP ๋ฐ AVIF์ ๊ฐ์ ์ต์ ์ด๋ฏธ์ง ํฌ๋งท์ JPEG ๋ฐ PNG์ ๊ฐ์ ๊ธฐ์กด ํฌ๋งท์ ๋นํด ์ฐ์ํ ์์ถ๋ฅ ๊ณผ ํ์ง์ ์ ๊ณตํฉ๋๋ค. Next.js ์ด๋ฏธ์ง ์ปดํฌ๋ํธ๋ ๋ธ๋ผ์ฐ์ ์ง์์ ๋ฐ๋ผ ์ด๋ฏธ์ง๋ฅผ ์ด๋ฌํ ํฌ๋งท์ผ๋ก ์๋ ๋ณํํ์ฌ ํ์ผ ํฌ๊ธฐ๋ฅผ ๋์ฑ ์ค์ด๊ณ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
WebP: ๊ตฌ๊ธ์ด ๊ฐ๋ฐํ ์ต์ ์ด๋ฏธ์ง ํฌ๋งท์ผ๋ก, ์ฐ์ํ ๋ฌด์์ค ๋ฐ ์์ค ์์ถ์ ์ ๊ณตํฉ๋๋ค. ์ต์ ๋ธ๋ผ์ฐ์ ์์ ๋๋ฆฌ ์ง์๋ฉ๋๋ค.
AVIF: AV1 ๋น๋์ค ์ฝ๋ฑ์ ๊ธฐ๋ฐ์ผ๋ก ํ ์ต์ ์ด๋ฏธ์ง ํฌ๋งท์ ๋๋ค. WebP๋ณด๋ค ๋ ๋์ ์์ถ๋ฅ ์ ์ ๊ณตํ์ง๋ง ๋ธ๋ผ์ฐ์ ์ง์ ๋ฒ์๋ ๋ ์ข์ต๋๋ค.
์๋ ํฌ๋งท ๋ณํ: Next.js ์ด๋ฏธ์ง ์ปดํฌ๋ํธ๋ ๋ธ๋ผ์ฐ์ ๊ฐ ์ง์ํ๋ ๊ฒฝ์ฐ ์ด๋ฏธ์ง๋ฅผ WebP ๋๋ AVIF๋ก ์๋ ๋ณํํฉ๋๋ค. ํฌ๋งท์ ๋ช ์์ ์ผ๋ก ์ง์ ํ ํ์ ์์ด ์ปดํฌ๋ํธ๊ฐ ์๋์ผ๋ก ์ฒ๋ฆฌํฉ๋๋ค.
๋ธ๋ผ์ฐ์ ์ง์: WebP ๋ฐ AVIF์ ๋ํ ํ์ฌ ์ง์ ์ํฉ์ ์ดํดํ๋ ค๋ฉด ๋ธ๋ผ์ฐ์ ํธํ์ฑ ํ(์: caniuse.com)๋ฅผ ํ์ธํ์ธ์.
๊ณ ๋ ค์ฌํญ:
- ์ด๋ฏธ์ง ์ต์ ํ ์๋น์ค๋ CDN์ด WebP ๋ฐ AVIF๋ฅผ ์ง์ํ๋์ง ํ์ธํ์ธ์.
- ์ด๋ฌํ ํฌ๋งท์ ์ง์ํ์ง ์๋ ๊ตฌํ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ํ ๋์ฒด ๋ฐฉ์์ ๊ณ ๋ คํ์ธ์ (Next.js ์ด๋ฏธ์ง ์ปดํฌ๋ํธ๋ ์ผ๋ฐ์ ์ผ๋ก ์ด๋ฅผ ์ํํ๊ฒ ์ฒ๋ฆฌํฉ๋๋ค).
๊ธ๋ก๋ฒ ์ ์ฉ: ๊ตญ์ ๋ด์ค ์์ง ์ฌ์ดํธ๋ WebP์ AVIF๋ก๋ถํฐ ํฐ ์ด์ ์ ์ป์ ์ ์์ต๋๋ค. ์ง์ญ๋ณ ์ธํฐ๋ท ์๋๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์, ๋ ์์ ์ด๋ฏธ์ง ํ์ผ ํฌ๊ธฐ๋ ๋์ญํญ์ด ์ ํ๋ ์ง์ญ์ ์ฌ์ฉ์์๊ฒ ๋ ๋น ๋ฅธ ๋ก๋ฉ ์๊ฐ๊ณผ ๋ฐ์ดํฐ ์๋น ๊ฐ์๋ก ์ด์ด์ง๋๋ค.
5. ๋์ ๋ ์ด์์์ ์ํ `fill`๊ณผ `objectFit` ํ์ฉํ๊ธฐ
fill
prop์ ์ด๋ฏธ์ง๊ฐ ๋ถ๋ชจ ์ปจํ
์ด๋์ ํฌ๊ธฐ๋ฅผ ์ฐจ์งํ๋๋ก ํฉ๋๋ค. ์ด๋ ์ด๋ฏธ์ง ํฌ๊ธฐ๊ฐ ์ฌ์ฉ ๊ฐ๋ฅํ ๊ณต๊ฐ์ ๋์ ์ผ๋ก ์ ์ํด์ผ ํ๋ ๋ฐ์ํ ๋ ์ด์์์ ๋ง๋ค ๋ ํนํ ์ ์ฉํฉ๋๋ค. objectFit
CSS ์์ฑ๊ณผ ๊ฒฐํฉํ์ฌ ์ด๋ฏธ์ง๊ฐ ์ปจํ
์ด๋๋ฅผ ์ฑ์ฐ๋ ๋ฐฉ์(์: cover
, contain
, fill
, none
, scale-down
)์ ์ ์ดํ ์ ์์ต๋๋ค.
์์:
<div style={{ position: 'relative', width: '100%', height: '300px' }}>
<Image
src="/my-image.jpg"
alt="My Image"
fill
style={{ objectFit: 'cover' }}
/>
</div>
์ค๋ช :
div
์์๋ ์ด๋ฏธ์ง์ ์ปจํ ์ด๋ ์ญํ ์ ํ๋ฉฐ ์๋ ์์น(relative position)๋ฅผ ๊ฐ์ง๋๋ค.<Image>
์ปดํฌ๋ํธ์๋fill
prop์ด ์ค์ ๋์ด ์์ด ๋ถ๋ชจ ์ปจํ ์ด๋์ ํฌ๊ธฐ๋ฅผ ์ฐจ์งํ๊ฒ ๋ฉ๋๋ค.objectFit: 'cover'
์คํ์ผ์ ์ด๋ฏธ์ง๊ฐ ์ ์ฒด ์ปจํ ์ด๋๋ฅผ ๋ฎ๋๋ก ๋ณด์ฅํ๋ฉฐ, ๊ฐ๋ก์ธ๋ก ๋น์จ์ ์ ์งํ๊ธฐ ์ํด ์ด๋ฏธ์ง์ ์ผ๋ถ๊ฐ ์๋ฆด ์ ์์ต๋๋ค.
์ฌ์ฉ ์ฌ๋ก:
- ์ ์ฒด ๋๋น ๋ฐฐ๋: ํ๋ฉด ์ ์ฒด ๋๋น์ ๊ฑธ์ณ ์๋ ๋ฐ์ํ ๋ฐฐ๋ ๋ง๋ค๊ธฐ.
- ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง: ์น์ ์ด๋ ์ปดํฌ๋ํธ์ ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง ์ค์ ํ๊ธฐ.
- ์ด๋ฏธ์ง ๊ฐค๋ฌ๋ฆฌ: ์ด๋ฏธ์ง ํฌ๊ธฐ๊ฐ ์ฌ์ฉ ๊ฐ๋ฅํ ๊ณต๊ฐ์ ๋ง์ถฐ ์กฐ์ ๋๋ ๊ทธ๋ฆฌ๋ ๋ ์ด์์์ ์ด๋ฏธ์ง ํ์ํ๊ธฐ.
๊ธ๋ก๋ฒ ์ ์ฉ: ์ ํ์ ์ ๋ณด์ด๋ ๋ค๊ตญ์ด ์น์ฌ์ดํธ๋ ๋ค์ํ ํ
์คํธ ๊ธธ์ด์ ํ๋ฉด ํฌ๊ธฐ์ ์ ์ํ๋ ์ ์ฐํ ๋ ์ด์์์ด ํ์ํฉ๋๋ค. fill
๊ณผ objectFit
์ ์ฌ์ฉํ๋ฉด ์ธ์ด๋ ๊ธฐ๊ธฐ์ ๊ด๊ณ์์ด ์ด๋ฏธ์ง๊ฐ ์๊ฐ์ ๋งค๋ ฅ์ ์ ์งํ๊ณ ๋ ์ด์์์ ์๋ฒฝํ๊ฒ ๋ค์ด๋ง๋๋ก ํ ์ ์์ต๋๋ค.
6. ํน์ ์๋๋ฆฌ์ค๋ฅผ ์ํ `unoptimized` Prop ๊ตฌ์ฑํ๊ธฐ
๋๋ฌธ ๊ฒฝ์ฐ์ง๋ง ํน์ ์ด๋ฏธ์ง์ ๋ํด ์๋ ์ด๋ฏธ์ง ์ต์ ํ๋ฅผ ๋นํ์ฑํํ๊ณ ์ถ์ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ด๋ฏธ ๊ณ ๋๋ก ์ต์ ํ๋ ์ด๋ฏธ์ง๊ฐ ์๊ฑฐ๋ ์ถ๊ฐ ์ฒ๋ฆฌ ์์ด CDN์์ ์ง์ ์ ๊ณตํ๊ณ ์ถ์ ์ด๋ฏธ์ง๊ฐ ์์ ์ ์์ต๋๋ค. unoptimized
prop์ true
๋ก ์ค์ ํ์ฌ ์ด๋ฅผ ๋ฌ์ฑํ ์ ์์ต๋๋ค.
์์:
<Image
src="/already-optimized.png"
alt="Already Optimized Image"
width={800}
height={600}
unoptimized={true}
/>
์ฌ์ฉ ์์ :
- ์ด๋ฏธ ์ต์ ํ๋ ์ด๋ฏธ์ง: ํ์ฌ ๋๊ตฌ๋ ์๋น์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ ์ต์ ํ๋ ์ด๋ฏธ์ง.
- CDN์์ ์ง์ ์ ๊ณต๋๋ ์ด๋ฏธ์ง: ์ถ๊ฐ ์ฒ๋ฆฌ ์์ด CDN์์ ์ง์ ์ ๊ณต๋๋ ์ด๋ฏธ์ง.
- ํน์ ์ด๋ฏธ์ง ํฌ๋งท: Next.js ์ด๋ฏธ์ง ์ปดํฌ๋ํธ์์ ์ง์ํ์ง ์๋ ํน์ ํฌ๋งท์ ์ฌ์ฉํ๋ ์ด๋ฏธ์ง.
์ฃผ์:
- ๋ชจ๋ ์๋ ์ด๋ฏธ์ง ์ต์ ํ ๊ธฐ๋ฅ์ ๋นํ์ฑํํ๋ฏ๋ก
unoptimized
prop์ ์ ์คํ๊ฒ ์ฌ์ฉํด์ผ ํฉ๋๋ค. unoptimized
๋ก ํ์ํ ์ด๋ฏธ์ง๊ฐ ํ์ผ ํฌ๊ธฐ๋ฅผ ์ต์ํํ๋๋ก ์ด๋ฏธ ์ ์ ํ ์ต์ ํ๋์๋์ง ํ์ธํ์ธ์.
๊ธ๋ก๋ฒ ์ ์ฉ: ์์ ์ ์ํ์ ์ ์ํ๋ ์ฌ์ง์๊ฐ๋ฅผ ์ํ ์น์ฌ์ดํธ๋ฅผ ์๊ฐํด ๋ณด์ธ์. ๊ทธ๋ค์ Next.js ์ตํฐ๋ง์ด์ ๊ฐ ๋ณ๊ฒฝํ ์ ์๋ ํน์ ์์ ํ๋กํ์ด๋ ์ ๋ฐํ ์ค์ ์ผ๋ก ์ด๋ฏธ์ง๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ ์ ํธํ ์ ์์ต๋๋ค. unoptimized
๋ฅผ ์ฌ์ฉํ๋ฉด ์๋ํ ๋๋ก ์ด๋ฏธ์ง๋ฅผ ์ ๊ณตํ ์ ์๋ ์ ์ด๊ถ์ ๊ฐ์ง ์ ์์ต๋๋ค.
7. ์ฒด๊ฐ ์ฑ๋ฅ ํฅ์์ ์ํ `blurDataURL` ํ์ฉํ๊ธฐ
blurDataURL
prop์ ์ฌ์ฉํ๋ฉด ์ค์ ์ด๋ฏธ์ง๊ฐ ๋ก๋๋๋ ๋์ ์ ํด์๋ ํ๋ ์ด์คํ๋ ์ด๋ฏธ์ง๋ฅผ ํ์ํ ์ ์์ต๋๋ค. ์ด๋ ๋ฌด์ธ๊ฐ ๋ก๋๋๊ณ ์๋ค๋ ์๊ฐ์ ์ ํธ๋ฅผ ์ ๊ณตํ์ฌ ํ์ด์ง๊ฐ ๋น์ด ์๊ฑฐ๋ ๋ฐ์์ด ์๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๋ ๊ฒ์ ๋ฐฉ์งํจ์ผ๋ก์จ ์ฌ์ฉ์์ ์ฒด๊ฐ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ต๋๋ค. Next.js 13 ์ด์ ๋ฒ์ ์์๋ ์ข
์ข
์ด๋ฅผ ์๋์ผ๋ก ์ฒ๋ฆฌํฉ๋๋ค.
์์:
๋จผ์ , BlurHash์ ๊ฐ์ ๋๊ตฌ๋ ์ ์ฌํ ์๋น์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง์์ ๋ธ๋ฌ ๋ฐ์ดํฐ URL์ ์์ฑํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ด๋ฏธ์ง์ ํ๋ฆฟํ ๋ฒ์ ์ ๋ํ๋ด๋ ์์ base64 ์ธ์ฝ๋ฉ ๋ฌธ์์ด์ ์ป์ ์ ์์ต๋๋ค.
<Image
src="/my-image.jpg"
alt="My Image"
width={600}
height={400}
placeholder="blur"
blurDataURL="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkqAcAAIUAgUW0RjgAAAAASUVORK5CYII="
/>
์ด์ :
- ์ฒด๊ฐ ์ฑ๋ฅ ํฅ์: ๋ฌด์ธ๊ฐ ๋ก๋๋๊ณ ์๋ค๋ ์๊ฐ์ ์ ํธ๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ์ฌ์ฉ์ ๊ฒฝํ ํฅ์: ํ์ด์ง๊ฐ ๋น์ด ์๊ฑฐ๋ ๋ฐ์์ด ์๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค.
- ๋ ์ด์์ ์ด๋ ๊ฐ์: ์ด๋ฏธ์ง ๊ณต๊ฐ์ ๋ฏธ๋ฆฌ ํ๋ณดํ์ฌ ๋ ์ด์์ ์ด๋์ ๋ฐฉ์งํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
๊ธ๋ก๋ฒ ์ ์ฉ: ๋ฉ์ง ์ฌ์ง์ผ๋ก ์ฌํ์ง๋ฅผ ์๊ฐํ๋ ๊ตญ์ ์ฌํ ๋ธ๋ก๊ทธ. blurDataURL
์ ์ฌ์ฉํ๋ฉด ๋๋ฆฐ ๋คํธ์ํฌ๋ฅผ ์ฌ์ฉํ๋ ์ฌ์ฉ์์๊ฒ๋ ๋ถ๋๋ฌ์ด ๋ก๋ฉ ๊ฒฝํ์ ์ ๊ณตํ์ฌ ๊ธ์ ์ ์ธ ์ฒซ์ธ์์ ๋ง๋ค๊ณ ์ฝํ
์ธ ๋ฅผ ํ์ํ๋๋ก ์ ๋ํฉ๋๋ค.
๊ธ๋ก๋ฒ ์ด๋ฏธ์ง ์ต์ ํ๋ฅผ ์ํ ๋ชจ๋ฒ ์ฌ๋ก
์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ์ํ ์ต์ ์ ์ด๋ฏธ์ง ์ฑ๋ฅ์ ๋ณด์ฅํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๊ณ ๋ คํ์ธ์:
- ์ฌ๋ฐ๋ฅธ ์ด๋ฏธ์ง ํฌ๋งท ์ ํ: ์ต์ ๋ธ๋ผ์ฐ์ ์๋ WebP ๋๋ AVIF๋ฅผ ์ฌ์ฉํ๊ณ ๊ตฌํ ๋ธ๋ผ์ฐ์ ์๋ ๋์ฒด ํฌ๋งท์ ์ ๊ณตํ์ธ์.
- ์ด๋ฏธ์ง ํฌ๊ธฐ ์ต์ ํ: ๋์ ๋์คํ๋ ์ด ํฌ๊ธฐ์ ๋ง๋ ์ ์ ํ ์น์๋ก ์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ ์กฐ์ ํ์ธ์.
- ์ด๋ฏธ์ง ์์ถ: ๋ฌด์์ค ๋๋ ์์ค ์์ถ์ ์ฌ์ฉํ์ฌ ํ์ผ ํฌ๊ธฐ๋ฅผ ์ค์ด์ธ์.
- ์ง์ฐ ๋ก๋ฉ ์ฌ์ฉ: ์ด๋ฏธ์ง๊ฐ ๋ทฐํฌํธ์ ๋ค์ด์ฌ ๋๋ง ๋ก๋ํ์ธ์.
- ์ค์ ์ด๋ฏธ์ง ์ฐ์ ์์ ์ง์ : ์ด๊ธฐ ํ์ด์ง ๋ก๋์ ์ค์ํ ์ด๋ฏธ์ง๋ฅผ ๋ฏธ๋ฆฌ ๋ก๋ํ์ธ์.
- CDN ํ์ฉ: CDN์ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์์๊ฒ ๊ฐ์ฅ ๊ฐ๊น์ด ์๋ฒ์์ ์ด๋ฏธ์ง๋ฅผ ์ ๊ณตํ์ธ์.
- ์ฑ๋ฅ ๋ชจ๋ํฐ๋ง: Google PageSpeed Insights ๋ฐ WebPageTest์ ๊ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ์น์ฌ์ดํธ ์ฑ๋ฅ์ ์ ๊ธฐ์ ์ผ๋ก ๋ชจ๋ํฐ๋งํ์ธ์.
๊ฒฐ๋ก
Next.js ์ด๋ฏธ์ง ์ปดํฌ๋ํธ๋ ์น์ฉ ์ด๋ฏธ์ง๋ฅผ ์ต์ ํํ๊ธฐ ์ํ ๊ฐ๋ ฅํ๊ณ ์ ์ฐํ ์๋ฃจ์
์ ์ ๊ณตํฉ๋๋ค. ๊ณ ๊ธ ๊ธฐ๋ฅ์ ํ์ฉํจ์ผ๋ก์จ ์ ์ธ๊ณ ์ฌ์ฉ์์๊ฒ ๋ ๋น ๋ฅธ ๋ก๋ฉ ์๊ฐ, ๋์ญํญ ์๋น ๊ฐ์ ๋ฐ ์ ๋ฐ์ ์ผ๋ก ํฅ์๋ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํ ์ ์์ต๋๋ค. sizes
prop ๋ง์คํฐํ๊ธฐ, priority
ํ์ฉํ๊ธฐ, ์ปค์คํ
๋ก๋ ๊ตฌ์ฑํ๊ธฐ, ์ด๋ฏธ์ง ํฌ๋งท ์ต์ ํํ๊ธฐ์ ์ด๋ฅด๊ธฐ๊น์ง, ์ด ๊ฐ์ด๋๋ ๋ชจ๋ ๊ธฐ๊ธฐ์ ๋ชจ๋ ์์น์์ ์ ์๋ํ๋ ์ง์ ์ผ๋ก ์ต์ ํ๋ ์ด๋ฏธ์ง๋ฅผ ๋ง๋๋ ๋ฐ ํ์ํ ์ง์๊ณผ ๋๊ตฌ๋ฅผ ์ ๊ณตํ์ต๋๋ค.
์น์ฌ์ดํธ ์ฑ๋ฅ์ ์ง์์ ์ผ๋ก ๋ชจ๋ํฐ๋งํ๊ณ ํ์์ ๋ฐ๋ผ ์ด๋ฏธ์ง ์ต์ ํ ์ ๋ต์ ์กฐ์ ํ์ฌ ์ฌ์ฉ์์๊ฒ ์ต์์ ๊ฒฝํ์ ์ ๊ณตํ๊ณ ์๋์ง ํ์ธํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.