I turn coffee into code ☕ → 💻 자세히보기

개발/프로젝트

Next.js에서 SWR 사용하기

xuwon 2025. 8. 31. 16:44

이번 프로젝트에서는 서버 컴포넌트를 제대로 사용해보려고 마음 먹었다!!

// 서버 컴포넌트
import React from "react";
import { Api } from "../api/api";
import { TAG_MAP, TagVariant } from "../components/common/tag/tag.types";
import { Marker } from "../page";
import MapClient from "./client";

const Page = async () => {
  // 서버에서 마커 데이터 가져오기
  const markersData = await Api.getAllMarkers();

  const markers = markersData.map((marker: Marker) => ({
    id: marker.id,
    lat: marker.lat,
    lng: marker.lng,
    emotion: (TAG_MAP[marker.tags[0] as keyof typeof TAG_MAP] ||
      "기본") as TagVariant,
  }));

  return <MapClient markers={markers} />;
};

export default Page;

데이터를 받아와서 지도에 마커를 띄우는 페이지였는데, 서버 컴포넌트에서 미리 데이터를 받아서 클라이언트 컴포넌트로 넘겨주었다.

클라이언트 컴포넌트에서는 받은 markers 데이터를 그대로 사용했는데,
develop 브랜치 배포 환경에서만 해도 잘 됐었다.

그런데...
main 배포로 바꾸고 나니까 원래 있던 데이터들만 보이고 새로 추가한 위치 데이터가 안 뜨기 시작했다.


찾아보니까
SSG (Static Site Generation) 때문이었다.

Next.js의 서버 컴포넌트에서 데이터를 패칭하면 기본적으로 정적 페이지가 생성된다.
즉, Api.getAllMarkers()를 호출했을 때의 결과가 빌드 시점에 고정되어 버리고,
이후에 데이터가 바뀌더라도 새로 빌드하지 않는 한 페이지에는 반영되지 않는다. . . . !!!

서버 컴포넌트를 처음 사용해봐서 이제야 깨달았다.
그래서 다른 방안을 찾아야 했는데 후보는 여러 가지가 있었다.

 

1. 강제로 SSR 적용
export const dynamic = "force-dynamic";
export const revalidate = 0;

이걸 상단에 선언하면 매 요청마다 새 데이터를 받아온다고 한다.

그치만 계속 요청을 하는 거니까 캐싱의 장점을 잃게 되고, 트래픽 비용이나 응답 속도 면에서 부담이 될 수 있다.

 

2. ISR(Incremental Static Regeneration) 사용

두번째로 ISR 사용이 있다.

export const revalidate = 60; // 60초마다 새로 빌드

이렇게 하면 60초마다 데이터가 갱신되기 때문에 자주 변하지 않는 데이터라면 ISR 사용이 유리하다.

그치만 나는 위치 등록을 바로 하면 등록이 되도록 하고 싶었다.

 

3. 아예 클라이언트 컴포넌트에서 호출하기

이건 뭐... 최대한 배제하고 싶었다.

난 서버 컴포넌트를 쓰고 싶기 때문에!!!

 

4. SWR 사용하기

그래서 선택한 방법이 SWR이었다.

서버 컴포넌트에서 한 번 데이터를 가져와 fallbackData로 내려주고,
클라이언트에서는 SWR을 이용해 최신 데이터를 다시 패칭할 수 있다.
이렇게 하면 초기 렌더링 시 깜빡임 없이 서버 데이터가 바로 보이고, 이후에는 SWR이 자동으로 최신 데이터를 불러와 갱신해준다. . .!!

const { data: markers } = useSWR("/posts/markers", fetcher, {
  fallbackData: initialMarkers || [],
});

그래서 클라이언트 컴포넌트에서 useSWR을 활용해서 초기에는 서버에서 내려준 데이터( fallbackData )를 보여주고, 이후에는 자동으로 최신 데이터를 가져와 반영하도록 했다. (fetcher는 데이터 페칭 함수)
덕분에 사용자는 첫 화면에서 데이터가 비어 보이는 깜빡임을 경험하지 않으면서도, 최신 상태의 마커들을 볼 수 있다!

주의점은, 이렇게 바꾸면 클라이언트에서 SWR이 데이터를 다시 가져오는 동안 일시적으로 markers가 비어 있는 상태가 될 수 있다.
그래서 예외처리를 꼼꼼하게 바꿔주었다!

실제로 SWR에는 더 많은 기능들이 있지만, 급하게 수정한 거라서 딱 기본 기능만 사용하게 되었다.