2025. 11. 4. 01:47ใTrouble Shooting & Issues/Linkiving

๋ชฉ์ฐจ
1. ์ด๋ค ํ์ผ๋ค์ด ์๋๊ฐ
2. API
2-1. api.ts
2-2. products.ts
2-3. useProducts.ts
3. useProducts.ts
4. Components
4-1. ItemCard.tsx
4-2. ItemList.tsx
4-3. Pagination.tsx
4-4. AllProducts.tsx
5. Trouble Shooting
5-1. ๋ฆฌ๋ ๋๋ง ์ ๊น๋นก๊ฑฐ๋ฆผ
5-2. next/image๋ฅผ ์ฌ์ฉํ ์ ์์๊น
5-3. apis/์๋ products.ts, type/์๋ products.ts์ธ๋ฐ ์ด๋๋ ๋๋
5-4. ํ์ฌ types/products.ts์๋ body์ ๋ด๊ธด ๋ด์ฉ์ค์์๋ ๋น์ฅ ํ์ํ ๊ฒ๋ง ์์ฑํ๋๋ฐ ๊ทธ๋ฅ ?๋ถ์ฌ์ ์ ๋ถ ์์ฑํ๋ ๊ฒ ์ข์๊น?
5-5. ProductsResponse ํ์ ๋ช ์ด๋๋ก๋ ๊ด์ฐฎ์๊ฐ
5-6. UseProductResult์ products, totalCount๋ ProductsResponse์ ๊ตฌ์กฐ๋ ๊ฒน์น๋๋ฐ ๋๋ ์ ์์ฑํ๋ ๊ฒ ๋ง๋?
1. ์ด๋ค ํ์ผ๋ค์ด ์๋๊ฐ
ํ์ฌ ๊ตฌํ์ ์๋ฃํ ์ํ์ด๋ค.
๊ทธ๋ฐ๋ฐ ๊ณ์ ์๋๋ ๊ฒ๋ค์ ์์ ํ๋ฉด์ ํ๋ค๋ณด๋ ๋๋ฌด.. ๋ชจ๋ ๊ฒ๋ค์ด ์ ๋ฆฌ๊ฐ ์๋๊ณ ํท๊ฐ๋ฆฌ๋ ์ํ์ฌ์ ์ ๋ฆฌํ๋ ๊ธ.
| ๊ธฐ์ ์คํ | ํ์ ์ ์ | API | Components |
| ⋅ Next.js ⋅ TypeScript ⋅ Axios |
products.ts export interface Product {
id: number;
name: string;
price: number;
favoriteCount: number;
images: string;
}
|
⋅ api.ts ⋅ products.ts ⋅ useProducts.ts |
⋅ ItemCard.tsx ⋅ ItemList.tsx ⋅ Pagination.tsx ⋅ AllProducts.tsx |
2. API
1. api.ts
๊ณตํต API ํด๋ผ์ด์ธํธ ์ค์ ์ ํ๋ ํ์ผ์ด๋ค.
// 1. axios ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ถ๋ฌ์ค๊ธฐ
import axios from 'axios';
// 2. axios ์ธ์คํด์ค ์์ฑ
const api = axios.create({
baseURL: 'https://example.vercel.app',
timeout: 5000,
headers: {
'Content-Type': 'application/json',
},
});
// 3. ์๋ต ์ธํฐ์
ํฐ ๋ฑ๋ก
api.interceptors.response.use(
(res) => res.data,
(err) => Promise.reject(err),
);
export default api;
// 1. axios ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ถ๋ฌ์ค๊ธฐ
axios๋ฅผ ๋ถ๋ฌ์๋ค.
// 2. axios ์ธ์คํด์ค ์์ฑ
axios.create()๋ก api๋ฅผ axios ์ธ์คํด์ค๋ก์จ ์์ฑํ๊ณ , ์ธ์คํด์ค๊ฐ ์์ํ ๊ธฐ๋ณธ๊ฐ๋ค์ ์ง์ ํ๋ค.
| baseURL | ⋅ ์ด ์ธ์คํด์ค๋ก ์ํํ๋ ์์ฒญ๋ค์ ์๋๊ฒฝ๋ก(/)๋ง ์ง์ ํด๋ baseURL์ ๊ฒฐํฉํ์ฌ ์ต์ข ์์ฒญ URL์ด ๊ตฌ์ฑ๋๋ค. |
| timeout | ⋅ ์์ฒญ์ด ์๋ต์ ๋ฐ๊ธฐ๊น์ง ์ต๋ 5์ด๋ก ์ค์ ํ์ฌ, 5์ด๋ฅผ ์ด๊ณผํ๋ฉด ์์ฒญ์ ์ทจ์ํ๊ณ ์๋ฌ๋ฅผ ๋ฐ์์ํจ๋ค. |
| headers | ⋅ ์ด ์ธ์คํด์ค๋ก ์ ์ก๋๋ ๋ชจ๋ ์์ฒญ์ ๊ธฐ๋ณธ ํค๋๋ฅผ ์ง์ ํ๋ค. ⋅ ์ฌ๊ธฐ์ ์ง์ ํ ํค๋๋ ์๋ฒ์ JSON ๋ฐ๋๋ฅผ ๋ณด๋ผ ๋ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉํ๋ MIME ํ์ ์ด๋ค. |
// 3. ์๋ต ์ธํฐ์ ํฐ ๋ฑ๋ก
์ธํฐ์ ํฐ๋ ๋ชจ๋ ์๋ต(์ฑ๊ณต/์คํจ)์ ๋ํด ํต์ผ๋ ์ ํ์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํ๋ค. (๊ณตํต ์๋ฌ ์ฒ๋ฆฌ, ์๋ต ๋ณํ, ์ธ์ฆ ๋ง๋ฃ ์ฒ๋ฆฌ ๋ฑ)
๋น์ฅ์ ํ์ ์์ผ๋ ์ผ๋จ ์์ฑํด๋ฌ๋ดค๋ค.
| (res) | ⋅ ์๋ต ์ฑ๊ณต ์ฝ๋ฐฑ ⋅ ์๋ฒ๋ก๋ถํฐ ์๋ต ๊ฐ์ฒด(res) ๋์ ๊ทธ ์์ data ํ๋๋ง ๋ฐํํ๋๋ก(res.data) ํ๋ค. ⋅ axios์ ํ์ค ์๋ต ๊ฐ์ฒด๋ { data, status, headers, ... } ํํ์ด๋, ๋๋ถ๋ถ์ ์ฑ์ data๋ง ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ด๋ค. |
| (err) | ⋅ ์๋ต ์คํจ ์ฝ๋ฐฑ ⋅ ์๋ต ์๋ฌ๊ฐ ๋ฐ์ํ์ ๋ ์ธํฐ์ ํฐ์์ Promise.reject()๋ก ์๋ฌ๋ฅผ ์ฌ์ ๋ฌํ๋ค. ⋅ ์ด๋ ๊ฒ ํ๋ฉด ์ธํฐ์ ํฐ ์ดํ์ try, catch์์ ์๋ฌ๋ฅผ ์ผ๊ด๋๊ฒ ์ก์ ์ ์๋ค. ⋅ Promise.reject(err)๋ Rejected Promise๋ฅผ ๋ฐํํ๋ ํ์ค JS ๋ฐฉ์์ด๋ค. |
2. products.ts
products ๊ด๋ จ API ์์ฒญ ํจ์๋ฅผ ์ ์ํ ํ์ผ์ด๋ค.
// 1. ์ ์ํ ํ์
๋ฐ api ๋ถ๋ฌ์ค๊ธฐ
import { Product } from '@/types/product';
import api from './api';
const END_POINT = '/products/';
// 2. ์๋ตํํ ํ์
์ ์
interface ProductsResponse {
list: Product[];
totalCount: number;
}
// 3. getProductsList ํจ์ ์ ์ธ
export const getProductsList = (option = {}):Promise<ProductsResponse> => {
return api.get(END_POINT, {
params: option
});
}
// 4. getTargetProduct ํจ์ ์ ์ธ
export const getTargetProduct = (productId:number)=>{
return api.get(`${END_POINT}${productId}/`);
}
// 1. ์ ์ํ ํ์ ๋ฐ api ๋ถ๋ฌ์ค๊ธฐ
์ ์ํ Product ํ์ ๊ณผ api๋ฅผ ๋ถ๋ฌ์จ๋ค.
๋ํ API ๊ฒฝ๋ก(์๋ํฌ์ธํธ)๋ฅผ ์์๋ก ์ ์ธํ๋ค.
// 2. ์๋ตํํ ํ์ ์ ์
getProductsList๊ฐ ๋ฐํํ ๋ฐ์ดํฐ์ ํ์ ์ ์ ์ํ๋ค.
- list: Product[] → Product ๊ฐ์ฒด ๋ฐฐ์ด๋ก, ์ค์ API์์ ์ํ ๋ชฉ๋ก์ด ๋ค์ด์ค๋ ํ๋
- totalCount : number → ์ ์ฒด ์ํ ์ (ํ์ด์ง์ ์ํด ํ์)
์๋ตํํ ํ์ ์ swagger ui์์ ํ์ธํ๊ณ ์์ฑํ๋ค.

