목표
- recoil default로 설정한 API가 호출되는 시점에 대해 이해하기
- next 최적화로 pre-fetch 되는 시점 이해하기
내용
- 발생한 문제
- recoil Atom에 default로 설정한 API가 사용하지 않는 페이지에서도 호출되는 이슈가 발생
- 예상한 원인
- recoil 은 전역상태관리를 하니까 모든 페이지에서 해당 데이터의 사용 여부와 관계 없이 설정해둔 API가 호출될 거라 예상
❌ 그러나 로컬 서버에서 테스트 시 동일한 에러가 발생하지 않음.
💡이유는 모든 페이지에서 상태 관리를 위해 API를 호출한 것이 아니라, NextJS 에서 최적화를 위해 링크<Link/>에 대한 prefetching 을 진행하면서 DB 페이지 링크 노출 시 API 호출이 발생하는 것이었음.
pre fetch로 Recoil API가 호출된 이유
해당 API만 호출되었던 이유는 default 에 API 설정 시 함수를 한번 감싸지 않고 바로 호출하는 형태로 작성하여서 pre-fetch 시 해당 부분을 스크립트가 읽자마자 호출된 것으로 추정
→ 바로 호출했던 이유는 react query의 fetchQuery를 사용하고 있어서 반환타입이 Promise가 되지 않도록 하기 위함 이었음.
const displayFilterNameGroup = atom({
key: RECOIL_KEYS.displayFilterTypeName,
default: fetchDisplayFilterTypeName(),
});
- 해결 방법
1. API 함수를 한번 감싸서 바로 호출되지 않도록 설정
const displayFilterTypeNameAtom = atom({
key: RECOIL_KEYS.displayFilterTypeName,
default: async () => {
const data = await fetchDisplayFilterTypeNameAtom();
return data;
},
});
→ atom을 사용하여 api를 호출하는 경우 react query의 fetchQuery를 사용하고 있어 Promise 타입을 반환하게 되어 한번 가공하거나 react query를 사용하지 않고 바로 API 함수를 호출하는 방법으로 변경 필요.
2. selector get을 사용
const displayDealTypeNameSelector = selector({
key: RECOIL_KEYS.displayDealTypeName,
get: async () => {
// NOTE: pre-fetch 시 api 호출되는 것을 막기 위해 서버사이드에서는 null을 return 합니다.
if (typeof window === "undefined") {
return null;
}
return fetchDisplayDealTypeName();
},
});
→ prefetching은 서버사이드에서 일어나는 과정이므로 window가 존재할 때, 즉 클라이언트 사이드인 경우에만 api 호출이 일어날 수 있도록 조건 추가
3. 콜백함수로 설정
const displayTypeTypeNameSelector = selector({
key: RECOIL_KEYS.displayTypeTypeName,
get: () => fetchDisplayTypeTypeName(),
});
- 원인에 대한 예상이 빗나갔던 이유
- recoil이 호출되는 시점에 대한 이해 부족
- recoil default의 반환 타입이 Promise가 되는 것을 막기 위해 함수를 바로 호출한 것에 대한 문제점을 인지하지 못함.
→ recoil의 경우 db 페이지를 제외한 페이지에서는 해당 selector 상태를 구독하지 않은 상태이기 때문에 호출되지 않는 것이 자연스러운 것임을 생각하지 못하고 있었음.
- 놓쳤던 부분에 대해 보완할 수 있는 방법
- recoil 기본 주요 개념 공식 문서 읽어보기 | https://recoiljs.org/ko/docs/introduction/core-concepts
- 배포 후 개발서버에서 테스트 진행해보거나, 배포 전 빌드 후 프로덕션 환경에서 테스트 해보기
- next prefetching 관련 문서 읽어보기 | https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#link-component
참고자료
https://recoiljs.org/ko/docs/introduction/core-concepts
https://recoiljs.org/docs/guides/asynchronous-data-queries/
https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#link-component
'일상 > Today I Learned' 카테고리의 다른 글
2023.08.17 [suspanse, useTransition] (0) | 2023.08.17 |
---|---|
2023.08.03[Softeer 장애물 인식 프로그램/백준 2667번 단지 번호 붙이기] (0) | 2023.08.03 |
2023.07.13[window.history.scrollRestoration] (0) | 2023.07.13 |
2023.06.26[nextjs - setState 경고] (0) | 2023.06.28 |
2023.06.16[nextjs - query ] (0) | 2023.06.17 |