뒤로가기

Tanstack Query를 통한 데이터 생명주기 관리 경험

react

문제 상황

Angular과 Electron을 기반으로 협업 툴을 웹과 앱으로 개발하는 과정에서 상태 관리의 복잡성이 증가했습니다. Redux를 사용하여 상태를 관리하고 있었지만, 화면의 복잡도가 증가함에 따라 데이터의 생성과 제거를 관리하는 것이 어려워졌습니다.

기존 접근 방식의 한계

각 화면에서 데이터를 생성 및 제거하는 접근 방식은 다음과 같은 문제를 야기했습니다:

  • 유지보수의 어려움: 데이터 생명주기 로직이 여러 화면에 분산되어 있어 추적이 어렵습니다.
  • 메모리 관리의 복잡성: 화면이 제거될 때 데이터를 적절히 정리하지 못하면 메모리 누수가 발생합니다.
  • 중복 코드: 유사한 데이터 관리 로직이 여러 컴포넌트에 반복됩니다.

데이터 중심 아키텍처로의 전환

이 문제를 해결하기 위해 데이터 관리를 화면이 아닌 독립적인 계층으로 분리하는 접근법을 검토했습니다. 데이터의 생명주기를 화면이 아닌 자체적인 라이프사이클로 관리하는 것이 핵심입니다.

데이터 계층 분리의 장점

  • 명확한 책임 분리: UI 계층은 표시에만 집중하고, 데이터 계층은 상태 관리에 집중합니다.
  • 자동화된 생명주기 관리: 데이터의 생성, 캐싱, 무효화, 제거가 자동으로 처리됩니다.
  • 재사용성 향상: 데이터 로직을 여러 화면에서 공유할 수 있습니다.

Tanstack Query의 핵심 기능

Tanstack Query는 이러한 데이터 중심 아키텍처를 구현하기 위한 강력한 도구입니다. 주요 기능은 다음과 같습니다:

키 기반 데이터 접근

해시키를 통해 데이터에 직관적으로 접근할 수 있어, 데이터 식별과 관리가 간소화됩니다.

자동 캐싱

캐시를 활용하여 불필요한 API 호출을 줄이고, 네트워크 비용을 최적화할 수 있습니다.

컴포넌트 로직 간소화

데이터 fetching 로직이 컴포넌트에서 분리되어, 컴포넌트는 UI 렌더링에만 집중할 수 있습니다.

실시간 동기화 지원

웹소켓과 결합하여 실시간 데이터 업데이트를 효과적으로 관리할 수 있습니다.

구현 사례: Todo 애플리케이션

Tanstack Query의 활용 방법을 이해하기 위해 Todo 앱을 구현했습니다. (Github repo)

클라이언트 요구사항

  1. 월 단위로 todo 리스트를 관리
  2. 월 단위로 todo 리스트 뷰 제공
  3. 위젯 형태로 여러 월을 동시에 볼 수 있는 뷰 제공

서버 요구사항

  1. 월 단위 todo 리스트에 대한 웹소켓 제공
  2. 단일 todo 수정에 대해서는 웹소켓 제공하지 않음
  3. todo 생성, 수정, 삭제에 대한 REST API 제공

아키텍처 특징

구현한 앱에서는 컴포넌트 계층에서 데이터 관리 로직을 최소화하고, Tanstack Query를 통해 데이터의 생명주기를 관리했습니다.

웹소켓 통합

웹소켓을 통해 실시간으로 데이터를 업데이트하는 부분에서 Tanstack Query를 활용하면 특히 효과적입니다. 데이터 계층에서 생성과 제거 시점에 자동으로 웹소켓의 room에 join하고 leave하는 로직을 구현하여, 화면에서는 이에 대한 로직을 처리할 필요가 없습니다.

// 예시: Query 생명주기와 WebSocket 연동
const useTodoList = (month: string) => {
  return useQuery({
    queryKey: ['todos', month],
    queryFn: () => fetchTodosByMonth(month),
    onSuccess: () => {
      // 데이터 로드 성공 시 웹소켓 room에 join
      socket.emit('join-room', month);
    },
    onSettled: () => {
      // 컴포넌트 unmount 시 leave
      return () => socket.emit('leave-room', month);
    }
  });
};

실무 도입 시 고려사항

Tanstack Query를 통해 얻을 수 있는 장점과 함께, 프로젝트 특성에 맞지 않는 기능들도 존재합니다.

Stale Time 설정의 한계

stale time 설정은 자동으로 API를 호출하게 만드는데, 이는 모든 앱의 특성에 맞지 않을 수 있습니다. 최소한의 API 호출과 웹소켓을 통한 데이터 업데이트를 중점으로 두어야 하는 경우, 이러한 설정은 오히려 불필요한 API 호출을 유발할 수 있습니다.

커스텀 솔루션 개발

프로젝트에 직접 Tanstack Query를 도입하지는 않았지만, 그 개념을 활용하여 데이터의 생명주기를 관리하는 커스텀 라이브러리를 개발하기로 결정했습니다. 이를 통해 프로젝트의 특성에 맞는 최적화된 솔루션을 구현할 수 있었습니다.

핵심 인사이트

데이터 구조 설계

데이터 구조를 설계할 때 확장성과 유지보수성을 고려하는 것이 중요합니다. 화면 중심이 아닌 데이터 중심의 아키텍처는 장기적인 유지보수 비용을 크게 절감합니다.

생명주기 자동화

데이터의 생성, 캐싱, 무효화, 제거를 자동화하면 개발자가 비즈니스 로직에 집중할 수 있습니다.

실시간 동기화 패턴

Tanstack Query와 웹소켓을 결합하면 복잡한 실시간 동기화 로직을 간소화할 수 있습니다.

결론

실제 프로덕션에 직접 도입하지는 않았지만, Tanstack Query를 연구하고 실험하는 과정에서 데이터 중심 아키텍처의 중요성을 이해하게 되었습니다. 이러한 경험은 앱의 성능을 향상시키고 유지보수를 용이하게 만드는 데 큰 도움이 됩니다.

데이터 관리를 화면에서 분리하고, 자동화된 생명주기 관리를 도입하는 것은 현대 프론트엔드 아키텍처의 핵심 패턴입니다. Tanstack Query는 이러한 패턴을 구현하기 위한 훌륭한 참고 사례이며, 프로젝트 특성에 맞게 커스터마이징하여 활용할 수 있습니다.

관련 아티클