// 3. getProductsList ํจ์ ์ ์ธ
| option = {} | ⋅ ๊ธฐ๋ณธ๊ฐ์ด ๋น ๊ฐ์ฒด์ธ ๋งค๊ฐ๋ณ์๋ก, ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ฌ๋ฐ๋๋ค. ⋅ Swagger์ ๋ฐ๋ฅด๋ฉด page, pageSize, orderBy, keyword ์ด๋ ๊ฒ ๋ค ๊ฐ์ง๋ฅผ ๋ฐ์ ์ ์๋ค. |
| ๋ฐํํ ํ์
Promise<ProductsResponse> |
⋅ ์ด ํจ์๊ฐ ProductsResponse ํ์
์ ๊ฐ์ ํฌํจํ Promise๋ฅผ ๋ฐํํ ๊ฒ์ ์ ์ธํ๋ค. ⋅ ๋ํ Promise๋ฅผ ๋ถ์์ผ๋ฏ๋ก ๋น๋๊ธฐ์ ๋์์ ํจ๋ ๋ํ๋ธ๋ค. |
| return๊ฐ | ⋅ api.get()์ผ๋ก GET ์์ฒญ์ ๋ณด๋ธ๋ค. ⋅ ์ฒซ๋ฒ์งธ ์ธ์: ์ต์ข URL๋ก, api์ baseURL๊ณผ ๊ฒฐํฉ๋์ด https://.../products/๊ฐ ์ต์ข ํํ์ด๋ค. ⋅ ๋๋ฒ์งธ ์ธ์: ์ฟผ๋ฆฌ์คํธ๋ง์ผ๋ก ๋ณํ๋ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ฌํ๋ค. { params: { page: 2 } } ํํ๋ผ๋ฉด, ์๋์ผ๋ก ?page=2๋ก ๋ณํ๋๋ค. |
// 4. getTargetProduct ํจ์ ์ ์ธ
productId: number๋ฅผ ์ธ์๋ก ๋ฐ๋๋ค.
์ธ์๋ก ๋ฐ์ productId๋ api.get()์ผ๋ก ์์ฒญ์ ๋ณด๋ผ ๋ ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด๋ก ๊ตฌ์ฑํ์ฌ ๋ณด๋ธ๋ค.
ํ์ฌ๋ก์จ๋ ์์ง ์ฌ์ฉํ์ง ์๊ณ ์ ์ธ๋ง ํด๋ ๊ฑฐ์ฌ์ ๋ฐํํ์ ์ ๋ช ์ํ์ง ์์๋ค. (์ถํ ๋ช ์ ํ์)
3. useProducts.ts
useProducts.ts๋ ์์ด ์ข ๋ง์์ API์ ์๋ฃ๊ณ ๋ฐ๋ก ๋บ๋ค.
์ฝ๋๊ฐ ์ข ๊ธธ์ด์ ๊ทธ๋ฅ ๋๋ ์ ์์๋๋ก ์ ๋ฆฌํด๋ณด๊ฒ ๋ค.
1. ํ์ํ ํ์ผ๋ค ๋ถ๋ฌ์ค๊ธฐ
"use client";
import { getProductsList } from "@/apis/products";
import { useState, useEffect, useRef } from "react";
import { Product } from "@/types/product";
ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ๋์ํ๋๋ก ์ง์ ํ๋ค. ํ ๋ด๋ถ์์ ๋ธ๋ผ์ฐ์ ์ ์ฉ api( useState, useEffect .. )๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ด๋ค.
๋ํ ํ ์์ ํ์ํ ํ์ผ๋ค์ ๋ถ๋ฌ์๋ค.
- getProductsList : ๋ฐฑ์์ ์ํ ๋ชฉ๋ก์ GETํ๋ API ํธ์ถ ๋ํผ
- use@@ : ์ํ, ์ฌ์ด๋์ดํํธ, ๋ ํผ๋ฐ์ค ๊ด๋ฆฌ
- Product : ์ํ ๊ฐ์ฒด ๊ตฌ์กฐ
2. ํ ํ๋ผ๋ฏธํฐ ํ์ ์ ์ (ํ ํํ ๋จน์ผ ๊ฑฐ)
interface UseProductsParams {
page?: number;
pageSize?: number;
orderBy?: "recent" | "favorite";
search?: string;
}
ํ ์ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌํ ํ์ ์ ์ ์ํ๋ค. Swagger ๋ฌธ์์ ๋ฐ๋ผ ์์ฑํ๋ค.

