본문 바로가기
React

React에서 서버와의 비동기 통신 최적화하기

by 굿센스굿 2024. 12. 16.
반응형

 

React 애플리케이션에서 서버와의 비동기 통신은 데이터를 가져오고 전송하는 데 필수적인 역할을 합니다. 하지만 잘못된 통신 구현은 성능 저하, 불필요한 네트워크 요청, 복잡한 코드 구조를 초래할 수 있습니다. 이번 글에서는 React에서 서버와의 비동기 통신을 최적화하는 방법과 유용한 모범 사례를 소개합니다.


1. React에서 비동기 통신의 역할

React 애플리케이션은 클라이언트 측에서 서버와 상호작용하기 위해 비동기 통신을 사용합니다. 이는 다음과 같은 작업을 포함합니다:

  • 데이터 가져오기 (GET): 서버에서 필요한 데이터를 요청
  • 데이터 전송 (POST, PUT, DELETE): 사용자 입력 또는 상태를 서버로 전송
  • 실시간 업데이트: WebSocket 또는 Server-Sent Events(SSE)를 사용해 변경 사항 수신

비동기 통신을 최적화하면 성능을 향상시키고 사용자 경험을 개선할 수 있습니다.


2. 비동기 통신 최적화의 필요성

React에서 비동기 통신을 최적화해야 하는 이유는 다음과 같습니다:

  • 네트워크 비용 절감: 불필요한 요청을 제거해 리소스를 절약
  • 사용자 경험 향상: 데이터를 빠르게 로드하여 더 매끄러운 UI 제공
  • 코드 관리 용이: 명확한 구조로 유지보수성을 높임

3. React 비동기 통신 최적화 전략

3.1. 데이터 페칭 라이브러리 활용

React에서 비동기 통신을 직접 구현할 수도 있지만, Axios, React Query, SWR 같은 라이브러리를 사용하면 더 효율적으로 데이터를 관리할 수 있습니다. 이러한 라이브러리는 캐싱, 중복 요청 방지, 자동 재요청 등 유용한 기능을 제공합니다.

React Query 예시:

import { useQuery } from 'react-query';

const fetchTodos = async () => {
  const response = await fetch('/api/todos');
  return response.json();
};

const TodoList = () => {
  const { data, error, isLoading } = useQuery('todos', fetchTodos);

  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>Error loading data</p>;

  return (
    <ul>
      {data.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
};

3.2. 요청 병합과 최소화

여러 개의 API 요청이 필요한 경우 이를 병합하여 네트워크 요청 횟수를 줄일 수 있습니다. 예를 들어, 서버에서 여러 리소스를 동시에 가져오는 방법은 다음과 같습니다:

const fetchData = async () => {
  const [users, posts] = await Promise.all([
    fetch('/api/users').then((res) => res.json()),
    fetch('/api/posts').then((res) => res.json()),
  ]);
  return { users, posts };
};

3.3. 캐싱 및 데이터 갱신 관리

데이터를 자주 변경하지 않는 경우, 이전 데이터를 캐싱하면 불필요한 요청을 방지할 수 있습니다. React Query와 SWR은 기본적으로 캐싱 기능을 제공합니다.

SWR 예시:

import useSWR from 'swr';

const fetcher = (url) => fetch(url).then((res) => res.json());

const Profile = () => {
  const { data, error } = useSWR('/api/user', fetcher);

  if (!data) return <p>Loading...</p>;
  if (error) return <p>Failed to load</p>;

  return <div>Hello, {data.name}!</div>;
};

3.4. 데이터 상태 관리

전역 상태 관리 도구를 사용해 API에서 가져온 데이터를 효율적으로 관리할 수 있습니다. 예를 들어, Redux Toolkit 또는 Zustand를 활용하여 상태를 중앙에서 제어하면 중복 요청을 줄이고 코드 구조를 간소화할 수 있습니다.

Redux Toolkit 예시:

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';

export const fetchPosts = createAsyncThunk('posts/fetchPosts', async () => {
  const response = await fetch('/api/posts');
  return response.json();
});

const postsSlice = createSlice({
  name: 'posts',
  initialState: { data: [], status: 'idle' },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchPosts.pending, (state) => {
        state.status = 'loading';
      })
      .addCase(fetchPosts.fulfilled, (state, action) => {
        state.status = 'succeeded';
        state.data = action.payload;
      });
  },
});

export default postsSlice.reducer;

4. 실시간 데이터 업데이트

실시간 데이터를 필요로 하는 경우 WebSocket, GraphQL Subscriptions, SSE와 같은 기술을 사용할 수 있습니다. WebSocket을 사용한 간단한 실시간 구현 예시는 다음과 같습니다:

import { useEffect, useState } from 'react';

const useWebSocket = (url) => {
  const [data, setData] = useState(null);

  useEffect(() => {
    const socket = new WebSocket(url);
    socket.onmessage = (event) => setData(JSON.parse(event.data));
    return () => socket.close();
  }, [url]);

  return data;
};

const RealTimeUpdates = () => {
  const data = useWebSocket('ws://example.com/updates');

  return <div>{data ? `Update: ${data.message}` : 'Waiting for updates...'}</div>;
};

5. 에러 처리 및 재시도 로직

API 호출 중 에러가 발생했을 때 이를 처리하고, 필요한 경우 자동으로 재시도하는 로직을 구현하는 것이 중요합니다. React Query와 Axios는 에러 처리 및 재시도 기능을 기본적으로 제공합니다.

Axios 예시:

import axios from 'axios';

const fetchData = async () => {
  try {
    const response = await axios.get('/api/data');
    return response.data;
  } catch (error) {
    if (error.response) {
      console.error('Server Error:', error.response.status);
    } else {
      console.error('Network Error:', error.message);
    }
    throw error;
  }
};

6. 결론

React에서 서버와의 비동기 통신을 최적화하면 성능을 높이고 사용자 경험을 향상시킬 수 있습니다. 데이터 페칭 라이브러리, 캐싱, 요청 병합, 실시간 업데이트 등을 적절히 활용하여 효율적인 통신 구조를 설계해 보세요. 최적화된 통신 전략은 React 애플리케이션의 성공적인 개발과 운영에 큰 기여를 할 것입니다.

반응형