React Query 디버깅 노트

Kim jisu·2025년 5월 25일
0

 Debugging Note

목록 보기
25/37

🐛 문제 상황

Next.js 프로젝트에서 @tanstack/react-query v5 사용 시 다양한 타입 에러 발생.

내가 FE개발을 담당 하진 않았지만, 고도화 하고 싶은 부분을 수정하다 생긴 에러 정리.


📋 발생한 에러들

1. useQuery API 변경 에러

// ❌ 에러 코드
export const useGetSubscriptionDetail = (id?: number) =>
  useQuery(
    [GET_subscription_detail.name, id],  // 첫 번째 인수로 queryKey 전달
    {
      enabled: !!id,
      queryFn: () => GET_subscription_detail(id!),
      select: (res) => res.data,
    }
  )

에러 메시지:

이 호출과 일치하는 오버로드가 없습니다. 
'queryKey' 속성이 '(string | number | undefined)[]' 형식에 없지만 
'UseQueryOptions<...>' 형식에서 필수입니다.

2. Select 함수 타입 에러

// ❌ 에러 코드
select: (res) => res.data

에러 메시지:

'(res: ApiResponse<SubscriptionDetailDto>) => { data: SubscriptionDetailDto; status: string; }' 
형식은 '(data: ApiResponse<SubscriptionDetailDto>) => SubscriptionDetailDto' 형식에 할당할 수 없습니다.

3. 데이터 구조 접근 에러

// ❌ 에러 코드
const { data: popularSubId } = useGetPopularSubscription();
const { data: subDetail } = useGetSubscriptionDetail(popularSubId);

에러 메시지:

'{ data: number; status: string; } | undefined' 형식의 인수는 
'number | undefined' 형식의 매개 변수에 할당될 수 없습니다.

4. 타입 불일치 에러

// ❌ 에러 코드
const { data: getInfra } = useGetInfraBySubscription(popularSubId);

에러 메시지:

'number | undefined' 형식의 인수는 'string' 형식의 매개 변수에 할당될 수 없습니다.

🔍 원인 분석

1. React Query v5 API 변경

  • v4: useQuery(queryKey, options) 형태
  • v5: useQuery({ queryKey, ...options }) 형태로 통합

2. 타입 추론 문제

  • 제네릭 타입을 명시적으로 지정했지만 select 함수와 불일치
  • TypeScript가 올바른 타입을 추론하지 못함

3. 데이터 구조 이해 부족

  • API 응답이 { data: T, status: string } 구조
  • .data 속성으로 실제 데이터에 접근해야 함

4. 훅 인터페이스 불일치

  • 일부 훅은 string 타입을 요구하지만 number를 전달

✅ 해결 방법

1. useQuery API 수정

// ✅ 해결된 코드
export const useGetSubscriptionDetail = (id?: number) =>
  useQuery({
    queryKey: [GET_subscription_detail.name, id],  // options 객체 내부로 이동
    enabled: !!id,
    queryFn: () => GET_subscription_detail(id!),
    select: (res: ApiResponse<SubscriptionDetailDto>) => res.data,
  })

2. 데이터 접근 구조 수정

// ✅ 해결된 코드
const { data: popularSubRes } = useGetPopularSubscription();
const popularSubId = popularSubRes?.data;  // .data로 실제 값 추출

const { data: subDetailRes } = useGetSubscriptionDetail(popularSubId);
const subDetail = subDetailRes?.data;  // .data로 실제 객체 추출

3. 타입 변환 처리

// ✅ 해결된 코드
const idString = popularSubId ? String(popularSubId) : '';
const { data: getInfra } = useGetInfraBySubscription(idString);

에러 예방 패턴

  • 옵셔널 체이닝(?.) 적극 활용
  • 기본값 설정으로 undefined 에러 방지
  • 조건부 렌더링으로 데이터 로딩 상태 처리
profile
Dreamer

0개의 댓글