Next.js μμ² μν°ν΄μ μ΄ν΄νκ³ μμ°¨μ λ°μ΄ν° νμΉμ΄ μ±λ₯μ λ―ΈμΉλ μν₯μ μμ보μΈμ. λ λΉ λ₯Έ μ¬μ©μ κ²½νμ μν λ°μ΄ν° λ‘λ© μ΅μ ν μ λ΅μ λ°κ²¬νμΈμ.
Next.js μμ² μν°ν΄: μμ°¨μ λ°μ΄ν° λ‘λ©μ μ΄ν΄μ μ΅μ ν
μΉ κ°λ°μ μΈκ³μμ μ±λ₯μ κ°μ₯ μ€μν©λλ€. λ‘λ©μ΄ λλ¦° μΉμ¬μ΄νΈλ μ¬μ©μλ₯Ό μ’μ μν€κ³ κ²μ μμ§ μμμ λΆμ μ μΈ μν₯μ λ―ΈμΉ μ μμ΅λλ€. μΈκΈ° μλ React νλ μμν¬μΈ Next.jsλ μ±λ₯μ΄ λ°μ΄λ μΉ μ ν리μΌμ΄μ μ ꡬμΆνκΈ° μν κ°λ ₯ν κΈ°λ₯μ μ 곡ν©λλ€. νμ§λ§ κ°λ°μλ μμ°¨μ λ°μ΄ν° λ‘λ© μ€μ λ°μν μ μλ "μμ² μν°ν΄"κ³Ό κ°μ μ μ¬μ μΈ μ±λ₯ λ³λͺ© νμμ μΈμ§ν΄μΌ ν©λλ€.
Next.js μμ² μν°ν΄μ΄λ 무μμΈκ°?
μμ‘΄μ± μ²΄μΈμ΄λΌκ³ λ μλ €μ§ μμ² μν°ν΄μ Next.js μ ν리μΌμ΄μ μμ λ°μ΄ν° νμΉ(data fetching) μμ μ΄ μμ°¨μ μΌλ‘, μ¦ νλκ° λλ νμ λ€λ₯Έ νλκ° μ€νλ λ λ°μν©λλ€. μ΄λ μ»΄ν¬λνΈκ° ν API μλν¬μΈνΈμμ λ°μ΄ν°λ₯Ό κ°μ Έμ¨ νμμΌ λ€λ₯Έ μλν¬μΈνΈμμ λ°μ΄ν°λ₯Ό κ°μ Έμ¬ μ μμ λ λ°μν©λλ€. μλ₯Ό λ€μ΄, ν νμ΄μ§μμ μ¬μ©μ νλ‘ν μ 보μ μ΅κ·Ό λΈλ‘κ·Έ κ²μλ¬Όμ νμν΄μΌ νλ μλ리μ€λ₯Ό μμν΄ λ³΄μΈμ. λ¨Όμ νλ‘ν μ 보λ₯Ό κ°μ Έμ¨ ν, ν΄λΉ λ°μ΄ν°κ° μ¬μ© κ°λ₯ν΄μ ΈμΌλ§ μ ν리μΌμ΄μ μ΄ μ¬μ©μμ λΈλ‘κ·Έ κ²μλ¬Όμ κ°μ Έμ€λ μμ μ μ§νν μ μμ΅λλ€.
μ΄λ¬ν μμ°¨μ μμ‘΄μ±μ "μν°ν΄" ν¨κ³Όλ₯Ό λ§λ€μ΄λ λλ€. λΈλΌμ°μ λ κ° μμ²μ΄ μλ£λ λκΉμ§ κΈ°λ€λ Έλ€κ° λ€μ μμ²μ μμν΄μΌ νλ―λ‘ λ‘λ μκ°μ΄ κΈΈμ΄μ§κ³ μ¬μ©μ κ²½νμ΄ μ νλ©λλ€.
μμ μλ리μ€: μ μμκ±°λ μν νμ΄μ§
μ μμκ±°λ μν νμ΄μ§λ₯Ό μκ°ν΄ λ΄ μλ€. μ΄ νμ΄μ§λ λ¨Όμ κΈ°λ³Έμ μΈ μν μ 보(μ΄λ¦, μ€λͺ , κ°κ²©)λ₯Ό κ°μ ΈμμΌ ν μ μμ΅λλ€. μ΄ μ λ³΄κ° ν보λλ©΄ κ΄λ ¨ μν, κ³ κ° λ¦¬λ·°, μ¬κ³ μ 보λ₯Ό κ°μ Έμ¬ μ μμ΅λλ€. λ§μ½ μ΄λ¬ν κ° λ°μ΄ν° νμΉκ° μ΄μ λ°μ΄ν° νμΉμ μμ‘΄νλ€λ©΄, μλΉν μμ² μν°ν΄μ΄ λ°μνμ¬ μ΄κΈ° νμ΄μ§ λ‘λ μκ°μ ν¬κ² μ¦κ°μν¬ μ μμ΅λλ€.
μμ² μν°ν΄μ΄ μ μ€μνκ°?
μμ² μν°ν΄μ μν₯μ μλΉν©λλ€:
- λ‘λ μκ° μ¦κ°: κ°μ₯ λͺ λ°±ν κ²°κ³Όλ νμ΄μ§ λ‘λ μκ°μ΄ λλ €μ§λ κ²μ λλ€. μ¬μ©μλ νμ΄μ§κ° μμ ν λ λλ§λ λκΉμ§ λ μ€λ κΈ°λ€λ €μΌ ν©λλ€.
- μ νλ μ¬μ©μ κ²½ν: κΈ΄ λ‘λ μκ°μ μ¬μ©μμκ² λΆλ§μ μκ²¨μ£Όκ³ μΉμ¬μ΄νΈλ₯Ό μ΄ννκ² λ§λ€ μ μμ΅λλ€.
- κ²μ μμ§ μμ νλ½: ꡬκΈκ³Ό κ°μ κ²μ μμ§μ νμ΄μ§ λ‘λ μλλ₯Ό μμ κ²°μ μμΈμΌλ‘ κ³ λ €ν©λλ€. λλ¦° μΉμ¬μ΄νΈλ SEOμ λΆμ μ μΈ μν₯μ λ―ΈμΉ μ μμ΅λλ€.
- μλ² λΆν μ¦κ°: μ¬μ©μκ° κΈ°λ€λ¦¬λ λμμλ μλ²λ κ³μν΄μ μμ²μ μ²λ¦¬νκ³ μμΌλ©°, μ΄λ μλ² λΆνμ λΉμ©μ μ¦κ°μν¬ μ μμ΅λλ€.
Next.js μ ν리μΌμ΄μ μμ μμ² μν°ν΄ μλ³νκΈ°
Next.js μ ν리μΌμ΄μ μ μμ² μν°ν΄μ μλ³νκ³ λΆμνλ λ° λμμ΄ λλ λͺ κ°μ§ λꡬμ κΈ°μ μ΄ μμ΅λλ€:
- λΈλΌμ°μ κ°λ°μ λꡬ: λΈλΌμ°μ κ°λ°μ λꡬμ λ€νΈμν¬ νμ μ ν리μΌμ΄μ μ΄ μμ±νλ λͺ¨λ λ€νΈμν¬ μμ²μ μκ°μ μΌλ‘ 보μ¬μ€λλ€. μμ²μ΄ μ΄λ£¨μ΄μ§λ μμ, μλ£μ 걸리λ μκ°, μμ² κ°μ μμ‘΄μ±μ νμΈν μ μμ΅λλ€. μ΄μ μμ²μ΄ μλ£λ νμμΌ λ€μ μμ²μ΄ μμλλ κΈ΄ μμ² μ²΄μΈμ μ°Ύμ보μΈμ.
- Webpage Test (WebPageTest.org): WebPageTestλ μμ² μμμ μκ°μ μκ°μ μΌλ‘ λνλ΄λ μν°ν΄ μ°¨νΈλ₯Ό ν¬ν¨νμ¬ μΉμ¬μ΄νΈμ λν μμΈν μ±λ₯ λΆμμ μ 곡νλ κ°λ ₯ν μ¨λΌμΈ λꡬμ λλ€.
- Next.js κ°λ°μ λꡬ: Next.js κ°λ°μ λꡬ νμ₯ νλ‘κ·Έλ¨(Chrome λ° Firefoxμμ μ¬μ© κ°λ₯)μ μ»΄ν¬λνΈμ λ λλ§ μ±λ₯μ λν ν΅μ°°λ ₯μ μ 곡νλ©° λλ¦° λ°μ΄ν° νμΉ μμ μ μλ³νλ λ° λμμ΄ λ μ μμ΅λλ€.
- νλ‘νμΌλ§ λꡬ: Chrome νλ‘νμΌλ¬μ κ°μ λꡬλ JavaScript μ½λμ μ±λ₯μ λν μμΈν ν΅μ°°λ ₯μ μ 곡νμ¬ λ°μ΄ν° νμΉ λ‘μ§μ λ³λͺ© νμμ μλ³νλ λ° λμμ μ€λλ€.
λ°μ΄ν° λ‘λ© μ΅μ ν λ° μμ² μν°ν΄ κ°μ μ λ΅
λ€ννλ, Next.js μ ν리μΌμ΄μ μμ λ°μ΄ν° λ‘λ©μ μ΅μ ννκ³ μμ² μν°ν΄μ μν₯μ μ΅μννκΈ° μν΄ μ¬μ©ν μ μλ λͺ κ°μ§ μ λ΅μ΄ μμ΅λλ€:
1. λ³λ ¬ λ°μ΄ν° νμΉ
μμ² μν°ν΄μ λμ²νλ κ°μ₯ ν¨κ³Όμ μΈ λ°©λ²μ κ°λ₯ν λλ§λ€ λ°μ΄ν°λ₯Ό λ³λ ¬λ‘ κ°μ Έμ€λ κ²μ λλ€. νλμ λ°μ΄ν° νμΉκ° μλ£λκΈ°λ₯Ό κΈ°λ€λ¦¬μ§ μκ³ λ€μ νμΉλ₯Ό μμνλ λμ , μ¬λ¬ λ°μ΄ν° νμΉλ₯Ό λμμ μμνμΈμ. μ΄λ μ 체 λ‘λ μκ°μ ν¬κ² μ€μΌ μ μμ΅λλ€.
`Promise.all()` μ¬μ© μμ:
async function ProductPage() {
const [product, relatedProducts] = await Promise.all([
fetch('/api/product/123').then(res => res.json()),
fetch('/api/related-products/123').then(res => res.json()),
]);
return (
<div>
<h1>{product.name}</h1>
<p>{product.description}</p>
<h2>Related Products</h2>
<ul>
{relatedProducts.map(relatedProduct => (
<li key={relatedProduct.id}>{relatedProduct.name}</li>
))}
</ul>
</div>
);
}
μ΄ μμ μμ `Promise.all()`μ μ ν μμΈ μ 보μ κ΄λ ¨ μνμ λμμ κ°μ Έμ¬ μ μκ² ν΄μ€λλ€. μ»΄ν¬λνΈλ λ μμ²μ΄ λͺ¨λ μλ£λ νμλ§ λ λλ§λ©λλ€.
μ₯μ :
- λ‘λ μκ° κ°μ: λ³λ ¬ λ°μ΄ν° νμΉμ νμ΄μ§λ₯Ό λ‘λνλ λ° κ±Έλ¦¬λ μ 체 μκ°μ κ·Ήμ μΌλ‘ μ€μ¬μ€λλ€.
- μ¬μ©μ κ²½ν κ°μ : μ¬μ©μκ° μ½ν μΈ λ₯Ό λ 빨리 λ³΄κ² λμ΄ λ λ§€λ ₯μ μΈ κ²½νμ μ 곡ν©λλ€.
κ³ λ €μ¬ν:
- μλ¬ μ²λ¦¬: λ³λ ¬ μμ² μ€ λ°μν μ μλ μ μ¬μ μ€ν¨λ₯Ό κ΄λ¦¬νκΈ° μν΄ `try...catch` λΈλ‘κ³Ό μ μ ν μλ¬ μ²λ¦¬λ₯Ό μ¬μ©νμΈμ. κ°λ³ μ±κ³΅ μ¬λΆμ κ΄κ³μμ΄ λͺ¨λ νλΌλ―Έμ€κ° μ΄νλκ±°λ κ±°λΆλλλ‘ νλ €λ©΄ `Promise.allSettled`λ₯Ό κ³ λ €νμΈμ.
- API νΈμΆ μ ν(Rate Limiting): API νΈμΆ μ νμ μ μνμΈμ. λ무 λ§μ μμ²μ λμμ 보λ΄λ©΄ μ ν리μΌμ΄μ μ΄ μ€λ‘νλ§λκ±°λ μ°¨λ¨λ μ μμ΅λλ€. μμ² νμμ΄λ μ§μ λ°±μ€νμ κ°μ μ λ΅μ ꡬννμ¬ νΈμΆ μ νμ μννκ² μ²λ¦¬νμΈμ.
- μ€λ²-νμΉ(Over-Fetching): μ€μ λ‘ νμν κ²λ³΄λ€ λ λ§μ λ°μ΄ν°λ₯Ό κ°μ Έμ€μ§ μλλ‘ νμΈμ. λΆνμν λ°μ΄ν°λ₯Ό κ°μ Έμ€λ κ²μ λ³λ ¬λ‘ μνλλλΌλ μ±λ₯μ μν₯μ λ―ΈμΉ μ μμ΅λλ€.
2. λ°μ΄ν° μμ‘΄μ± λ° μ‘°κ±΄λΆ νμΉ
λλ‘λ λ°μ΄ν° μμ‘΄μ±μ νΌν μ μμ΅λλ€. λ€λ₯Έ λ°μ΄ν°λ₯Ό κ°μ Έμ€κΈ° μ μ λ¨Όμ μ΄κΈ° λ°μ΄ν°λ₯Ό κ°μ ΈμμΌ ν μλ μμ΅λλ€. μ΄λ° κ²½μ°μλ μ΄λ¬ν μμ‘΄μ±μ μν₯μ μ΅μννλλ‘ λ Έλ ₯ν΄μΌ ν©λλ€.
`useEffect`μ `useState`λ₯Ό μ¬μ©ν μ‘°κ±΄λΆ νμΉ:
import { useState, useEffect } from 'react';
function UserProfile() {
const [userId, setUserId] = useState(null);
const [profile, setProfile] = useState(null);
const [blogPosts, setBlogPosts] = useState(null);
useEffect(() => {
// Simulate fetching the user ID (e.g., from local storage or a cookie)
setTimeout(() => {
setUserId(123);
}, 500); // Simulate a small delay
}, []);
useEffect(() => {
if (userId) {
// Fetch the user profile based on the userId
fetch(`/api/user/${userId}`) // Make sure your API supports this.
.then(res => res.json())
.then(data => setProfile(data));
}
}, [userId]);
useEffect(() => {
if (profile) {
// Fetch the user's blog posts based on the profile data
fetch(`/api/blog-posts?userId=${profile.id}`) //Make sure your API supports this.
.then(res => res.json())
.then(data => setBlogPosts(data));
}
}, [profile]);
if (!profile) {
return <p>Loading profile...</p>;
}
if (!blogPosts) {
return <p>Loading blog posts...</p>;
}
return (
<div>
<h1>{profile.name}</h1>
<p>{profile.bio}</p>
<h2>Blog Posts</h2>
<ul>
{blogPosts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
μ΄ μμ μμλ `useEffect` ν μ μ¬μ©νμ¬ μ‘°κ±΄λΆλ‘ λ°μ΄ν°λ₯Ό κ°μ Έμ΅λλ€. `profile` λ°μ΄ν°λ `userId`κ° μ¬μ© κ°λ₯ν΄μ§ νμλ§ κ°μ Έμ€κ³ , `blogPosts` λ°μ΄ν°λ `profile` λ°μ΄ν°κ° μ¬μ© κ°λ₯ν΄μ§ νμλ§ κ°μ Έμ΅λλ€.
μ₯μ :
- λΆνμν μμ² λ°©μ§: λ°μ΄ν°κ° μ€μ λ‘ νμν λλ§ κ°μ Έμ€λλ‘ λ³΄μ₯ν©λλ€.
- μ±λ₯ κ°μ : μ ν리μΌμ΄μ μ΄ λΆνμν API νΈμΆμ νμ§ μλλ‘ νμ¬ μλ² λΆνλ₯Ό μ€μ΄κ³ μ λ°μ μΈ μ±λ₯μ ν₯μμν΅λλ€.
κ³ λ €μ¬ν:
- λ‘λ© μν: μ¬μ©μμκ² λ°μ΄ν°κ° λ‘λ© μ€μμ μ리λ μ μ ν λ‘λ© μνλ₯Ό μ 곡νμΈμ.
- 볡μ‘μ±: μ»΄ν¬λνΈ λ‘μ§μ 볡μ‘μ±μ μ μνμΈμ. λ무 λ§μ μ€μ²©λ μμ‘΄μ±μ μ½λλ₯Ό μ΄ν΄νκ³ μ μ§ κ΄λ¦¬νκΈ° μ΄λ ΅κ² λ§λ€ μ μμ΅λλ€.
3. μλ² μ¬μ΄λ λ λλ§(SSR) λ° μ μ μ¬μ΄νΈ μμ±(SSG)
Next.jsλ μλ² μ¬μ΄λ λ λλ§(SSR)κ³Ό μ μ μ¬μ΄νΈ μμ±(SSG)μ λ°μ΄λ©λλ€. μ΄λ¬ν κΈ°μ μ μλ²λ λΉλ μμ μ½ν μΈ λ₯Ό 미리 λ λλ§νμ¬ ν΄λΌμ΄μΈνΈ μ¬μ΄λμμ μνν΄μΌ ν μμ λμ μ€μμΌλ‘μ¨ μ±λ₯μ ν¬κ² ν₯μμν¬ μ μμ΅λλ€.
`getServerSideProps`λ₯Ό μ¬μ©ν SSR:
export async function getServerSideProps(context) {
const product = await fetch(`http://example.com/api/product/${context.params.id}`).then(res => res.json());
const relatedProducts = await fetch(`http://example.com/api/related-products/${context.params.id}`).then(res => res.json());
return {
props: {
product,
relatedProducts,
},
};
}
function ProductPage({ product, relatedProducts }) {
return (
<div>
<h1>{product.name}</h1>
<p>{product.description}</p>
<h2>Related Products</h2>
<ul>
{relatedProducts.map(relatedProduct => (
<li key={relatedProduct.id}>{relatedProduct.name}</li>
))}
</ul>
</div>
);
}
μ΄ μμ μμ `getServerSideProps`λ νμ΄μ§λ₯Ό λ λλ§νκΈ° μ μ μλ²μμ μ ν μμΈ μ 보μ κ΄λ ¨ μνμ κ°μ Έμ΅λλ€. 미리 λ λλ§λ HTMLμ΄ ν΄λΌμ΄μΈνΈλ‘ μ μ‘λμ΄ μ΄κΈ° λ‘λ μκ°μ΄ λ λΉ¨λΌμ§λλ€.
`getStaticProps`λ₯Ό μ¬μ©ν SSG:
export async function getStaticProps(context) {
const product = await fetch(`http://example.com/api/product/${context.params.id}`).then(res => res.json());
const relatedProducts = await fetch(`http://example.com/api/related-products/${context.params.id}`).then(res => res.json());
return {
props: {
product,
relatedProducts,
},
revalidate: 60, // Revalidate every 60 seconds
};
}
export async function getStaticPaths() {
// Fetch a list of product IDs from your database or API
const products = await fetch('http://example.com/api/products').then(res => res.json());
// Generate the paths for each product
const paths = products.map(product => ({
params: { id: product.id.toString() },
}));
return {
paths,
fallback: false, // or 'blocking'
};
}
function ProductPage({ product, relatedProducts }) {
return (
<div>
<h1>{product.name}</h1>
<p>{product.description}</p>
<h2>Related Products</h2>
<ul>
{relatedProducts.map(relatedProduct => (
<li key={relatedProduct.id}>{relatedProduct.name}</li>
))}
</ul>
</div>
);
}
μ΄ μμ μμ `getStaticProps`λ λΉλ μμ μ ν μμΈ μ 보μ κ΄λ ¨ μνμ κ°μ Έμ΅λλ€. κ·Έλ° λ€μ νμ΄μ§λ 미리 λ λλ§λμ΄ CDNμμ μ 곡λλ―λ‘ λ§€μ° λΉ λ₯Έ λ‘λ μκ°μ 보μ₯ν©λλ€. `revalidate` μ΅μ μ μ μ§μ μ μ μ¬μμ±(ISR)μ νμ±ννμ¬ μ 체 μ¬μ΄νΈλ₯Ό λ€μ λΉλνμ§ μκ³ λ μ£ΌκΈ°μ μΌλ‘ μ½ν μΈ λ₯Ό μ λ°μ΄νΈν μ μκ² ν΄μ€λλ€.
μ₯μ :
- λ λΉ λ₯Έ μ΄κΈ° λ‘λ μκ°: SSRκ³Ό SSGλ ν΄λΌμ΄μΈνΈ μ¬μ΄λμμ μνν΄μΌ ν μμ λμ μ€μ¬ μ΄κΈ° λ‘λ μκ°μ λ¨μΆμν΅λλ€.
- SEO κ°μ : κ²μ μμ§μ 미리 λ λλ§λ μ½ν μΈ λ₯Ό μ½κ² ν¬λ‘€λ§νκ³ μΈλ±μ±ν μ μμ΄ SEOκ° ν₯μλ©λλ€.
- λ λμ μ¬μ©μ κ²½ν: μ¬μ©μκ° μ½ν μΈ λ₯Ό λ 빨리 λ³΄κ² λμ΄ λ λ§€λ ₯μ μΈ κ²½νμ μ 곡ν©λλ€.
κ³ λ €μ¬ν:
- λ°μ΄ν° μ΅μ μ±: λ°μ΄ν°κ° μΌλ§λ μμ£Ό λ³κ²½λλμ§ κ³ λ €νμΈμ. SSRμ μμ£Ό μ λ°μ΄νΈλλ λ°μ΄ν°μ μ ν©νλ©°, SSGλ μ μ μ½ν μΈ λ λλ¬Όκ² λ³κ²½λλ μ½ν μΈ μ μ΄μμ μ λλ€.
- λΉλ μκ°: SSGλ νΉν λκ·λͺ¨ μΉμ¬μ΄νΈμ κ²½μ° λΉλ μκ°μ μ¦κ°μν¬ μ μμ΅λλ€.
- 볡μ‘μ±: SSRκ³Ό SSGλ₯Ό ꡬννλ©΄ μ ν리μΌμ΄μ μ 볡μ‘μ±μ΄ μΆκ°λ μ μμ΅λλ€.
4. μ½λ μ€ν리ν
μ½λ μ€ν리ν μ μ ν리μΌμ΄μ μ½λλ₯Ό νμμ λ°λΌ λ‘λν μ μλ λ μμ λ²λ€λ‘ λλλ κΈ°μ μ λλ€. μ΄λ νμ¬ νμ΄μ§μ νμν μ½λλ§ λ‘λνμ¬ μ ν리μΌμ΄μ μ μ΄κΈ° λ‘λ μκ°μ μ€μΌ μ μμ΅λλ€.
Next.jsμμμ λμ μν¬νΈ(Dynamic Imports):
import dynamic from 'next/dynamic';
const MyComponent = dynamic(() => import('../components/MyComponent'));
function MyPage() {
return (
<div>
<h1>My Page</h1>
<MyComponent />
</div>
);
}
μ΄ μμ μμλ `next/dynamic`μ μ¬μ©νμ¬ `MyComponent`λ₯Ό λμ μΌλ‘ λ‘λν©λλ€. μ΄λ `MyComponent`μ μ½λκ° μ€μ λ‘ νμν λλ§ λ‘λλμ΄ νμ΄μ§μ μ΄κΈ° λ‘λ μκ°μ μ€μΈλ€λ κ²μ μλ―Έν©λλ€.
μ₯μ :
- μ΄κΈ° λ‘λ μκ° κ°μ: μ½λ μ€ν리ν μ μ΄κΈ°μ λ‘λν΄μΌ νλ μ½λμ μμ μ€μ¬ μ΄κΈ° λ‘λ μκ°μ λ¨μΆμν΅λλ€.
- μ±λ₯ κ°μ : νμν μ½λλ§ λ‘λν¨μΌλ‘μ¨ μ½λ μ€ν리ν μ μ ν리μΌμ΄μ μ μ λ°μ μΈ μ±λ₯μ ν₯μμν¬ μ μμ΅λλ€.
κ³ λ €μ¬ν:
- λ‘λ© μν: μ¬μ©μμκ² μ½λκ° λ‘λ© μ€μμ μ리λ μ μ ν λ‘λ© μνλ₯Ό μ 곡νμΈμ.
- 볡μ‘μ±: μ½λ μ€ν리ν μ μ ν리μΌμ΄μ μ 볡μ‘μ±μ μΆκ°ν μ μμ΅λλ€.
5. μΊμ±
μΊμ±μ μΉμ¬μ΄νΈ μ±λ₯μ ν₯μμν€κΈ° μν μ€μν μ΅μ ν κΈ°μ μ λλ€. μμ£Ό μ‘μΈμ€νλ λ°μ΄ν°λ₯Ό μΊμμ μ μ₯ν¨μΌλ‘μ¨ μλ²μμ λ°μ΄ν°λ₯Ό λ°λ³΅μ μΌλ‘ κ°μ Έμ¬ νμμ±μ μ€μ¬ μλ΅ μκ°μ λ¨μΆν μ μμ΅λλ€.
λΈλΌμ°μ μΊμ±: λΈλΌμ°μ κ° μ΄λ―Έμ§, CSS νμΌ, JavaScript νμΌκ³Ό κ°μ μ μ μμ°μ μΊμν μ μλλ‘ μλ²μμ μ μ ν μΊμ ν€λλ₯Ό μ€μ νλλ‘ κ΅¬μ±νμΈμ.
CDN μΊμ±: μ½ν μΈ μ μ‘ λ€νΈμν¬(CDN)λ₯Ό μ¬μ©νμ¬ μΉμ¬μ΄νΈ μμ°μ μ¬μ©μμ λ κ°κΉμ΄ κ³³μ μΊμνμ¬ μ§μ° μκ°μ μ€μ΄κ³ λ‘λ μκ°μ κ°μ νμΈμ. CDNμ μ½ν μΈ λ₯Ό μ μΈκ³ μ¬λ¬ μλ²μ λΆμ°μμΌ μ¬μ©μκ° κ°μ₯ κ°κΉμ΄ μλ²μμ μ‘μΈμ€ν μ μλλ‘ ν©λλ€.
API μΊμ±: API μλ²μ μΊμ± λ©μ»€λμ¦μ ꡬννμ¬ μμ£Ό μ‘μΈμ€νλ λ°μ΄ν°λ₯Ό μΊμνμΈμ. μ΄λ λ°μ΄ν°λ² μ΄μ€ λΆνλ₯Ό ν¬κ² μ€μ΄κ³ API μλ΅ μκ°μ κ°μ ν μ μμ΅λλ€.
μ₯μ :
- μλ² λΆν κ°μ: μΊμ±μ λ°μ΄ν°λ₯Ό λ°μ΄ν°λ² μ΄μ€μμ κ°μ Έμ€λ λμ μΊμμμ μ 곡νμ¬ μλ² λΆνλ₯Ό μ€μ λλ€.
- λ λΉ λ₯Έ μλ΅ μκ°: μΊμ±μ λ°μ΄ν°λ² μ΄μ€μμ λ°μ΄ν°λ₯Ό κ°μ Έμ€λ κ²λ³΄λ€ ν¨μ¬ λΉ λ₯Έ μΊμμμ λ°μ΄ν°λ₯Ό μ 곡νμ¬ μλ΅ μκ°μ κ°μ ν©λλ€.
- μ¬μ©μ κ²½ν κ°μ : λ λΉ λ₯Έ μλ΅ μκ°μ λ λμ μ¬μ©μ κ²½νμΌλ‘ μ΄μ΄μ§λλ€.
κ³ λ €μ¬ν:
- μΊμ 무ν¨ν: μ¬μ©μκ° νμ μ΅μ λ°μ΄ν°λ₯Ό λ³Ό μ μλλ‘ μ μ ν μΊμ 무ν¨ν μ λ΅μ ꡬννμΈμ.
- μΊμ ν¬κΈ°: μ ν리μΌμ΄μ μ νμμ λ°λΌ μ μ ν μΊμ ν¬κΈ°λ₯Ό μ ννμΈμ.
6. API νΈμΆ μ΅μ ν
API νΈμΆμ ν¨μ¨μ±μ Next.js μ ν리μΌμ΄μ μ μ λ°μ μΈ μ±λ₯μ μ§μ μ μΈ μν₯μ λ―ΈμΉ©λλ€. API μνΈ μμ©μ μ΅μ ννκΈ° μν λͺ κ°μ§ μ λ΅μ λ€μκ³Ό κ°μ΅λλ€:
- μμ² ν¬κΈ° μ€μ΄κΈ°: μ€μ λ‘ νμν λ°μ΄ν°λ§ μμ²νμΈμ. μ¬μ©νμ§ μλ λλμ λ°μ΄ν°λ₯Ό κ°μ Έμ€λ κ²μ νΌνμΈμ. GraphQLμ΄λ API μμ²μ νλ μ νκ³Ό κ°μ κΈ°μ μ μ¬μ©νμ¬ νμν λ°μ΄ν°λ₯Ό μ νν μ§μ νμΈμ.
- λ°μ΄ν° μ§λ ¬ν μ΅μ ν: JSONκ³Ό κ°μ ν¨μ¨μ μΈ λ°μ΄ν° μ§λ ¬ν νμμ μ ννμΈμ. ν¨μ¬ λ λμ ν¨μ¨μ±μ΄ νμνκ³ μΆκ°μ μΈ λ³΅μ‘μ±μ κ°μν μ μλ€λ©΄ νλ‘ν μ½ λ²νΌμ κ°μ λ°μ΄λ리 νμμ μ¬μ©νλ κ²μ κ³ λ €ν΄ λ³΄μΈμ.
- μλ΅ μμΆ: API μλ²μμ μμΆ(μ: gzip λλ Brotli)μ νμ±ννμ¬ μλ΅ ν¬κΈ°λ₯Ό μ€μ΄μΈμ.
- HTTP/2 λλ HTTP/3 μ¬μ©: μ΄λ¬ν νλ‘ν μ½μ λ©ν°νλ μ±, ν€λ μμΆ λ° κΈ°ν μ΅μ νλ₯Ό ν΅ν΄ HTTP/1.1μ λΉν΄ ν₯μλ μ±λ₯μ μ 곡ν©λλ€.
- μ¬λ°λ₯Έ API μλν¬μΈνΈ μ ν: μ ν리μΌμ΄μ μ νΉμ μꡬμ λ§κ² API μλν¬μΈνΈλ₯Ό ν¨μ¨μ μΌλ‘ μ€κ³νμΈμ. λλμ λ°μ΄ν°λ₯Ό λ°ννλ μΌλ°μ μΈ μλν¬μΈνΈλ νΌνμΈμ.
7. μ΄λ―Έμ§ μ΅μ ν
μ΄λ―Έμ§λ μ’ μ’ μΉνμ΄μ§ μ 체 ν¬κΈ°μ μλΉ λΆλΆμ μ°¨μ§ν©λλ€. μ΄λ―Έμ§λ₯Ό μ΅μ ννλ©΄ λ‘λ μκ°μ ν¬κ² κ°μ ν μ μμ΅λλ€. λ€μ λͺ¨λ² μ¬λ‘λ₯Ό κ³ λ €ν΄ λ³΄μΈμ:
- μ΅μ νλ μ΄λ―Έμ§ νμ μ¬μ©: JPEG, PNGμ κ°μ ꡬν νμμ λΉν΄ μμΆλ₯ κ³Ό νμ§μ΄ λ μ’μ WebPμ κ°μ μ΅μ μ΄λ―Έμ§ νμμ μ¬μ©νμΈμ.
- μ΄λ―Έμ§ μμΆ: νμ§μ λ무 λ§μ΄ ν¬μνμ§ μμΌλ©΄μ μ΄λ―Έμ§λ₯Ό μμΆνμΈμ. ImageOptim, TinyPNGμ κ°μ λꡬλ μ¨λΌμΈ μ΄λ―Έμ§ μμΆκΈ°λ₯Ό μ¬μ©νλ©΄ μ΄λ―Έμ§ ν¬κΈ°λ₯Ό μ€μΌ μ μμ΅λλ€.
- μ΄λ―Έμ§ ν¬κΈ° μ‘°μ : μΉμ¬μ΄νΈμ λ§λ μ μ ν ν¬κΈ°λ‘ μ΄λ―Έμ§ ν¬κΈ°λ₯Ό μ‘°μ νμΈμ. ν° μ΄λ―Έμ§λ₯Ό μμ ν¬κΈ°λ‘ νμνλ κ²μ λμνμ λλΉνλ―λ‘ νΌν΄μΌ ν©λλ€.
- λ°μν μ΄λ―Έμ§ μ¬μ©: μ¬μ©μμ νλ©΄ ν¬κΈ°μ κΈ°κΈ°μ λ°λΌ λ€λ₯Έ ν¬κΈ°μ μ΄λ―Έμ§λ₯Ό μ 곡νλ €λ©΄ `<picture>` μμλ `<img>` μμμ `srcset` μμ±μ μ¬μ©νμΈμ.
- μ§μ° λ‘λ©(Lazy Loading): μ΄λ―Έμ§κ° λ·°ν¬νΈμ λ³΄μΌ λλ§ λ‘λλλλ‘ μ§μ° λ‘λ©μ ꡬννμΈμ. μ΄λ νμ΄μ§μ μ΄κΈ° λ‘λ μκ°μ ν¬κ² μ€μΌ μ μμ΅λλ€. Next.jsμ `next/image` μ»΄ν¬λνΈλ μ΄λ―Έμ§ μ΅μ νμ μ§μ° λ‘λ©μ κΈ°λ³Έμ μΌλ‘ μ§μν©λλ€.
- μ΄λ―Έμ§μ CDN μ¬μ©: CDNμ μ΄λ―Έμ§λ₯Ό μ μ₯νκ³ μ 곡νμ¬ μ μ‘ μλμ μμ μ±μ ν₯μμν€μΈμ.
κ²°λ‘
Next.js μμ² μν°ν΄μ μΉ μ ν리μΌμ΄μ μ μ±λ₯μ ν° μν₯μ λ―ΈμΉ μ μμ΅λλ€. μν°ν΄μ μμΈμ μ΄ν΄νκ³ μ΄ κ°μ΄λμμ μ€λͺ ν μ λ΅μ ꡬνν¨μΌλ‘μ¨ λ°μ΄ν° λ‘λ©μ μ΅μ ννκ³ λ‘λ μκ°μ μ€μ΄λ©° λ λμ μ¬μ©μ κ²½νμ μ 곡ν μ μμ΅λλ€. μ΅μμ κ²°κ³Όλ₯Ό μ»κΈ° μν΄ μ ν리μΌμ΄μ μ μ±λ₯μ μ§μμ μΌλ‘ λͺ¨λν°λ§νκ³ μ΅μ ν μ λ΅μ λ°λ³΅μ μΌλ‘ κ°μ νλ κ²μ μμ§ λ§μΈμ. κ°λ₯ν λλ§λ€ λ³λ ¬ λ°μ΄ν° νμΉμ μ°μ μνκ³ , SSRκ³Ό SSGλ₯Ό νμ©νλ©°, API νΈμΆ λ° μ΄λ―Έμ§ μ΅μ νμ μΈμ¬ν μ£Όμλ₯Ό κΈ°μΈμ΄μΈμ. μ΄λ¬ν ν΅μ¬ μμμ μ§μ€ν¨μΌλ‘μ¨ μ¬μ©μλ₯Ό λ§μ‘±μν€λ λΉ λ₯΄κ³ μ±λ₯μ΄ λ°μ΄λλ©° λ§€λ ₯μ μΈ Next.js μ ν리μΌμ΄μ μ ꡬμΆν μ μμ΅λλ€.
μ±λ₯ μ΅μ νλ μΌνμ± μμ μ΄ μλ μ§μμ μΈ κ³Όμ μ λλ€. μ κΈ°μ μΌλ‘ μ½λλ₯Ό κ²ν νκ³ , μ ν리μΌμ΄μ μ μ±λ₯μ λΆμνλ©°, νμμ λ°λΌ μ΅μ ν μ λ΅μ μ‘°μ νμ¬ Next.js μ ν리μΌμ΄μ μ΄ λΉ λ₯΄κ³ λ°μμ± μκ² μ μ§λλλ‘ νμΈμ.