Loading...
본문 바로가기
👥
총 방문자
📖
0개 이상
총 포스팅
🧑
오늘 방문자 수
📅
0일째
블로그 운영

여러분의 방문을 환영해요! 🎉

다양한 개발 지식을 쉽고 재미있게 알려드리는 블로그가 될게요. 함께 성장해요! 😊

코딩 정보/NextJs

[NextJs] 서버 컴포넌트를 통한 데이터 가져오기

by 꽁이꽁설꽁돌 2025. 4. 5.
728x90
반응형
     

목차

     

     

    클라이언트 측에서 데이터를 가져와 쓰게 되면 아래와 같이 페이지 소스에서 보이지 않는다.

    따라서 서버 컴포넌트를 이용해야 한다.

     

     

    use client를 이용한 이전 코드

    "use client";
    import NewsList from "@/components/news-list";
    import { useEffect, useState } from "react";
    export default function NewsPage() {
      const [news, setNews] = useState([]);
      const [isLoading, setIsLoading] = useState(false);
      const [error, setError] = useState();
      useEffect(() => {
        async function fetchNews() {
          setIsLoading(true);
          const response = await fetch("http://localhost:8080/news");
          if (!response.ok) {
            setError("Failed to fetch News..");
            setIsLoading(false);
          }
          const news = await response.json();
          setIsLoading(false);
          setNews(news);
        }
        fetchNews();
      }, []);
    
      if (isLoading) {
        return <p>Loading...</p>;
      }
      if (error) {
        return <p>{error}</p>;
      }
      return (
        <>
          <h1>News Page</h1>
          <NewsList news={news} />
        </>
      );
    }

     

     

    use server를 이용한 코드

    import NewsList from "@/components/news-list";
    
    export default async function NewsPage() {
      const response = await fetch("http://localhost:8080/news");
    
      if (!response.ok) {
        throw new Error("Failed to fetch news.");
      }
    
      const news = await response.json();
    
      return (
        <>
          <h1>News Page</h1>
          <NewsList news={news} />
        </>
      );
    }

     

    아래와 같이 리소스가 담겨 있는 것을 볼 수 있고 이것은 seo에 이점을 줄 수 있다.

     

     

    로딩 페이지 세밀하게 조정하기

    아래와 같이 원하는 컴포넌트에 suspend로 감싸면 그 부분에서 데이터를 가져올 때 loading fallback을 만들 수 있다.

    import NewsList from "@/components/news-list";
    import {
      getAvailableNewsMonths,
      getNewsForYear,
      getNewsForYearAndMonth,
    } from "@/lib/news";
    import Link from "next/link";
    import { getAvailableNewsYears } from "@/lib/news";
    import { Suspense } from "react";
    
    async function FilterHeader({ year, month }) {
      const availableYears = await getAvailableNewsYears();
    
      let links = availableYears;
    
      if (
        (year && !availableYears.includes(year)) ||
        (month && !getAvailableNewsMonths(year).includes(month))
      ) {
        throw new Error("Invalid filter.");
      }
      if (!month && year) {
        links = getAvailableNewsMonths(year);
      }
    
      if (year && month) {
        links = [];
      }
      return (
        <header id="archive-header">
          <nav>
            <ul>
              {links.map((link) => {
                const href = year
                  ? `/archive/${year}/${link}`
                  : `/archive/${link}`;
                return (
                  <li key={link}>
                    <Link href={href}>{link}</Link>
                  </li>
                );
              })}
            </ul>
          </nav>
        </header>
      );
    }
    
    async function FilteredNews({ year, month }) {
      let news;
    
      if (year && !month) {
        news = await getNewsForYear(year);
      } else if (year && month) {
        news = await getNewsForYearAndMonth(year, month);
      }
      let newsContent = <p>No news found for the selected period.</p>;
      if (news && news.length > 0) {
        newsContent = <NewsList news={news} />;
      }
      return newsContent;
    }
    
    export default async function FilteredNewsPage({ params }) {
      const filter = (await params).filter;
    
      const selectedYear = filter?.[0];
      const selectedMonth = filter?.[1];
    
      const availableYears = await getAvailableNewsYears();
    
      let links = availableYears;
    
      if (!selectedMonth && selectedYear) {
        links = getAvailableNewsMonths(selectedYear);
      }
    
      if (selectedYear && selectedMonth) {
        links = [];
      }
    
      return (
        <>
          <Suspense fallback={<p>Loading filter...</p>}>
            <FilterHeader year={selectedYear} month={selectedMonth} />
          </Suspense>
          <Suspense fallback={<p>Loading news...</p>}>
            <FilteredNews year={selectedYear} month={selectedMonth} />
          </Suspense>
        </>
      );
    }
    
    //archive 이후 모든 경로 세그먼트에 대해
    //활성화되도록 보장

     

    반응형