개발자

next.js app-router에서 fetch revalidate 옵션을 주었을 때 데이터가 갱신되지 않는 현상

2024년 02월 29일조회 289

현재 서버에서 하루 단위로 DB데이터를 업데이트하고 있습니다. 거기에 맞춰 프론트단에서도 하루 단위로 갱신된 데이터를 보여주기 위해 api fetch옵션인 `{ next: {revadliate : 36000} }` 을 설정해 두었습니다. 그런데 revalidate로 설정한 시간이 지나도 화면에 나타나는 데이터가 갱신되지 않아요... 개발 환경에선 업데이트 된 데이터가 나오다가도 배포 페이지에선 이전 데이터가 나오는거 같아요. (배포는 aws로 했습니다) 서버 db 데이터는 잘 업데이트 되고있는걸 확인했습니다. 혼자서 자료를 아무리 찾아봐도 원인과 해결법을 모르겠어서 도움 요청합니다ㅠㅠ fetch 코드와 fetch를 호출하는 코드도 함께 첨부합니다.

1// fetch코드
2import { APIResponse } from "@/src/types/APIResponse";
3import { objectToQueryString } from "@/src/utils/common/objectController";
4import { APIAdapter } from "./adapter";
5
6export class Fetch implements APIAdapter {
7  private fetchOptions: RequestInit;
8
9  // fetch 초기설정
10  constructor(cookie?: Record<string, any>) {
11    this.fetchOptions = {
12      method: "GET",
13      headers: {
14        "Content-Type": "application/json",
15        Cookie: cookie ? objectToQueryString(cookie, ";") : "",
16      },
17      credentials: "include",
18      body: null,
19      next: {
20        revalidate: 0,
21      },
22    };
23  }
24
25...
26
27  // fetch next-revalidate 옵션 설정
28  setRevalidate(revalidate: number | false | undefined): void {
29    this.fetchOptions.next = {
30      ...this.fetchOptions.next,
31      revalidate,
32    };
33  }
34
35  // fetch함수 실행
36  async fetching<T>(url: string): Promise<APIResponse<T>> {
37    try {
38      const rs = await fetch(url, this.fetchOptions);
39      const data = await rs.json();
40
41      return {
42        ...data,
43        status: rs.status,
44      };
45    } catch (error) {
46      return {
47        result: "fail",
48        status: 500,
49        message: "알 수 없는 에러 발생",
50        payload: {} as T,
51      };
52    }
53  }
54}
55
56
57
58// fetch 사용하는 코드 - api를 호출하고 이벤트 정보를 가져
59export async function getRecentEvents(): Promise<
60  APIResponse<EventThumbnail[]>
61> {
62  // fetchAdapter 인스턴스 생성
63  const apiFetch = new Fetch(); 
64  // revalidate 옵션 설정
65  apiFetch.setRevalidate(36000);
66  // fetch 실행
67  const rs = await apiFetch.fetching<MainEventsPayload>(`${url}/latest`);
68  // 데이터 포맷 변경
69  const data = rs?.payload.events.rows.map((event: Event) => ({
70    thumbnail: event.thumbnail,
71    id: event.id,
72    title: event.title,
73  }));
74
75  return {
76    ...rs,
77    payload: data,
78  };
79}
이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.
profile picture
익명님의 질문

답변 1

백승훈님의 프로필 사진

안녕하세요 답변 드립니다 😏 개발 환경에서 정상 작동한다면 배포 환경의 캐싱 데이터가 아직 존재할 수 있습니다. https://www.smileshark.kr/post/how-to-set-cachecontrol-header-in-amazon-cloudfront 혹시 AWS에서 Cloudflare나 다른 캐싱 서비스 (Redis)등을 제공하는 서비스와 연결되어 있으실 것 같은대 해당 부분에서 캐싱 데이터가 업데이트되지 않아 발생하는 문제일 확율이 높습니다. 혹은 Next의 버전에 따라 SSG나 ISR을 사용하셨다면 재갱신 주기를 설정하거나 빌드 시 html 파일이 이미 완성된 상태라 구조 자체를 다시 확인하셔야 할 수 있습니다.

profile picture

익명

작성자

2024년 02월 29일

안녕하세요 답변 감사합니다! aws에서는 E2C로 단순 배포만 하였고 cludflare, redis 등을 사용하지 않은거 같아요. 제가 배포했지만 aws를 잘 모른채 그냥 따라한거라.. 복잡한 기능은 사용하지 않은 것 같습니다. 컴포넌트가 ssg, isr인지 확인하기 위해 build해보았는데 람다 아이콘(Dynamic)이 뜹니다. 문득 든 생각인데 혹시 fetch를 실행하는 컴포넌트가 SSR인게 이유일수도 있을까요?

백승훈님의 프로필 사진

백승훈

프론트 엔드 개발자 (FE)2024년 02월 29일

좀더 정확하게 확인해보기 위해선 배포시 통신의 결과값을 먼저 확인해보세요 백엔드와 Rest API 통신 및 CSR환경이면 통신 응답을 보실 수 있으실꺼고 그 응답에 제대로된 값이 들어오는지 보시면됩니다. SSR 환경이면 서버에서 그려줄 때 캐싱된 이전값을 불러와 사용하거나 할 가능성도 있습니다. 자세한건 저도 코드랑 사이트를 봐야 아는거라 일단 해당 항목부터 점검해보세요😏

profile picture

익명

작성자

2024년 03월 28일

알고보니 revalidate는 잘 동작하는데 서버쪽 DB업데이트 시간과 제가 설정한 revalidate시간 차이때문에 업데이트되지 않아보였던 버그(?)였습니다! 답변감사했습니다😊

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

AI 답변
커리어리 AI 봇 프로필 이미지

커리어리 AI 봇

GPT가 달아주는 답변입니다.

2024년 02월 29일

Next.js의 revalidate 옵션은 `getStaticProps` 또는 `getServerSideProps`에서 사용되며, 데이터를 가져오는 방법입니다. 이것은 Incremental Static Regeneration(ISR)이라고 오직 Next.js에서만 제공하는 기능으로써, 특정 페이지가 다시 생성되어야 할 시점을 설정할 수 있게 해줍니다. 하지만 웹 브라우저(fetch API) 또는 Node.js(fetch 모듈) 환경에서 fetch를 사용할 때 next-revalidate 옵션은 존재하지 않습니다. 따라서 이 부분에 대한 문제 해결 방법은 Next.js의 ISR 기능을 활용하는 것입니다. ISR기능을 사용하게 되면, 첫번째 유저의 요청엔 기존에 생성된 정적페이지를 제공합니다. 그리고 해당 요청과 동시에 백그라운드 작업으로 새롭게 페이지를 생성합니다. 따라서 두번째 유저부터는 새롭게 생성된 데이터로 구성된 페이지를 볼 수 있습니다. ISR을 설정하기 위해선 다음과 같이 코드를 작성할 수 있습니다:: ```typescript export const getStaticProps = async () => { ... // 데이터 fetch 요청 const data = await getRecentEvents() return { props: { data }, // Next revalidate 설정 (10 시간) revalidate: 36000, }; }; ``` 위와 같이 `getStaticProps` 내에서 `revalidate` 값을 설정하여 원하시는 갱신 주기를 만들 수 있습니다. 그리고 이렇게 가져온 prop을 페이지 컴포넌트에 전달해서 사용할 수 있습니다.

목록으로

지금 가입하면 모든 질문의 답변을 볼 수 있어요!