3. ํ ๋ฐํ ๊ฐ์ฒด ํ์ ์ ์ (ํ ์ด ๋ฑ์ ๊ฑฐ)
interface UseProductResult {
products: Product[];
totalCount: number;
loading: boolean;
error: Error | null;
}
ํ ์ด ๋ฐํํ ๊ฐ์ฒด์ ํ์ ์ ์ ์ํ๋ค.
๊ฐ์ฒด ๋ฐ๋์ธ list, totalCount๋ฅผ ํฌํจํด์ loading, error๋ ์ถ๊ฐ๋ก ์ ์ํ๋ค.
4. useProducts ์ ์ธ
export const useProducts = ({
page,
pageSize,
orderBy,
search
} : UseProductsParams): UseProductResult => { ...
UserProductsParams ํ์ ์ ๋ฐ๋๋ก ์ ์ธํ์ผ๋ฉฐ, ๋ฐํ๊ฐ์ผ๋ก UseProductResult ํ์ ์ ๊ฐ์ง๋๋ก ํ๋ค.
ํ๋ผ๋ฏธํฐ๋ค์ ์ด๊ธฐ๊ฐ์ ์๋ฒ์์ ๋ณด์ฅํ๊ธฐ ๋๋ฌธ์ ์ด๊ธฐ๊ฐ ์ง์ ์ ํ์ง ์์๋ค.
5. ๋ณ์ ๋ฐ setter ์ ์ธ
const [products, setProducts] = useState<Product[]>([]);
const [totalCount, setTotalCount] = useState(0);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
| products, totalCount | ⋅ ์ค์ ๋ณด์ฌ์ค ๋ฐ์ดํฐ์ ์ด ๊ฐ์ |
| loading | ⋅ ์ด๊ธฐ ๋ก๋ฉ(์ด๊ธฐ ๋ง์ดํธ ์) ์ฌ๋ถ ⋅ true๋ก ์ด๊ธฐํํ์ฌ ๋ง์ดํธ ์ ๋ก๋๊ฐ ์์์ ๋ช ํํ ํจ |
| error | ⋅ ์๋ฌ ๊ฐ์ฒด |
6. fetchProducts ์ ์
fetchProducts๋ try, catch, finally๋ฅผ ๊ฐ์ง๋ค. ๊ฐ ํํธ๋ณ๋ก ๋๋ ์ ์ ๋ฆฌํ์.
try
// fetchProducts() : ์ํ ๋ถ๋ฌ์ค๊ธฐ
const fetchProducts = async (initial = false) => {
if (initial) setLoading(true);
setError(null);
try {
const res = await getProductsList({
page,
pageSize,
orderBy,
search,
});
// ๋ฐ์ดํฐ ๋งคํ
const list = (res.list ?? []).map(
(p: Product): Product => ({
id: p.id,
name: p.name,
price: p.price,
favoriteCount: p.favoriteCount,
images: p.images?.[0],
}),
);
// ๋ฐ์ดํฐ ์ํ ์
๋ฐ์ดํธ
setProducts(list ?? []);
setTotalCount(res.totalCount ?? 0);
}
- fetchProducts๋ ์ค์ API ํธ์ถ์ ๋ด๋นํ๋ค.
initial ํ๋๊ทธ๋ก ์ด๊ธฐ๋ก๋(true)์ธ์ง, ์๋๋ฉด ์ฌ์์ฒญ(false)์ธ์ง ๊ตฌ๋ถํ๋ค. - setError(null)๋ก ์์ฒญ ํ๊ธฐ ์ ์ ๊ธฐ์กด ์๋ฌ๋ฅผ ์ด๊ธฐํ ํ๋ค.
getProductsList()
- axios ์์ฒญํ๋ ํจ์์ธ getProductsListfh API๋ฅผ ํธ์ถํ๋ค.
- ํ๋ผ๋ฏธํฐ๋ก ์ฟผ๋ฆฌ(page, pageSize, orderBy, search)๋ค์ ์ ์กํ๋ค.
mapped
- getProductsList๋ก ํธ์ถํด์ ์๋ต๋ฐ์ ๊ฐ์ด res์ ์๋ค. res์ ๋ค์ด์๋ ๋ฐ์ดํฐ๋ฅผ ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ ๋ณ์์ ๋งคํํด์ค์ผ ํ๋ค.
- ๋ฐ๋๋ฅผ ๋ณด๋ฉด "list" ๋ฐฐ์ด ์์ ๋งคํํ ๋ฐ์ดํฐ๋ค์ด ๋ค์ด์์์ผ๋ฏ๋ก res.list(๋น์๋ค๋ฉด ๋น ๋ฐฐ์ด[])์ ๋ฐ์ดํฐ๋ฅผ Product์ ๋งคํํ๋ค.
catch, finally
catch (err) {
if (err instanceof Error) setError(err);
else setError(new Error("Unknown error"));
} finally {
setLoading(false);
}
};
catch๋ก ์๋ฌ ์ฒ๋ฆฌ๋ฅผ ํ๊ณ , finally๋ก ์์ฒญ ์๋ฃ ์ loading์ false๋ก ์ธํ ํ๋ค.
7. ๋ง๋ฌด๋ฆฌ
// initialParams์ ๊ฐ ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค fetch
useEffect(() => {
fetchProducts();
}, [page, pageSize, orderBy, search]);
// refetch
const refetch = async () => {
await fetchProducts(); // refetch๋ false
};
return { products, totalCount, loading, error };
};
useEffect()๋ก ์์์ ์ ์ํ fetchProducts๋ฅผ ํธ์ถํ๋ค.
ํ๋ผ๋ฏธํฐ๊ฐ์ด ๋ฌ๋ผ์ง ๋๋ง๋ค ํธ์ถํ๋ค.
๋ฆฌ๋ ๋๋ง์ ์ํ refetch๋ฅผ ์ ์ํด์ ๋ฆฌํด๊ฐ์ ํฌํจ์ํจ๋ค.
4. Components
1. ItemCard.tsx
๋ณธ๋ฌธ
2. ItemList.tsx
๋ณธ๋ฌธ
3. Pagination.tsx
๋ณธ๋ฌธ
4. AllProducts.tsx
๋ณธ๋ฌธ
5. TroubleShooting
1. ๋ฆฌ๋ ๋๋ง์ ๊น๋นก๊ฑฐ๋ฆผ
์ด์ ์๋ try๋ฌธ์ ์์ํ ๋ ํญ์ setLoading(true)๊ฐ ์คํ๋๋๋ก ๋์ด์์๋ค.
์ด ๋์ React ๋์ ์์๋ฅผ ์ดํด๋ณด์.
- ์ฒ์ ํ์ด์ง ๋ ๋(products๊ฐ ๋น์ด์์. ๋ํ loading๋ true๋ก ์ด๊ธฐํ๋์ด ์์)
- fetchProducts() ํธ์ถํ์ฌ ๋ฐ์ดํฐ ์์ฒญ → setLoading(true)
→ React๊ฐ ๋ฆฌ๋ ๋๋ง
→ ํ๋ฉด์์ ๊ธฐ์กด ์นด๋ DOM์ ์ ๊ฑฐ (๋น ์ํ) - ๋ฐ์ดํฐ ๋์ฐฉ → setProducts(list) + setLoading(false)
→ React๊ฐ ๋์ฐฉํ ๋ฐ์ดํฐ๋ก ๋ฆฌ๋ ๋๋ง
→ ์นด๋ UI๊ฐ ์๋ก ๊ทธ๋ ค์ง
ํ๋ฉด์ ์ฒซ ๋ ๋๋ง์ด ์๋ฃ๋ ํ loading์ finally๋ฌธ์์ false ์ํ๊ฐ ๋๋ค.
ํ์ง๋ง ํ์ด์ง๋ค์ด์ ์ผ๋ก ๋ฆฌ๋ ๋๋ง์ ํ ๋๋ง๋ค loading์ true๋ก ๋ฐ๊ฟ๋๋ง๋ค React๊ฐ ๊ธฐ์กด DOM์ ์ด๊ธฐํํ๊ณ ์ฌ๋ ๋๋ง์ ํ๋ฉฐ ๊น๋นก์์ด ๋ฐ์ํ๊ฒ ๋๋ ๊ฒ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด if (initial) setLoading(true)๋ฅผ ์์ฑํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น?
์ฐ์ ๊ฐ์ฅ ์ฒ์ ํ์ด์ง๋ฅผ ๋ก๋ํ์ ๋๋ loading์ด true์ผ ๊ฒ์ด๋ค. (์ฒ์์ ๊ทธ๋ ๊ฒ ์ด๊ธฐํํ๊ธฐ ๋๋ฌธ)
ํ์ง๋ง ๊ทธ ๋ค๋ก ํ์ด์ง๋ฅผ ์๋ก๊ณ ์นจํ๋ ๊ฒ์ด ์๋๋ผ๋ฉด loading์ false์ํ๊ฐ ๋๋ค.
- ์ด๊ธฐ ๋ ๋ (loading = true)
- ๋ฐ์ดํฐ ๋์ฐฉ → setProducts(list) + setLoading(false)
→ ์นด๋ UI ๋ ๋๋ง - ํ์ด์ง๋ค์ด์
๋ฑ์ผ๋ก refetch → initial = false
→ setLoading(true)๊ฐ ํธ์ถ๋์ง ์์
→ ๊ธฐ์กด ์นด๋ UI ๊ทธ๋๋ก ์ ์งํ๊ณ ๋ฐ์ดํฐ๋ง ๊ต์ฒด
→ React๋ DOM ์ผ๋ถ๋ง ๊ฐฑ์ ํ์ฌ ๊น๋นก์์ด ์์
์ด๋ ๊ฒ loading ์ํ๋ฅผ ๊ฐ์ ๋ก true๋ก ๋๋ฆฌ์ง ์๊ฒํ์ฌ ๊น๋นก์์ ์ง์ ๋ค.
โ๊ทธ๋ฐ๋ฐ ์ด๋ ๊ฒ loading ์ํ๋ฅผ ์ง์๋ ๊ด์ฐฎ์๊น??
์ด๋ ๊ฒ ํ๋ฉด ๊ฐ๋ฐ์๋๊ตฌ์์ ๋คํธ์ํฌ์ throttling์ ๊ฑธ์์ ๋ ์ฌ์ฉ์๊ฐ ๋ฐ์ดํฐ์ ๋ก๋ฉ ์ฌ๋ถ๋ฅผ ํ์ธํ ์ ์๋ค.
ํ์ด์ง๋ค์ด์ ์ผ๋ก ํ์ด์ง๋ฅผ ๋๊ฒจ๋ ์๋ฌด๋ฐ ์ก์ ์์ด ๋ฐ์ดํฐ๊ฐ ๋์ฐฉํ ๋๊น์ง ์ด์ ๋ฐ์ดํฐ๋ง ๋์ฐ๊ธฐ ๋๋ฌธ์ด๋ค.
โ ์ด ๋ถ๋ถ์ ์ฌ์ค ์ด์ ์ ๋ค๋ฅธ ๊ณผ์ ํ์ ์์ ๋ค๋ฃฌ ์ ์ด ์๋ค.

