본문 바로가기

🌼 TIL

Next.js에서 ReactQuery를 이용한 데이터 관리 및 CRUD 기능 구현

Next.js으로 작업한 프로젝트에 React-Query를 이용하여 CRUD 기능을 구현하였다.

Firebase를 이용하여 데이터를 관리하였다.

 

먼저 이번 프로젝트에 React-Query를 사용한 이유는 이렇다

  • redux를 사용하면서 미들웨어를 사용하기엔 너무 무거움
  • 서버 상태와 클라이언트 상태를 독립적으로 관리하기 위해
  • 캐싱 기능을 활용하기 용이(사진을 이용한 서비스가 많기에 캐싱기능을 활용하기로 결정)

 

포스터를 게시하는 코드

//* 이미지 업로드
  const [imageUpload, setImageUpload]: any = useState(null);
  const imgPath: string = uuidv4();
  
  let postState: any = {
    title: title,
    content: content,
    imgUrl: '',
    createdAt: Date.now(),
    creator: authService.currentUser?.uid,
    city: city,
    town: town,
    clickCounter: 0,
    lat: saveLatLng.Ma,
    long: saveLatLng.La,
    address: saveAddress,
    nickname: nickname,
    imgPath: imgPath,
  };

  //* useMutation 사용해서 포스트 추가하기
  const { mutate: onAddData, isLoading } = useMutation(addData);

  //* 추가버튼 눌렀을때 실행하는 함수
  const onClickAddData = async () => {
    const imageRef = ref(storageService, `images/${imgPath}`);
    uploadString(imageRef, imageUpload, 'data_url').then((response) => {
      getDownloadURL(response.ref).then((url) => {
        const response = url;
        postState = {
          ...postState,
          imgUrl: response,
        };
        onAddData(postState, {
          onSuccess: () => {
            queryClient.invalidateQueries('infiniteData');
            setIsPostMapModal(false);
            customConfirm('등록을 완료하였습니다!');
          },
        });
      });
    });

    visibleReset();
  };
  
  return (
  <div>
  	   <PostFormBackButton
                onClick={() => {
                  setIsPostMapModal(!postMapModal);
                }}
              >
                {isMobile && <img src="/Back-point.png" />}
              </PostFormBackButton>
              내 스팟 추가하기
            </PostFormContenTitle>
        </PostFormBackButton>
  </div>

addDoc을 이용하여 데이터를 추가하는 함수 

//* 포스트 추가하기
export const addData: any = (data: any) => {
  addDoc(collection(dbService, 'post'), data);
};

수정의 과정도 이와 유사하다.

수정 시 updateDoc을 사용한다.

 

삭제 시 deleteDoc을 사용하여 docId를 삭제한다.

 

데이터를 가져와 Read할 때의 과정은 이러하다

일단 Firebase의 firestore에 추가된 데이터를 가져온다

//* 스토어에서 데이터 불러오기
export const getData = async () => {
  const response: any = [];

  const querySnapshot = await getDocs(collection(dbService, 'post'));
  querySnapshot.forEach((doc) => {
    response.push({ id: doc.id, ...doc.data() });
  });

  return response;
};

이때 useQuery를 사용하여 데이터를 가져온다

사진이 많은 서비스기에 데이터 캐시를 관리하고 성능 최적화를 위해 staleTime과 cacheTime을 사용하였다.

//* useQuery 사용해서 포스트 데이터 불러오기
  const {
    data: detail,
    isLoading,
    isError,
  } = useQuery('detailData', getData, {
    staleTime: 60 * 1000, // 1분, default >> 0
    cacheTime: 60 * 5 * 1000, // 5분, default >> 5분
  });

이후 가져온 데이터를 사용하여 화면에 표시한다.