'use client'
import { useQuery } from '@tanstack/react-query'
import { getRuntimeHomeBootstrapQueryOptions } from '@/lib/obo-api/query-options'
import type { RuntimeHomeBootstrapQueryParams } from '@/lib/obo-api/query-options'
export function useRuntimeHomeBootstrapQuery(params: RuntimeHomeBootstrapQueryParams) {
return useQuery(getRuntimeHomeBootstrapQueryOptions(params))
}
위 코드는 Next.js 클라이언트 컴포넌트에서 Tanstack Query(React Query) 의 useQuery 를 커스텀 훅으로 감싼 패턴이고,
서버 상태를 가져오고 캐싱하고 다시 갱신하는 흐름을 깔끔하게 추상화한 예시이다.
useQuery 는 비동기 데이터를 가져올 때 data, isLoading, isError 같은 상태를 함께 관리해주기 때문에, 직접 useState, useEffectr 로 구현하는 것보다 훨씬 편하다.
useQuery 란?
useQuery 는 기본적으로 서버에서 가져오는 데이터 상태를 관리하는 도구이다.
보통 GET 요청에 사용하고, 요청 상태와 결과를 함께 반환한다.
주요 반환값은 아래와 같다.
- data : 성공적으로 받아온 데이터
- isLoading 또는 isPending = 로딩 중인지 여부
- isError : 실패했는지 여부
- error : 실패했는지 여부
- refetch : 수동 재조회 함수
이런 값들을 직접 상태로 만들 필요가 없어서, UI 코드가 단순해진다.
Spring 개발자 관점
// Java
@GetMapping("/main")
public MainResponse getMain() {
return service.getMain();
}
를 호출하는
MainResponse response = restTemplate.getForObject(...);
와 비슷한 역할이다.
React 에서는
const result = useQuery(...)
문제점
로딩 처리
에러 처리
재조회
캐시
중복 호출
전부 직접 구현해야 한다.
그래서 React Query 인 useQuery 를 사용한다.
// TypeScript
const query = useQuery(...)
로딩 처리
에러 처리
재조회
캐시
중복 호출
모두 관리한다.
useQuery 결과
// TypeScript
const query = useQuery(...)
// TypeScript 내부 결과
query.data
query.error
query.isLoading
query.isSuccess
query.isFetching
왜 커스텀 훅으로 감싸나
useQuery 를 커스텀 훅으로 감싼 핵심 장점은 재사용성과 응집도이다. 쿼리 키, API 호출 함수, 캐시 정책을 한 함수에 묶어두면
여러 컴포넌트에서 같은 데이터를 일관되게 쓸 수 있다.
// TypeScript
const { data, isLoading, error } = useRuntimeHomeBootstrapQuery({ userId })
// TypeScript
export function useRuntimeHomeBootstrapQuery(params: RuntimeHomeBootstrapQueryParams) {
return useQuery(getRuntimeHomeBootstrapQueryOptions(params))
}
// RuntimeHomeBootstrapQueryParams
export type RuntimeHomeBootstrapQueryParams = Partial<RuntimeHomeBootstrapRequest>
// RuntimeHomeBootstrapRequest
export type RuntimeHomeBootstrapRequest = {
site: string
menu?: string
dnis?: string
}
이렇게 쓰다보면 "어떻게 가져오는지" 가 아니라 "무슨 데이터를 쓰는지"만 보면 된다.
TanStack Query v5 의 queryOptions 패턴
예전
useQuery({
queryKey:[...],
queryFn:...
})
React Query 5 방식
useQuery({
queryKey:[...],
queryFn:...
})
- queryKey 를 일관되게 관리
- queryFn 에서 실제 API 호출을 한다. 내부에서는 fetch(...) 또는 axios.get(...)
-