React Query를 사용할 때, 한 페이지에서 여러 mutate를 사용하다 보면 코드가 복잡해지고 가독성이 떨어질 수 있습니다.
저 역시 page.tsx에서 useMutation을 직접 사용하던 초기 방식에서, 이를 hooks 폴더로 분리하여 관리 효율성을 높였습니다.
이번 글에서는 제가 겪었던 문제와 이를 해결하기 위한 과정을 소개합니다.
■ 기존 폴더 구조
처음에는 src/api 폴더에서 API 호출 로직만 분리하고, page.tsx에서 직접 useMutation을 사용했습니다.
src/
├── api/
│ ├── map.ts # 경로 관련 API
│ ├── user.ts # 사용자 관련 API
│ ├── index.ts # API 묶음 관리
├── app/
│ ├── page.tsx # 페이지 컴포넌트
초기 코드 (page.tsx)
import { useMutation } from '@tanstack/react-query';
import { route, shareRoute } from '@/api/map';
export default function Page() {
const { mutate: mutateFindRoute } = useMutation<String, Error, RouteData>({
mutateFn: route
onSuccess: (data) => console.log('경로 찾기 성공:', data),
onError: (error) => console.error('경로 찾기 실패:', error.message),
});
const { mutate: mutateShareRoute } = useMutation<String, Error, ShareData>({
mutateFn: shareRoute,
onSuccess: (data) => console.log('경로 공유 성공:', data),
onError: (error) => console.error('경로 공유 실패:', error.message),
});
const handleFindRoute = () => {
mutateFindRoute({ origin: '서울', destination: '부산' });
};
const handleShareRoute = () => {
mutateShareRoute({ routeId: 123 });
};
return (
<div>
<button onClick={handleFindRoute}>경로 찾기</button>
<button onClick={handleShareRoute}>경로 공유하기</button>
</div>
);
}
문제점
- 코드 길이 증가:
- 페이지 컴포넌트 내부에 API 호출과 useMutation 옵션들이 반복적으로 작성되며 코드가 길어짐.
- 가독성 저하:
- UI 렌더링, 이벤트 처리, API 호출 로직이 한 파일에 섞여 있어 코드의 목적이 명확하지 않음.
■ 개선된 폴더 구조
위 문제를 해결하기 위해 src/hooks 폴더를 추가하여 useMutation 관련 로직을 분리했습니다.
이제 API 호출은 여전히 api 폴더에서 관리하며, React Query 훅은 hooks 폴더에서 처리합니다.
수정된 폴더 구조
src/
├── api/
│ ├── map.ts # 경로 관련 API
│ ├── user.ts # 사용자 관련 API
│ ├── index.ts # API 묶음 관리
├── hooks/
│ ├── useFindRouteMutation.ts # 경로 찾기 훅
│ ├── useShareRouteMutation.ts # 경로 공유 훅
├── app/
│ ├── page.tsx # 페이지 컴포넌트
커스텀 훅으로 분리 (useFindRouteMutation.ts)
import { useMutation } from '@tanstack/react-query';
import { route } from '@/api/map';
const useFindRouteMutation= () => {
return useMutation<String, Error, RouteData> ({
mutateFn: route,
onSuccess: (data) => console.log('경로 찾기성공:', data),
onError: (error) => console.error('경로 찾기 실패:', error.message),
});
};
export default useFindRouteMutation;
커스텀 훅으로 분리 ( useShareRouteMutation .ts)
import { useMutation } from '@tanstack/react-query';
import { route } from '@/api/map';
const useFindRouteMutation= () => {
return useMutation<String, Error, ShareData> ({
mutateFn: share,
onSuccess: (data) => console.log('경로 공유 성공:', data),
onError: (error) => console.error('경로 공유 실패:', error.message),
});
};
export default useFindRouteMutation;
컴포넌트 코드 수정 (page.tsx)
import useFindRouteMutation from '@/hooks/useFindRouteMutation';
import useShareRouteMutation from '@/hooks/useShareRouteMutation';
export default function Page() {
const findRouteMutation = useFindRouteMutation();
const shareRouteMutation = useShareRouteMutation();
const handleFindRoute = () => {
findRouteMutation.mutate({ origin: '서울', destination: '부산' });
};
const handleShareRoute = () => {
shareRouteMutation.mutate({ routeId: 123 });
};
return (
<div>
<button onClick={handleFindRoute}>경로 찾기</button>
<button onClick={handleShareRoute}>경로 공유하기</button>
</div>
);
}
개선된 구조의 장점
1. 유지보수성 향상
- React Query 관련 로직은 hooks 폴더에서 일괄 관리 가능.
2. 가독성 향상
- 컴포넌트는 UI와 이벤트 처리에만 집중.
3. 관심사의 분리
- React Query와 상태 관리: hooks 폴더에서 처리.
- UI와 사용자 이벤트: 컴포넌트에서 집중.
'React' 카테고리의 다른 글
[useMutation] 매개변수 타입 처리: 한 개와 여러 개의 차이점 (0) | 2025.01.17 |
---|---|
[TypeScript] 매개변수 처리 방식 (직접 받기 vs 객체로 받기) (0) | 2025.01.14 |
[SEO] SEO와 Metadata 설정(Next.js) (2) | 2024.10.04 |
[Next.js] 클라이언트와 서버 실행 분리해야하는 이유(feat. Zustand) (0) | 2024.09.11 |
[Next.js] SSR과 SSG의 최적화 전략: 동적 컴포넌트 관리 방법 (1) | 2024.08.28 |