사내 프로젝트를 리엑트로 만드는 중에 생긴 이슈와 관련되어 정리한 내용입니다.
현재 프로젝트 상황은 아래와 같다
- 서버 데이터를 생성/수정/삭제 하는 CRUD 중 CUD 기능은 크게 사용 X
- 대부분 Read 기능 요구이며 전달 값 (param) 에 맞게 다른 Read 요청 필요
- 에러 핸들링은 서스팬스와 에러 바운더리 통해서 처리
- tanstack query (react query) 는 v5
- useQuery , useSuspenseQuery 사용 하는 훅 생성 중
이슈 1.
이런 환경 속에서 page 컴포넌트에 최초 마운트 되었을 때 필요에 따라 쿼리를 돌릴지 말지 정해야 할 필요가 있는데 useQuery의 경우 enabled 옵션을 false 하면 되지만 서스펜스를 이용하기 위하여 사용 하는 useSuspenseQuery 의 경우에는 마운트 되버리면 실행 되는 상태입니다.
// 커스텀 훅
const useLogin = (param) => {
const fetchData = (param) => {
//fetch 처리
}
//query 방식
const {data1} = useQuery({
queryKey: ['login', param],
queryFn: () => fetchData(param),
enabled: false
});
//suspense 방식
const {data2} = useSuspenseQuery({
queryKey: ['login', param],
queryFn: () => fetchData(param),
})
return {data1, data2}
};
// 실제 페이지
const Page = () => {
const [test, setTest] = useState({});
const {data} = useLogin(test);
const handleClick = (e) => {
// 이래저래 이벤트 처리 후 obj 객체 생성하여
setTest(obj);
}
return (
<>
<button onClick={handleClick}>클릭</button>
로그인 여부 :{data.isLogin}
</>
)
}
이슈 2
위 작업 중에 fetch 에러가 발생하여 throw Error 를 할 경우 에러바운더리로 던져지는 작업 하고 싶은데 실제로 에러 바운더리로 던져지긴 하지만 에러 로그가 2번 이상 발생 되는 상황이 발생 됩니다.
const fetchData = (param) => {
return await axios.get('/',param)
.then((res) => { return res})
.catch((err) => { throw err});
}
//query 방식
const {data1} = useQuery({
queryKey: ['login', param],
queryFn: () => fetchData(param),
enabled: false
});
//suspense 방식
const {data2} = useSuspenseQuery({
queryKey: ['login', param],
queryFn: () => fetchData(param),
})
이런식으로 코드를 작성하면 query 에서는 queryFn 에서 return 되는 data 값이 없다고 에러 1번 발생 되고 fetchData 에서 발생 된 throw 관련 에러도 발생 되면서 필요 없는 에러가 여러번 발생 되고 있습니다 .
이슈에 대한 생각
이곳 저곳 커뮤니티나 다른 개발자 분들에게 질문 외에도 래퍼나 내가 놓친 것이 없는지 다시 되돌아 공부해보면서 나온 결과입니다.
이슈 1.
먼저 이슈 1의 경우에 react의 suspense 목적은 이해하고 있었다고 생각했지만 제대로 이해하지 못한 상태로 사용한 문제로 생긴 이슈입니다.
애초에 suspense는 fetching 하는 동안 특정 UI 화면을 보여주기 위한 목적으로 사용 되어야 하는데 저는 에러 바운더링을 사용하기 위해서는 꼭 사용해야하는 기능이라고 생각하여 사용하였고, 그로 인하여 react-query 내장 함수 중 useSuspenseQuery 를 사용하게 된 것입니다.
개발 의도에 따르면 최초 마운트 되었을 때 실행 처리를 다르게 해야 하는데 무조건 실행 되어야하는 suspense 기능 때문에 훅이 자동으로 돌게 되는 것...
그렇기 때문에 개발 의도에 맞게 사용하려면 useSuspenseQuery가 아닌 useQuery 를 사용해야 하고, 옵션 (enabled : false 또는 useRef로 마운트 못하게 하기...) 등을 통해서 분기를 생성 해야 한다는게 결론입니다.
이슈 2.
사실 에러 관련 된 내용은 서스팬스 작업 때 발생 되는 오류들 중 하나라서 크게 이슈 될 문제는 아니라고 하는 피드백이 대부분이였지만... 해결책을 찾지는 못했다 ... (이럴꺼면 애초에 이슈라고 남기지도 말껄 ㅠ ..)
추가적으로 리엑트 쿼리나 리엑트에 대해서 위 이슈 같은 내용들이 나올 때마다 기록을 남겨두는 습관을 만들 계획이다