Next.js 데이터 fetching

2025. 5. 13. 21:28Coding Study/Next.js

 

React 에서의 데이터 Fetching

 react 에서는 useEffect 를 사용 하여 데이터를 fetching 을 하게 된다.

 이로서 컴포넌트가 렌더릴 될 때 나 데이터가 변경 되었을 때 데이터를 불러올 수 있다.

 하지만 화면이 렌더링 된 후 데이터를 불러오기 시작한다.

 빈화면이 보이고, 자바스크립트실행 해서 이제 드디여 화면이 보였는데

 또다시 데이터 fetching 하는 시간 까지 기다려야 한다.

 

Next.js 에서의 데이터 fetching

 

SSR (Server Side Rendering)

 Next.js 에서는 사전렌더링 과정중에 데이터 fetching 까지 수행 하여서 진행 하기 때문에 React 의 느린 FCP 를 좀더 빠르게 진행할 수

 있다.

 

 

 

<SSR 적용 방법>

   컴포넌트 상단에 getSeverSideProps를 작성한다.

   return 값으로 컴포넌트에 넘겨줄 props를 작성하고

  컴포넌트에서 받아서 쓰면, SSR 방식으로 작동하는 컴포넌트가 된다.

export const getServerSideProps = () => { // 서버에서 먼저 실행 되는 함수
  const data = "hello";   
  return {
    props: {              // 프롭으로 현재 파일에 작성된 컴포넌트에 데이터 전달한다.
      data,           
    },
  };
};



export default function Home({ data }) {  // 이 컴포넌트도 서버에서 먼저 실행되어서
  console.log(data);                     // HTML 파일로 변환이되어 클라이언트에 전달되면
  return (<></>                          // 클라이언트에서 다시 렌더링 된다.
  );
}

 

< 클라이언트(브라우저) 에서만 실행 하는 방법 >

여기서 상기의 코드는 서버에서 1번 ( 2) javaScript 실행 ), 브라우저 ( 6)javaScript 실행, 수화)에서 1번 총 2번 실행 된다는 점이다.

그래서 Home 컴포넌트의 console.log(data) 의 값인 'hello' 가 VSCode터미널에 1번 출력되고 브라우저 콘솔에 1번출력되어 총 2번 출력이 된다.

그리고 서버에서 실행 하는 2) jacaScript 실행 때문에 아래의 window 객체를 실행 하려고 하면 서버는 window 객체가 없어서 에러가 발생 한다.

export default function Home({ data }) {  
  window.location                         // 서버에는 window 객체가 없어서 에러!
  return (<></>                         
  );
}

 

서버에서는 실행을 안하고 

클라이언트에서만 1번 실행 하게 하려면 useEffect 로 작성하면 클라이언트에서만 실행 하게 할 수 있다. 

export default function Home({ data }) {  

useEffect(()=>{            
 console.log(window) // 이제는 렌더링 이후에 클라이언트(브라우저)에서만 1번 실행 함
}.[])
               
  return (<></>                         
  );
}

 

 

 Home 컴포넌트도 결론적으로 2번 실행이 되어서 서버에서  "hello" 가 출력이되고

 브라우저 console 에도 "hello" 가 출력이된다.

 

home 컴포넌트가 클라이언트에서 1번만 실행 하고 싶다면 useEffect 를 사용 하면 된다.

 

useEffect(() =>{   // 컴포넌트가 렌더링된 이후에 실행됨
 console.log(window)
},[])

 

SSG (Server Side Generation)

항상 버전을 최신버전으로 유지할 수 있는 장점이 있지만 매번 새로운 데이터를 받아온다. 

그런데 이때 서버상태가 않좋다거나 주고받아야 하는 데이터의 용량이 크거나 해서 응답 속도가 늦어지게 되면 데이터를 받아올때까지

사용자는 기다려야 하는 불편한 경험을 주는 치명적인 단점이 있다.

SSR 방식에서의 데이터 패칭이 늦어질 경우

 

이러한 단점을 보안 하기 위한 새로운 사전렌더링 방식이 SSG 이다.

API 요청 응답이 늦어 질때는 build Time 에 미리 받아오는 방법이다.

npm run build 할 때 미리 데이터를 받아온 페이지를 만들어 놓는 것이다.

하지만 단점으로는 다시는 페이지를 새로 생성하지 않기때문에 최신데이터 반영은 하지 못한다는 점이다.

SGG 방식에서의 Data fetching

 

 