skeleton ์์ ์ ์ถ๊ฐ๋ก ํ๋ ๊ฒ์ด๋ค.
์ ์ ์นด์นด์ค ๋ธ๋ก๊ทธ์์ ์ค์ผ๋ ํค์ ๋ฌด์กฐ๊ฑด์ ์ผ๋ก ๋์ฐ๋ฉด ์คํ๋ ค ๊น๋นก์ด๋ ๋๋์ ์ฃผ์ด ํผ๋ก๊ฐ์ ์ค ์ ์๋ค๋ ๊ฒ์ ๋ณด๊ณ ์์ฑํ๋ ๊ฒ์ด๋ค.
์ปดํฌ๋ํธ ๋ง์ดํธ ํ 0.2์ด๊ฐ์ skeleton์ ๋ณด์ด์ง ์์ผ๋, 0.2์ด๊ฐ ๋์ผ๋ฉด ์ค์ผ๋ ํค์ ๋ณด์ธ๋ค.
์ค์ผ๋ ํค์ ๋์ฐ๊ณ ๊ธฐ๋ค๋ฆฌ๋๋์ ๋ฐ์ดํฐ๊ฐ ๋ก๋๋๋ฉด ๋ฐ์ดํฐ๋ฅผ ๊ทธ๋๋ก ๋ณด์ด๋ ๊ฑฐ๋ค.
ํ ์์๋ ์ค์ผ๋ ํค์ ๋ณด์ผ์ง ์ฌ๋ถ๋ง ์๋ ค์ฃผ๊ณ ๋ณด์ฌ์ฃผ๋๊ฑด UI์์ ๋งก๊ฒ๋๋๋ฐ,
๊ทธ๊ฑธ ์๊ฐํ๋ฉด ์ฌ์ค loading์ด ๋ค์๋ true๋ก ๋ ์ ์๋ ์ ์ฝ๋์ ๊ตฌ์กฐ๋ ๋ฌธ์ ๊ฐ ์๋ค.
(์ ๋๋ ๋ฐ์ดํฐ๋ฅผ ๋ชฝ๋ ๋ถ๋ฌ์์ ๋ฌธ์ ๊ฐ ๋ฐ๊ฒฌ๋์ง ์์๋ค.)
์ด ๋ถ๋ถ์ ์ค์ผ๋ ํค์ ๊ตฌํํ ํ, ์ฒดํฌํ๋ฉด์ ๋ค์ ๋ค๋ค๋ด์ผ๊ฒ ๋ค. ์ผ๋จ ์ง๊ธ์ ๊น๋นก์์ ํด๊ฒฐํ๊ธด ํ๋ค.
2. next/image๋ฅผ ์ฌ์ฉํ ์ ์์๊น
์ฐธ๊ณ
https://axios-http.com/docs/intro
Getting Started | Axios Docs
Getting Started Promise based HTTP client for the browser and node.js What is Axios? Axios is a promise-based HTTP Client for node.js and the browser. It is isomorphic (= it can run in the browser and node.js with the same codebase). On the server-side it
axios-http.com
'Trouble Shooting & Issues > Linkiving' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [Next.js] ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๋งํฌ์ ์ธ๋ค์ผ ๊ฐ์ ธ์ค๊ธฐ (0) | 2025.11.17 |
|---|---|
| ์ธํฐ๋ ์ ์ด ๊ฐ๋ฅํ ํ๊ทธ ์ค์ฒฉ ์์ํค๊ธฐ (0) | 2025.11.05 |
| ๊ธฐ๋ณธ TextArea์ ํ์ฅ์ฑ ๊ณ ๋ฏผ (์ ์ ? ๋์ ?) (0) | 2025.11.03 |
| [WIP]npm์์ pnpm์ผ๋ก ๋ฐ๊ฟจ๋๋ storybook action์ด ์๋จนํ๋ค (0) | 2025.11.03 |
| Button ์ปดํฌ๋ํธ ๋ฆฌํฉํ ๋ง ํ๊ธฐ (0) | 2025.10.27 |
GitHub