개발 ‐ api 추가 방법 - ConSeat/frontend GitHub Wiki
🤔 컨벤션을 지켜야 하는 이유
- SSR에서는 Tanstack Query의 useQuery 훅을 사용할 수 없습니다. 대신 prefetch도 제공하고 있어서 먼저 여기서 api를 호출하고 Hydration하여 CSR에서 추가 api 요청없이 사용할 수 있습니다.
- prefetchQuery는
{queryKey, queryFn}
를 받아 실행되기 때문에 이를 모아 관리하고 있습니다. key와 fn이 잘못 매칭되는 휴먼 에러를 방지하기 위함입니다.
🎯 api 추가 방법
1. endpoints 파일에 endpoint를 추가합니다.
2. queryKeys는 factory 형식으로 만들어두었습니다.
이를 참고하여 각 파일(member, review, stadium)에 .api와 .query를 추가하면 됩니다.
3. __.api.ts
에는 api 반환, 요청 type과 요청 함수를 작성합니다.
api.public
은 access token이 필요 없는 요청, api.secure
는 access token이 필요한 요청입니다. 스웨거의 좌물쇠 여부를 확인하고 작성합니다.
export interface StadiumListResponse {
totalReviewCount: number;
active: StadiumInfo[];
inactive: StadiumInfo[];
}
export const getStadiumList = async () => {
const { data } = await api.public.get<StadiumListResponse>({ // 콘서트장 리스트는 api.public
endpoint: API_ENDPOINTS.STADIUMS,
errorMessage: MESSAGES.ERROR.GET_STADIUMS,
});
return { data: data.body };
};
4. ___.query.ts
는 react-query를 사용하기 위한 queryKey와 queryFn을 작성하는 곳입니다.
export const stadiumQueries = {
list: {
queryKey: stadiumKeys.all,
queryFn: getStadiumList,
},
};
5. CSR을 위한 useQuery를 작성합니다.
hooks/queries/useFetch___.ts
로 형식입니다. get 요청 외에는 hooks/mutations/useMutate___.ts
로 작성합니다.
export const useFetchStadiumList = () => {
return useQuery(stadiumQueries.list);
};
const useMutateAuth = () => {
const postLoginAndRefreshMutation = useMutation<{ accessToken: string }, Error, void, unknown>({
mutationFn: postLoginAndRefresh,
meta: { silent: true },
});
return { postLoginAndRefreshMutation };
};
6. SSR에서도 stadiumQueries.list
를 활용해 prefetch 합니다.
createPrefetchedQueryClient
함수를 만들어 dehydratedState를 모듈화하였습니다. 사용처에서는 아래와 같이 쓰면 됩니다.
export default async function HomePage() {
const { dehydratedState } = await createPrefetchedQueryClient([stadiumQueries.list]);
return (
<HydrationBoundary state={dehydratedState}>
<HomeClient />
</HydrationBoundary>
);
}
🌈 QueryProvider 설명
function makeQueryClient() {
return new QueryClient({
defaultOptions: {
queries: {
retry: false, // 한 번 실패했다면 바로 errorboundary로 보내 사용자가 다시 시도 하게함(기본: 3번)
throwOnError: true,
staleTime: 60 * 1000, // SSR에서 불러온 정보를 CSR에서 하이드레이션하여 바로 사용하기 위함
networkMode: 'online', // 오프라인일 때 로딩 -> 네트워크 연결되면 바로 완성된 화면 보임
},
mutations: {
networkMode: 'always', // 오프라인일 때 mutation 동작 error로 간주 & 막음
},
},
queryCache: new QueryCache({
onError: (error) => {
alert(error.message); // error 처리
},
}),
mutationCache: new MutationCache({
onError: (error) => {
alert(error.message); // error 처리
},
}),
});
}
let browserQueryClient: QueryClient | undefined = undefined;
function getQueryClient() {
if (isServer) {
return makeQueryClient();
} else {
if (!browserQueryClient) browserQueryClient = makeQueryClient()
return browserQueryClient; // CSR일 때 매번 makeQueryClient 하는 것 막음
}
}