< SSG 적용 방법 >

 컴포넌트상단에 getStaticProps 라는 함수를 작성해서 컴포넌트로 props 를 전달하면 이제 Home 컴포넌트는

 SSG 방식으로 작동 하게 된다.

 다만 실행 시 주의 점은 Product 모드로 진행 해야 SSG 방식으로 작동하는 것을 확인할 수 있다. 

 개발 모드에서는 실행 시 getStaticprops 함수내의 코드도 실행 해서 터미널에 출력 한다. 

export const getStaticProps = () => {   // SSG 방식으로 작동
  const data = "hello";                 // 이제 터미널에 출력되지 않는다.(npm build 후 product 모드로 해야함 )
  return {	                         // 개발모드에서는 여전히 터미널에 출력 되니 주의													
    props: {           
      data,           
    },
  };
};



export default function Home({ data }) {  
  console.log(data);                     
  return (<></>                         
  );
}

 

npm build 로 생성하게되면  생성된 모든 페이지의 특성을 아래의 기호로 나타내 준다.

 

 

 동적경로에 SSG 적용하기

 

동적경로 즉 book/1 이나 book/2 와 같은 경로에 getStaticProps를 사용하면 에러가 발생하는데 getStaticPaths 를 적용 해야 한다는 말이다. 

 

그래서 아래와 같이 1,2 3 의 페이지는 미리 만들어 놓고 fallback 옵션을 false 로 하면 없는 경로 요청 시 404 를 반환

fallback 이란 지정해둔 페이지외에는 어떻게 해야 하는지에 대한 옵션이다.

export const getStaticPaths = () => {  // 동적경로에 SSG 적용
  return {
    paths: [
      { params: { id: "1" } },  // URL parameter 는 문자로 지정해야 함
      { params: { id: "2" } },
      { params: { id: "3" } },
    ],
    fallback: false, // id 1,2,3 외 페이지는 404 반환
  };
};


 fallback : "blocking"  옵션

첫번째 요청에는 SSR 방식으로 하고

다음번에는 SSG 방식으로 페이지를 받아옴

 

 fallback : true  옵션 

  Props 없는 페이지를 먼저 반환 후 

  Props 계산해서 페이지 반환

  --> 컴포넌트의 UI 를 먼저 렌더링 하고 후속으로 props 데이터는 나중에 전달 한다.

 

 

현재 페이지가 fallback 상태* 일때 router 객체의 isFallback 객체를 아래와 같이 사용할 수 있다.

const router = useRouter();
  if (router.isFallback) return "로딩중입니다.";

*fallback 상태 : 페이지 컴포넌트가 아직 서버로부터 데이터를 전달받지 못한 상태

 

 

ISR ( Increment Static Regeneration )

 ISR 방식은 생성된 정적 페이지를 일정시간을 주기로 다시 생성한다.

 revalidate 옵션에 시간(초) 를 입력 하면 지정된 시간 동안은 업데이트 하지 않다가.

 지정된 시간이 지난 후에 요청을 하게 되면,

 기존 페이지를 일단 먼저 보내고 추후에 업데이트 되면 새로운 페이지를 전달한다.

 

< 적용방법>

export const getStaticProps = async () => {

  console.log("인덱스페이지");

  const [allBooks, recoBooks] = await Promise.all([
    fetchBooks(),
    fetchRandomBooks(),
  ]);

  return {
    props: {
      allBooks,
      recoBooks,
    },
    revalidate: 3,     // 3초마다 페이지 재 생성 옵션 추가
  };
};

 

 

OnDemend ISR

 요청을 받을 때 마다 페이지를 새로 생성

 src> pages > api 의 폴더에서 파일을 새로 만들고 아래의 api 요청 코드를 작성한다.

 res.revalidate('/') 가 실행 되면 root 경로의 페이지가 재검증 되면서 새로 업데이트가 된다.

 

참고로 api 폴더내의 파일명으로 작성시 /pages/api/ 파일명  을하게되면 api 요청을 할 수 있다. 

 

그렇기 때문에 "/pages/api/ 파일명" 주소로 API 요청을 보내면 페이지가 업데이트 되는 것이다. 

export default async function handler( req,res ) {
  try {
    await res.revalidate("/");
    return res.json({ revalidate: true });
  } catch (err) {
    res.status(500).send("Revalidation Failed");
    console.log(err);
  }
}

 

'Coding Study > Next.js' 카테고리의 다른 글

Next.js 사전렌더링  (0) 2025.05.13
Next.js 페이지 라우터  (2) 2025.05.01