Coworkers - 팀 페이지 구현(react-query 활용)

오병훈·2025년 3월 3일
0
post-thumbnail

1. react-query를 이용한 데이터 패치

1️⃣ 서버 상태 관리를 효율적으로 하기 위해 (useQuery 활용)

✅ 기존 방식 (useState + useEffect)

❌ 문제점

  • 불필요한 API 요청 발생
  • 컴포넌트가 마운트될 때마다 무조건 API 요청을 실행하여 같은 데이터를 여러 번 요청할 가능성이 있습니다.
  • 데이터 최신화가 어렵습니다.
  • 다른 컴포넌트에서 데이터가 변경되었을 때, 이를 자동으로 반영하기 어렵습니다.
  • 로딩 및 에러 처리가 번거롭습니다.

✅ 적용된 부분

const { data: groupData, isLoading, error } = useQuery({
  queryKey: ['group', groupId],
  queryFn: () =>
    groupId
      ? getGroup({ id: groupId })
      : Promise.reject(new Error('No ID provided')),
  enabled: !!groupId,
  staleTime: 0,
  refetchOnMount: 'always',
});

✅ 개선된 점

1. API 요청 자동 최적화 및 캐싱

  • 동일한 queryKey를 사용하므로 같은 데이터를 여러 곳에서 요청해도 한 번만 API 요청을 실행합니다.
  • 예전 방식(useEffect + fetch)은 컴포넌트가 마운트될 때마다 API 요청을 실행하여 불필요한 네트워크 요청이 발생했지만, useQuery는 이를 방지합니다.

2. 자동 데이터 최신화

  • useQueryinvalidateQueries(['group', groupId])을 통해 데이터 변경 시 자동으로 최신 상태로 갱신됩니다.

3. 로딩 및 에러 상태 관리 내장

  • isLoading, error 상태가 내장되어 있어, 별도로 useState를 추가하지 않아도 됩니다.
  • if (isLoading) return <Loading />;을 통해 간단하게 처리할 수 있습니다.

✅ 적용 예시

export default function HeaderTeam({ type, onClick }: HeaderTeamProps) {
  const {
    data: userData,
    isLoading,
    error,
  } = useQuery<GetUserResponse>({
    queryKey: ['user'],
    queryFn: getUser,
    staleTime: 5 * 60 * 1000,
  });

  if (isLoading) {
    return <div className="hidden tablet:block">로딩 중...</div>;
  }

  if (error) {
    return <div>유저 데이터를 불러오는데 실패했습니다.</div>;
  }
  
}

✅ 결과:

→ 불필요한 API 호출을 줄이고, 데이터가 변경될 때마다 자동으로 UI가 최신화됩니다.
→ 로딩/에러 상태를 자동으로 관리할 수 있어 코드가 더 간결해집니다.

2️⃣ 불필요한 API 요청 방지 및 데이터 최신화 (useQueryClient 활용)

✅ 기존 방식 (각 컴포넌트에서 개별 API 요청)

❌ 문제점

  • 같은 데이터를 여러 번 불필요하게 요청함
    tasks 데이터가 여러 개의 컴포넌트에서 필요하면 각각의 컴포넌트가 API를 중복 호출하게 됩니다.
    네트워크 트래픽이 증가하여 성능이 저하될 수 있습니다.
    데이터가 변경되었을 때 즉각적인 UI 업데이트가 어렵다
    예를 들어, 할 일 목록에 새로운 할 일을 추가해도 기존 데이터를 다시 불러오지 않으면 변경된 내용이 반영되지 않습니다.
    각각의 API 요청을 따로 관리해야 하므로 코드가 복잡해짐

🚀 React Query 활용 (useQueryClient + invalidateQueries)

✅ 적용된 부분

const queryClient = useQueryClient();

const createMutation = useMutation({
  mutationFn: (newTaskList: { name: string }) => {
    const trimmedName = newTaskList.name.trim();
    return createTaskList({ groupId, name: trimmedName });
  },
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ['taskLists', groupId] });
    queryClient.invalidateQueries({ queryKey: ['group', groupId] });
    methods.reset();
    closeModal();
  },
});

✅ 개선된 점

1. 불필요한 네트워크 요청 방지

  • 예전 방식에서는 할 일 목록을 추가할 때, 기존 데이터를 다시 가져오기 위해 전체 페이지를 새로고침해야 했습니다.
  • invalidateQueries(['taskLists', groupId])을 사용하면 새로운 데이터를 다시 불러와도 기존 캐싱된 데이터와 병합하여 최소한의 업데이트만 실행합니다.

2. 데이터 동기화 문제 해결

  • invalidateQueries를 사용하면 변경된 데이터를 즉시 서버에서 가져와 동기화하기 때문에 UI가 항상 최신 상태로 유지됩니다.

✅ 결과:

→ 같은 데이터를 여러 곳에서 공유하여 중복 API 요청을 방지할 수 있습니다.
→ 변경된 데이터를 자동으로 최신화하여 페이지를 새로고침하지 않아도 반영됩니다.
→ 네트워크 부하를 줄이고, 사용자 경험(UX)을 개선할 수 있습니다.

profile
Front-End Developer

0개의 댓글