프로그래머스 데브코스

[Tanstack Query / 트러블 슈팅] useSuspenseQuery로 데이터 로딩 상태 처리하기

hellosonic 2024. 3. 22. 22:10

🚀 들어가며

프로필 수정 페이지를 개발하던 중 예상하지 못하던 문제가 발생했다. useQuery 훅을 통해 get 요청으로 받아온 데이터가 일시적으로 undefined였고, undefined의 프로퍼티에 접근하려니 당연히 에러가 발생했다. useQuery의 isLoading 변수를 활용해서 데이터가 불러오기 전까지 로딩 상태를 표시해주려 했지만, 이 방법으로는 해결되지 않았다. 팀원과 문제를 해결하던 중, useQuery 대신 useSuspenseQuery 훅을 사용했고 문제를 해결할 수 있었다. useQuery와 useSuspenseQuery의 차이점에 대해 알아보자

이전에  

 

 

✅ 문제해결

▪︎ 문제의 시작

처음에는 아래와 같이 useQuery 훅을 활용하여 데이터를 받아오는 코드를 작성했다. 

useUserInfo.ts

 

하지만 useQuery 훅을 통해 받아온 데이터가 undefined 일 수 있고, undefined를 객체처럼 프로퍼티에 접근하려고 하니 당연히 타입스크립트 에러가 발생한다는 문구가 나왔다. 처음엔 useQuery 훅의 isLoding 변수를 활용해서 useQuery 훅으로 받아온 데이터가 undefined일 경우(즉, 로딩 상태일 경우) null을 리턴해줌으로써 문제를 해결하려고 했다. 하지만 의도와는 다르게 해결하지 못했다.

ProfileEditPage.tsx

 

결국, 타입스크립트의 에러만 단편적으로 해결하는 방법으로 타입 단언을 사용했다. 받아온 데이터가 undefined나 null 값을 가지지 않는 객체 형태라고 단언해줌으로써 임시적으로 빨간 줄을 제거할 수 있었다.

ProfileEditPage.tsx

 

하지만 테스트 과정에서 같은 문제가 발생했다. 비록 타입 단언으로 에디터 상의 빨간 줄은 제거할 수 있었지만 useQuery로 받아온 데이터가 여전히 undefined일 수 있다는 문제였다.

 

 

▪︎ 문제의 해결

Tanstack Query의 useQuery 훅 대신 useSuspenseQuery 훅으로 문제를 해결할 수 있었다.

useUserInfo.ts

 

 

▪︎ useQuery 와 useSuspenseQuery

그렇다면 useQuery와 useSuspenseQuery는 무엇이 다를까?

리액트에는 아직 렌더링이 준비되지 않은 컴포넌트가 있을 때 로딩 화면을 보여주고 로딩이 완료되면 해당 컴포넌트를 렌더링하는 기능이 존재한다. 바로 React.Suspense 라는 기능이다.

 

React 최상위 API – React

A JavaScript library for building user interfaces

ko.legacy.reactjs.org

 

useSuspenseQuery 훅은 useQuery 훅과는 다르게 리액트의 Suspense 기능과 연동하여, 데이터 로딩 중에는 대체 UI를 보여줄 수 있고, 데이터가 준비되고 나서야 해당 컴포넌트를 렌더링한다. 즉, useSuspenseQuery 훅을 활용함으로써 아직 데이터를 받아오기 전까지 렌더링되는 것을 막고, 데이터가 성공적으로 받아온 이후 렌더링함으로써 문제를 해결할 수 있었던 것이다.

 

 

 

🛸 마치며

프로젝트 기획 단계에 멘토님과 커피챗 시간에 Tanstack Query와 관련한 이야기가 나왔었다. 당시 우리팀은 이번 프로젝트에 사용할 기술스택들을 논의하는 단계였고, 멘토님은 우리에게 로딩 처리를 위해 useSuspense를 사용하는 것을 추천한다고 말씀해주셨다.

이전 팀 프로젝트에서는 useQuery 훅과 isLoding 변수로 로딩처리를 했었다. 그렇기 때문에 useSuspense 개념이 생소하게 느껴졌었는데, 직접 문제를 마주하고 해결하는 과정에서 '멘토님과 그 때 나누었던 이야기가 이런 것 때문이었구나' 라는 것을 깨달았고, 풍부한 경험을 하는 것이 개발자에게 매우 중요하다는 것을 다시 한 번 느꼈다. 아, 그리고 타입 단언은 절대 함부로 하면 안된다는 것을 다시 한 번 깨달았다.