본문 바로가기

코딩/트러블슈팅

Tanstack Query - prefetchQuery로 공휴일 데이터 패칭 최적화하기

크로스핏 박스 전용 웹사이트 'wodLog'의 Hold(회원권 일시정지) 메뉴를 개발하면서 겪은 문제와 해결 과정을 공유하고자 합니다.

 

Hold(회원권 일시정지 메뉴)는 현재 이용 중인 체육관에서 일시정지 요청 글을 올리면 관리자 확인 후 잔여일을 알려주는 수동적인 시스템과 신청 즉시 잔여일을 확인할 수 없다는 점, 그리고 작성하는 페이지에 달력이 없어서 신청 시 한번 더 확인해야 하는 번거로움을 줄이기 위해 개발하게 되었습니다.

 

회원권 일시정지 시 작성해야하는 내용과 잔여일 확인 방법

 

 

이러한 수동적이고 불편한 프로세스를 개선하기 위해 다음 기능들을 포함한 Hold 메뉴를 기획했습니다.

  1. 공휴일이 표시된 달력 UI
  2. 선택한 기간에 따른 실시간 잔여일 계산
  3. 일요일과 공휴일을 자동으로 제외한 정확한 일수 계산 

 

개발 완료된 Hold 메뉴

 

 

🔍 문제 상황

처음에는 단순히 공휴일 API를 호출하여 달력에 해당 데이터를 표시하는 방식으로 구현했는데, 다음과 같은 문제가 발생했습니다.

 

1. 달력 UI 불안정성

  • Hold 등록 시 공휴일을 제외한 실제 일시정지 일수를 계산하기 위해 공휴일 API를 호출
  • 데이터를 비동기로 불러오는 동안 달력 UI에서 공휴일 표시가 불안정하게 변화
  • 달력 매 월 이동 시마다 공휴일이 깜박이는 현상이 발생하여 사용자 경험 저하

2. 불필요한 API 호출

  • 달력을 이동할 때마다 동일한 공휴일 데이터를 반복적으로 API 호출
  • 이미 받아온 데이터를 캐싱하지 않아 서버 리소스 낭비

 

 

위 GIF와 같이 달력 매 월 이동 시마다 API가 새롭게 호출되고 데이터가 받아지면 공휴일로 인식되어 몇 초 뒤 회색으로 바뀌는, 즉 깜박거리는 현상을 보실 수 있습니다.

 

 

💡 문제 해결 과정

1차 시도: Tanstack Query로 데이터 관리

모든 데이터를 받아온 이후에도 달력 매 월 이동 시 깜박임이 지속되기에 받아온 데이터를 캐싱해야겠다는 생각으로 Tanstack Query를 도입하게 되었습니다.

 

Tanstack Query는 쿼리 키를 기반으로 데이터를 캐싱합니다. 같은 쿼리 키로 요청이 발생하면 서버에 요청하지 않고 캐시 된 데이터를 사용하게 됩니다. 따라서 캐시 된 데이터를 사용하게 되어 중복 요청을 줄일 수 있습니다.

 

개선된 점

  1. 한번 불러온 연도의 공휴일 데이터는 재사용되어 불필요한 API 호출 감소
  2. 캐시 된 데이터를 사용할 때는 깜박임 현상 없이 부드러운 UI 제공 

 

위 GIF는 Tanstack Query를 도입한 결과입니다.

컴포넌트 최초 마운트 시 여전히 깜박임 현상이 발생하지만 그래도 데이터 패칭이 완료된 후에는 캐싱되었기 달력 이동 시에도 깜박임 없는 모습을 확인할 수 있습니다.

 

 

최종 해결: prefetchQuery 적용

이제 컴포넌트 최초 마운트 시 데이터 패칭 문제만 남아있습니다.

다른 개발자 분께 이 문제에 대해 물어보니 '백그라운드에서 미리 데이터를 받아오는 방법이 있다'라는 힌트를 얻게 되었고,

Tanstack Query를 도입한 김에 공식문서에서 관련 기능이 있을지 찾아보게 되었습니다. 그렇게 `prefetchQuery`를 발견하게 되었고 적용하게 되었습니다.

 

아래는 Tanstack Query의 `prefetchQuery` 공식문서 내용입니다. https://tanstack.com/query/latest/docs/reference/QueryClient#queryclientprefetchquery

 

TanStack | High Quality Open-Source Software for Web Developers

Headless, type-safe, powerful utilities for complex workflows like Data Management, Data Visualization, Charts, Tables, and UI Components.

tanstack.com

 

 

`prefetchQuery`를 사용하여 컴포넌트가 마운트 되는 시점에 필요한 해당 연도의 공휴일 데이터를 미리 로드함으로써, 사용자의 달력 조작 이전에 모든 데이터를 준비할 수 있었습니다.

// WriteHold.tsx
const WriteHold = () => {
  const queryClient = useQueryClient();
  const years = [currentYear, currentYear + 1];

  // 컴포넌트 마운트 시 공휴일 데이터를 미리 로드
  useEffect(() => {
    years.forEach((year) => {
      queryClient.prefetchQuery(holdQueryKeys.holidays(year));
    });
  }, [queryClient]);

 

 

위 GIF는 최종 해결된 결과입니다!

 


✏️ 개선 결과

 

1. UI 안정성 향상

  • Hold 등록 페이지 진입 시 달력 깜박임 현상 제거
  • 달력에서 매 월 이동 시에도 부드러운 UX 제공
  • 공휴일 표시가 안정적으로 유지

2. 성능 최적화

  • 불필요한 API 호출 제거
  • 캐싱된 데이터 재사용으로 서버 부하 감소

 

📌 이전 코드와 비교

  • 초기 버전: 매 달력 이동 시 실시간 API 호출로 인한 달력 UI 깜박임
  • 첫 번째 시도: Tanstack Query 적용으로 캐싱되어 초기 로딩 외 깜박임 감소
  • 최종 해결: Tanstack Query `prefetchQuery` 사용으로 모든 상황에서 깜박임이 없는 부드러운 UI 제공

[초기 버전] 매 달력 이동 시 실시간 API 호출로 인한 달력 UI 깜박임
해결하기 위한 과정들