[Next.js] SWR 데이터 갱신 안되는 현상

hyejinJo·2023년 7월 6일
0

React

목록 보기
4/9
post-thumbnail

문제 상황: 댓글 기능을 만드는 중 댓글이 등록되어 해당 댓글이 속한 리스트 데이터가 변경 되었는데, 변경된 데이터가 클라이언트 측으로 바로 갱신되지 않는 문제가 발생했다.
이 때문에 사용자가 댓글을 쓴 바로 직후 화면이 업데이트 되지 않고 새로고침을 하고 나서야 화면에 반영되는 것이다.

SWR 을 이용해서, 서버에 보낸 변경된 데이터가 실시간으로 클라이언트에도 적용되도록 하고싶은데
바로 반영이 안되었던 이유는, SWR 이 캐싱과 재사용을 기반으로 동작하기 때문에 데이터의 변경이 즉시 반영되지 않을 때가 있기 때문이었다. 😱

그렇기에 데이터를 변경한 후 캐시를 새로 갱신해야했고, SWR 에서 제공하는 mutate 라는 함수를 사용하여 데이터를 캐싱 및 업데이트 할 수 있었다.

mutate 함수는 캐시된 데이터를 직접 갱신하고 컴포넌트를 리렌더링 해준다. 예를 들어, 데이터를 변경한 후에 mutate 함수를 호출하여 캐시된 데이터를 갱신할 수 있다.

// mutate 함수를 import
import useSWR, { mutate } from 'swr';

// 데이터 변경 후의 시점에 mutate 함수 호출
mutate('/api/data', updatedData);

이렇게 mutate 함수를 호출하면 SWR은 해당 키의 데이터를 다시 가져오고 캐시된 데이터를 갱신한다. 컴포넌트도 자동으로 리렌더링되어 변경된 데이터가 반영된다.

위의 방식은 SWR 의 함수인 mutate 를 전역으로 사용하는 방식이고, 그 안에 특정 경로를 넣으면 된다.

우리는 아래처럼 useSWR 훅을 사용하는 방식으로 해결했다. useSWR 훅은 데이터를 가져오기 위해 사용 되지만 반환값으로 mutate 함수 또한 제공된다. 이 방식은 우리가 현재 useSWR 훅을 통해 가져온 데이터를 갱신하고자 할 때 사용 되는데, 일반적으로 해당 방법이 더 권장되고 있다고 한다!

해결:

...
  const { data: commentListData, mutate, isLoading } = useSWR(
      router.isReady &&
      router.pathname.split('/')[1] === 'daily' &&
      router.query.id
          ? `/api/manager-comment?${$queryToString(router.query)}&currentPage=1&dutyDiarySeq=${router.query.id}`
          : null
  )
...

const handleCommentSubmit = async (body) => {
    try {
      ...
      )
      if (code === 'SUC001') {
        await alertPop('success', '댓글이 작성되었습니다.')
        await mutate
      } else {
        ...

🤔 궁금했던 점

1. mutate() 안에 경로를 넣지 않고도 실행이 잘 된 이유:

mutate() 함수는 경로를 명시적으로 지정하지 않았을 때 기본적으로 이전에 사용한 경로(useSWR 훅을 호출할 때 전달한 경로와 동일한 경로)에 대한 캐시를 갱신하고 갱신 후 컴포넌트가 다시 렌더링된다.

2. 다른 컴포넌트에서 경로가 사용되어 엉뚱한 경로로 갱신되는 경우

mutate() 함수는 호출한 컴포넌트의 경로에 대한 캐시를 갱신하므로 다른 컴포넌트의 캐시는 영향을 받지 않는다. 경로가 다른 컴포넌트의 데이터를 갱신하려면 해당 컴포넌트에서 mutate() 함수를 호출해야 한다.


공식문서: SWR 뮤테이션(Mutation) & 재검증(Revalidation)

profile
FE Developer 💡

0개의 댓글