본문 바로가기
Frontend/React

데이터 CRUD 처리(api작성)와 hooks React Query 사용

by 디스코비스킷 2024. 12. 16.
반응형

1. 데이터 CRUD는 API에서 작성

데이터의 생성(Create), 읽기(Read), 수정(Update), 삭제(Delete) 작업은 API 파일에서 작성하는 것이 좋다.
API 파일은 서버와 통신하는 로직을 모아둔 곳으로, 컴포넌트에서 API 호출 로직을 분리해 유지보수성과 재사용성을 높인다.

// api/posts.ts
import { db } from '@/lib/firebase';
import { collection, addDoc, getDocs, updateDoc, deleteDoc } from 'firebase/firestore';
// CREATE
export const createPost = async (postData: Post) => {
const docRef = await addDoc(collection(db, 'posts'), postData);
return { id: docRef.id, ...postData };
};
// READ
export const fetchPosts = async () => {
const snapshot = await getDocs(collection(db, 'posts'));
return snapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() }));
};
// UPDATE
export const updatePost = async (id: string, updatedData: Partial<Post>) => {
const postRef = doc(db, 'posts', id);
await updateDoc(postRef, updatedData);
return { id, ...updatedData };
};
// DELETE
export const deletePost = async (id: string) => {
const postRef = doc(db, 'posts', id);
await deleteDoc(postRef);
return id;
};

2. React Query로 API 처리 (Hooks 활용)

React Query의 useQueryuseMutation을 활용하면 데이터를 효율적으로 관리할 수 있다.
API와 관련된 데이터 fetching, 캐싱, 상태 관리 로직을 hooks에 작성해 컴포넌트에서는 간결하게 사용할 수 있다.

// hooks/usePosts.ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { createPost, fetchPosts, updatePost, deletePost } from '@/api/posts';
export const usePosts = () => {
// READ
const { data: posts, isLoading, error } = useQuery(['posts'], fetchPosts);
return { posts, isLoading, error };
};
export const useCreatePost = () => {
const queryClient = useQueryClient();
return useMutation(createPost, {
onSuccess: () => {
queryClient.invalidateQueries(['posts']); // 새로고침
},
});
};
export const useUpdatePost = () => {
const queryClient = useQueryClient();
return useMutation(updatePost, {
onSuccess: () => {
queryClient.invalidateQueries(['posts']);
},
});
};
export const useDeletePost = () => {
const queryClient = useQueryClient();
return useMutation(deletePost, {
onSuccess: () => {
queryClient.invalidateQueries(['posts']);
},
});
};

3. React Query를 사용하는 이유

React Query는 비동기 데이터 로직을 단순화하고, 서버와 클라이언트 상태를 관리하기 위한 도구이다. 이를 활용하면 다음과 같은 이점이 있다.

  1. 캐싱 및 데이터 동기화
    • 동일한 데이터를 반복적으로 요청하지 않고, 캐싱된 데이터를 재사용한다.
    • 데이터 변경 시 자동으로 갱신하거나, 명시적으로 갱신(invalidateQueries)할 수 있다.
  2. 로딩/에러 상태 관리 간소화
    • API 호출 상태(로딩, 에러, 성공)를 기본적으로 관리하며, UI에 쉽게 반영할 수 있다.
  3. 자동화된 데이터 갱신
    • 페이지 이동, 특정 조건 발생 시 데이터를 자동으로 갱신한다.
    • 백그라운드에서 최신 데이터를 가져와 사용자 경험을 향상시킨다.
  4. 간결한 코드
    • 컴포넌트에서 API 호출, 상태 관리, 데이터 캐싱 등을 별도로 처리하지 않아도 된다.
    • 반복적인 비동기 로직 제거로 코드 가독성과 유지보수성이 증가한다.
  5. 서버 상태와 클라이언트 상태 분리
    • React Query는 서버 데이터만 관리하며, 클라이언트 상태 관리는 다른 상태 관리 라이브러리와 병행 가능하다.

React Query가 없는 경우와 비교

React Query 없이 데이터 로직을 작성할 경우:

  1. useState와 useEffect를 통해 데이터를 가져오는 로직 작성.
  2. 로딩 상태와 에러 상태를 별도로 관리.
  3. 데이터 캐싱 및 무효화 로직을 수작업으로 구현.
  4. 여러 컴포넌트에서 동일 데이터를 사용할 경우, 중복 로직 발생.
  5. 데이터 동기화와 리프레시 처리가 번거로움.
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
try {
const response = await fetch('/api/posts');
const result = await response.json();
setData(result);
} catch (err) {
setError(err);
} finally {
setIsLoading(false);
}
};
fetchData();
}, []);

React Query를 사용하면 위와 같은 반복적인 코드가 크게 줄어든다.

4. 컴포넌트에서 React Query 활용

컴포넌트에서는 복잡한 데이터 로직 없이 usePosts, useCreatePost와 같은 hooks를 간단히 호출해 사용할 수 있다.

import { usePosts, useCreatePost } from '@/hooks/usePosts';
const PostList = () => {
const { posts, isLoading, error } = usePosts();
const createPost = useCreatePost();
const handleAddPost = () => {
createPost.mutate({ title: 'New Post', content: 'Hello World!' });
};
if (isLoading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<div>
<button onClick={handleAddPost}>Add Post</button>
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
};

결론

  1. API 파일에서 CRUD 작업을 정의하고, 이를 서버와 통신하는 기본 단위로 사용한다.
  2. Hooks에서는 React Query를 활용해 API 호출과 상태 관리를 담당한다.
  3. 컴포넌트에서는 useQueryuseMutation으로 데이터에 접근하며, 비즈니스 로직은 분리된다.

이 방식으로 코드의 재사용성, 유지보수성, 성능 최적화를 크게 개선하자!

반응형

최근댓글

최근글

© Copyright 2024 ttutta