소스 :
https://github.dev/mschwarzmueller/nextjs-course-code/tree/04-data-fetching
https://github.dev/mschwarzmueller/nextjs-course-code/tree/05-prj-data-fetching
https://nextjs-event1.netlify.app/
1.index.js
import fs from "fs"; import path from "path"; import Link from "next/link"; // HomePage 컴포넌트: props로 전달된 제품 목록을 렌더링 function HomePage(props) { const { products } = props; return ( <ul> {products.map((product) => ( <li key={product.id}> {/* 각 제품을 링크로 표시, 클릭 시 해당 제품의 상세 페이지로 이동 */} <Link href={`/products/${product.id}`} >{product.title}</Link> </li> ))} </ul> ); } // getStaticProps 함수: 정적 페이지 생성을 위한 데이터 페칭 export async function getStaticProps(context) { // 파일 경로 설정: 현재 작업 디렉토리에서 "data/dummy-backend.json" 파일을 가리킴 const filePath = path.join(process.cwd(), "data", "dummy-backend.json"); // 파일을 읽어 JSON 데이터를 문자열로 가져옴 const jsonData = fs.readFileSync(filePath, "utf8"); // JSON 문자열을 JavaScript 객체로 파싱 const data = JSON.parse(jsonData); // 데이터가 없는 경우 '/no-data'로 리디렉션 if(!data){ return{ redirect:{ destination: '/no-data' } } } // 데이터에 제품이 없는 경우 404 페이지를 반환 if(data.products.length === 0) { return { notFound: true }; } // 데이터가 유효한 경우, props로 제품 목록을 전달 return { props: { products: data.products, }, // 페이지를 10초마다 재생성하여 최신 데이터를 반영 revalidate: 10, }; } export default HomePage;
주석 요약
- HomePage 컴포넌트: props로 전달된 products 목록을 받아와 각 제품을 링크로 렌더링합니다. 클릭 시 제품의 상세 페이지로 이동합니다.
- getStaticProps 함수: Next.js의 정적 사이트 생성(SSG)을 위해 사용됩니다.
- 파일 경로 설정: dummy-backend.json 파일의 경로를 설정합니다.
- 파일 읽기: 해당 파일을 읽어 JSON 데이터를 문자열로 가져옵니다.
- JSON 파싱: 문자열을 JavaScript 객체로 파싱합니다.
- 데이터 검증 및 리디렉션/404 처리: 데이터가 없거나 제품이 없는 경우 적절하게 처리합니다.
- 유효한 데이터 반환: 유효한 데이터가 있는 경우, 이를 props로 전달하고 페이지를 10초마다 재생성하도록 설정합니다.
2.[pid].js
import React, { Fragment } from "react"; import fs from "fs"; import path from "path"; // ProductDetailPage 컴포넌트: props로 전달된 제품의 상세 정보를 렌더링 const ProductDetailPage = (props) => { const { loadedProduct } = props; // 로딩 상태 처리: 제품 정보가 없을 경우 로딩 메시지 표시 if (!loadedProduct) { return <h1>Loading...</h1>; } // 제품 정보가 있을 경우 제목과 설명을 렌더링 return ( <Fragment> <h1>{loadedProduct.title}</h1> <p>{loadedProduct.description}</p> </Fragment> ); }; // 데이터 페칭 함수: 로컬 파일에서 제품 데이터를 읽어와 파싱 async function getData() { const filePath = path.join(process.cwd(), "data", "dummy-backend.json"); const jsonData = fs.readFileSync(filePath, "utf8"); const data = JSON.parse(jsonData); return data; } // getStaticProps 함수: 제품 상세 정보를 정적 페이지로 생성하기 위한 데이터 페칭 export async function getStaticProps(context) { const { params } = context; // URL 매개변수에서 제품 ID 추출 const productId = params.pid; const data = await getData(); // 데이터 페칭 // 제품 ID에 해당하는 제품 찾기 const product = data.products.find((product) => product.id === productId); // 제품이 없을 경우 404 페이지 반환 if (!product) { return { notFound: true }; } // 제품이 있을 경우 제품 정보를 props로 전달 return { props: { loadedProduct: product, }, }; } // getStaticPaths 함수: 정적 경로를 생성하기 위한 모든 제품 ID를 지정 export async function getStaticPaths() { const data = await getData(); // 데이터 페칭 const ids = data.products.map((product) => product.id); // 모든 제품 ID 추출 // 제품 ID를 이용하여 경로 생성 const pathsWithParams = ids.map((id) => ({ params: { pid: id } })); return { paths: pathsWithParams, // 생성할 경로 목록 fallback: false, // fallback 설정 (해당 경로가 없으면 404 페이지 반환) }; } export default ProductDetailPage;
주석 요약
- ProductDetailPage 컴포넌트: props로 전달된 loadedProduct를 사용하여 제품의 제목과 설명을 렌더링합니다. 제품 정보가 없을 경우 로딩 메시지를 표시합니다.
- getData 함수: 로컬 파일 시스템에서 제품 데이터를 읽어와 JSON 객체로 파싱합니다.
- getStaticProps 함수: Next.js의 정적 사이트 생성(SSG)을 위해 사용됩니다. params에서 제품 ID를 추출하고, 해당 ID의 제품 정보를 찾아 props로 전달합니다. 제품이 없을 경우 404 페이지를 반환합니다.
- getStaticPaths 함수: Next.js의 동적 경로를 위한 함수입니다. 모든 제품 ID를 사용하여 정적 경로를 생성합니다. fallback이 false로 설정되어 있어, 경로가 존재하지 않을 경우 404 페이지를 반환합니다.
3.[uid].js
// UserIdPage 컴포넌트: props로 전달된 사용자 ID를 렌더링 function UserIdPage(props) { return <h1>{props.id}</h1>; } export default UserIdPage; // getServerSideProps 함수: 서버 사이드에서 동적으로 데이터를 가져오기 위해 사용 export async function getServerSideProps(context) { const { params, req, res } = context; // 요청 컨텍스트에서 매개변수, 요청, 응답 객체 추출 const userId = params.uid; // URL 매개변수에서 사용자 ID 추출 // props로 전달할 데이터 반환 return { props: { id: "userid-" + userId, // 사용자 ID를 "userid-" 접두어와 함께 반환 }, }; }
주석 요약
- UserIdPage 컴포넌트: props로 전달된 id를 사용하여 사용자 ID를 렌더링합니다.
- getServerSideProps 함수: Next.js의 서버 사이드 렌더링(SSR)을 위해 사용됩니다. 요청 컨텍스트에서 URL 매개변수, 요청 객체, 응답 객체를 추출합니다.
- params: URL 매개변수를 포함하며, 여기서 사용자 ID (uid)를 추출합니다.
- req 및 res: 요청(Request) 및 응답(Response) 객체로, 필요시 추가적인 처리를 할 수 있습니다.
- 반환값: props 객체를 반환하여 UserIdPage 컴포넌트에 사용자 ID를 전달합니다. userid- 접두어를 붙여서 반환합니다.
이 코드는 서버 사이드에서 사용자 ID를 동적으로 가져와 페이지를 렌더링하는 간단한 예제입니다.
4.client-photos.js
import { useEffect, useState } from "react"; import useSWR from "swr"; // Fetcher 함수 정의: 주어진 URL에서 데이터를 가져와 JSON으로 파싱 const fetcher = (...args) => fetch(...args).then(res => res.json()) // LastSalesPage 컴포넌트: 판매 데이터를 렌더링 function LastSalesPage() { const [salesData, setSalesData] = useState([]); // 상태 변수로 판매 데이터 초기화 // useSWR 훅 사용: 지정된 URL에서 데이터를 가져옴 const { data, error, isValidating } = useSWR("https://jsonplaceholder.typicode.com/photos", fetcher); // useEffect 훅 사용: 데이터가 변경될 때마다 판매 데이터를 설정 useEffect(() => { if (data) { console.log("==================>", data); setSalesData(data); } }, [data]); // 에러 발생 시 에러 메시지 렌더링 if (error) { return <h1>Error....</h1>; } // 데이터가 유효화되고 있을 때 로딩 메시지 렌더링 if (isValidating) { return <h1>Loading....</h1>; } // 판매 데이터를 렌더링 return ( <div> <h1>Sales Data</h1> <ul> {salesData && salesData.map((sale) => ( <li key={sale.id}> <img src={sale.thumbnailUrl} alt={sale.title} /> {sale.title} </li> ))} </ul> </div> ); } export default LastSalesPage;
주석 요약
- Fetcher 함수: fetcher 함수는 주어진 URL에서 데이터를 가져와 JSON으로 파싱합니다.
- LastSalesPage 컴포넌트: 판매 데이터를 렌더링합니다.
- 상태 변수: salesData 상태 변수로 판매 데이터를 관리합니다.
- useSWR 훅: 지정된 URL에서 데이터를 가져오고, data, error, isValidating 값을 반환합니다.
- useEffect 훅: data가 변경될 때마다 salesData를 설정합니다.
- 에러 처리: 에러가 발생하면 에러 메시지를 렌더링합니다.
- 로딩 상태: 데이터가 유효화되고 있을 때 로딩 메시지를 렌더링합니다.
- 데이터 렌더링: salesData를 렌더링하고 각 항목에 이미지와 제목을 표시합니다
5.sever-photos.js
import { useEffect, useState } from "react"; import useSWR from 'swr'; // 데이터 가져오는 fetcher 함수 정의 const fetcher = (...args) => fetch(...args).then(res => res.json()) // LastSalesPage 컴포넌트 정의 function LastSalesPage({ initialData }) { // 상태 변수 정의: initialData를 초기 값으로 설정 const [salesData, setSalesData] = useState(initialData); // useSWR 훅 사용: 데이터를 가져오고 상태 관리 const { data, error, isValidating } = useSWR("https://jsonplaceholder.typicode.com/photos", fetcher, { initialData, // 초기 데이터 설정 }); // useEffect 훅 사용: 데이터가 업데이트될 때마다 상태 업데이트 useEffect(() => { if (data) { setSalesData(data); // 데이터가 있으면 salesData 상태 업데이트 } }, [data]); // data가 변경될 때 useEffect 실행 // 에러 발생 시 에러 메시지 출력 if (error) { return <h1>Error....</h1>; } // 데이터 유효화 중일 때 로딩 메시지 출력 if (isValidating) { return <h1>Loading....</h1>; } // 정상적으로 데이터가 로드된 경우 판매 데이터 렌더링 return ( <div> <h1>Sales Data</h1> <ul> {salesData && salesData.map((sale) => ( <li key={sale.id}> <img src={sale.thumbnailUrl} alt={sale.title} /> {sale.title} </li> ))} </ul> </div> ); } // getStaticProps 함수: 정적 페이지 생성을 위해 데이터를 사전에 가져옴 export async function getStaticProps() { const data = await fetcher("https://jsonplaceholder.typicode.com/photos"); // 데이터 가져오기 return { props: { initialData: data, // 초기 데이터를 props로 전달 }, }; } export default LastSalesPage; // 컴포넌트 export
주석 요약
- fetcher 함수: 주어진 URL에서 데이터를 가져와 JSON으로 파싱하는 함수입니다.
- LastSalesPage 컴포넌트: 판매 데이터를 렌더링하는 함수형 컴포넌트입니다.
- 상태 관리: useState 훅을 사용하여 salesData 상태를 관리합니다.
- 데이터 가져오기: useSWR 훅을 사용하여 주어진 URL에서 데이터를 가져옵니다. initialData로 초기 데이터를 설정합니다.
- 데이터 업데이트: useEffect 훅을 사용하여 data가 업데이트될 때마다 salesData 상태를 업데이트합니다.
- 에러 처리: error가 발생하면 에러 메시지를 출력합니다.
- 로딩 상태: 데이터를 가져오는 중일 때 isValidating 값에 따라 로딩 메시지를 출력합니다.
- 데이터 렌더링: 정상적으로 데이터를 로드하면 판매 데이터를 화면에 렌더링합니다.
- getStaticProps 함수: Next.js에서 정적 페이지 생성을 위해 데이터를 사전에 가져오는 함수입니다. fetcher를 사용하여 데이터를 가져온 후, 초기 데이터를 props로 전달합니다.
이 코드는 Next.js와 swr 라이브러리를 사용하여 데이터를 비동기적으로 가져오고, 정적 페이지 생성에 필요한 초기 데이터를 사전에 준비하는 방법을 보여줍니다.
댓글 ( 0)
댓글 남기기