밝을희 클태

[ Next.JS ]상품 업로드, 수정, 조회 로직 본문

KEYNUT 프로젝트

[ Next.JS ]상품 업로드, 수정, 조회 로직

huipark 2024. 7. 16. 16:53

Next.JS 14 App Router

프론트엔드

SSR

// URN = /shop
// 모든 상품 조회
const res = await fetch(${process.env.NEXT_PUBLIC_BASE_URL}, {
      next: { tags: ['products'] },
});
// URN = /
// 최근 등록된 상품 일부 조회
const res = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/products/recent`, {
      next: { tags: ['products'] },
});
// URN = /product/[id]
// 등록된 상품 조회
const res = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/products/${id}`, {
    next: { tags: [id] },
});

CSR

CSR에서는 next.tags기능을 사용 못해서 따로 재검증 로직을 추가해줘야 한다. 상품 수정이 일어날 경우 queryKeycategories || prices가 들어있으면 다음 요청에 query의 상태와 상관없이 무조건 재검증

CustomHook

queryKey를 체크해 카테고리와, 가격 필터가 들어있으면 다음 요청에 재검증

import { useQueryClient } from '@tanstack/react-query';
import { useCallback } from 'react';

export const useInvalidateFiltersQuery = () => {
  const queryClient = useQueryClient();

  return useCallback(() => {
    queryClient.invalidateQueries({
      predicate: query =>
        query.queryKey.some(key => typeof key === 'string' && (key.includes('categories') || key.includes('prices'))),
    });
  }, [queryClient]);
};

 

상품 업로드, 수정 시

async fun ... {
	res = await fetch();
    
    if (res.ok)
    {
        위의 커스텀훅 실행()
        router.push(URL);
        router.refresh();	// SSR 환경의 데이터 캐시 재검증 요청을 해도 즉시 재검증을 하지
                            //않기 때문에 해당 동작을 한 유저는 refresh()로 서버 데이터를 새로 불러옴
    }
{

삭제된 상품 체크 

webSocket을 사용하지 않으면 다른 사용자가 삭제한 상품을 실시간으로 체크하기가 힘듬(staleTime: 1분) stale시간 이내에 다른 사용자가 삭제된 상품을 클릭하면 조회수 증가하는 로직에서 상품의 data를 체크해서 없으면 query 재검증을 요청해 상품의 삭제 상태를 반영

useEffect(() => {
    const fetchUpdateViews = async () => {
      const data = await incrementViewCount(id);
      if (!data) {
        alert('삭제된 상품입니다.');
        커스텀 훅()
        return router.back();
      }
      queryClient.setQueryData(['product', id], oldData => ({
        ...oldData,
        views: data.views,
      }));
    };
    fetchUpdateViews();
}, []);

회원 탈퇴

alert('회원 탈퇴가 정상적으로 처리되었습니다.');
위의 커스텀훅 실행()
router.refresh();

백엔드

상품 업로드 API

// 상품 업로드시 "/shop"(전체 상품 조회), "/"(최근 등록 상품) 요청의 데이터 캐시를 재검증
export async function POST(req) {
	revalidateTag('products');
}

상품 수정 API

// "/product/[id]"(상품), "/shop", "/" 요청의 데이터 캐시 재검증
// "/" 을 재검증 하는 이유는 최근에 업로드된 상품의 수정일 가능성도 있기 때문
export async function PUT(req) {
    const productId = formData.get('id');
    revalidateTag(productId);
    revalidateTag('products');
}

상품 상태 변경(판매 중, 판매완료) API

export async function PUT(req, { params }) {
    revalidateTag(id);
    revalidateTag('products');
}

회원 탈퇴

export async function DELETE(req, { params }) {
    revalidateTag('products');
}