본문 바로가기
React

React에서 비동기 코드 처리하기

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

 

비동기 처리는 현대 웹 애플리케이션 개발에서 필수적인 요소입니다. React에서도 데이터를 가져오거나 사용자 상호작용에 실시간으로 응답해야 하는 경우 비동기 코드가 중요하게 사용됩니다. 이번 글에서는 React에서 비동기 코드를 처리하는 방법과 이를 효율적으로 관리하는 다양한 패턴 및 모범 사례를 다룹니다.


1. 비동기 코드란 무엇인가?

비동기 코드란 실행 중에 즉시 완료되지 않고 일정 시간이 지난 후 완료되는 작업을 처리하는 코드입니다. 네트워크 요청, 타이머, 파일 읽기 등의 작업이 여기에 해당합니다. JavaScript에서는 이를 Promise, async/await, 그리고 callback을 통해 처리할 수 있습니다. React 환경에서는 데이터 패칭(Data Fetching)이나 이벤트 기반 상호작용에서 비동기 코드를 많이 사용합니다.


2. React에서 비동기 코드 사용하기

React는 상태(state)를 기반으로 UI를 업데이트하기 때문에 비동기 코드를 통해 데이터를 가져온 후 상태를 업데이트하여 UI를 변경합니다.

2-1. 기본 예제: useEffect와 비동기 코드

useEffect 훅은 React 컴포넌트가 렌더링된 후 부수효과(side effect)를 처리하기 위한 도구로, 비동기 코드를 실행하는 데 자주 사용됩니다.

import React, { useState, useEffect } from 'react';

function FetchDataExample() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function fetchData() {
      try {
        const response = await fetch('https://api.example.com/data');
        const result = await response.json();
        setData(result);
      } catch (error) {
        console.error('Error fetching data:', error);
      } finally {
        setLoading(false);
      }
    }

    fetchData();
  }, []);

  if (loading) return

Loading...

;
  if (!data) return

No data available

;

  return (

Data:

{JSON.stringify(data, null, 2)}
); } export default FetchDataExample;

위 예제에서는 useEffect 내부에서 비동기 함수 fetchData를 호출하여 데이터를 가져온 후 상태를 업데이트합니다. loading 상태를 추가로 관리해 사용자 경험을 개선했습니다.


2-2. useEffect의 비동기 처리 주의점

useEffect 자체는 동기 함수로 설계되었기 때문에, 비동기 코드를 직접 useEffect에 전달하는 것은 권장되지 않습니다. 비동기 작업은 함수 내부에 정의된 별도의 비동기 함수에서 처리해야 합니다.

useEffect(() => {
  async function fetchData() {
    // 비동기 작업 수행
  }
  fetchData();
}, []);

3. 상태 관리 라이브러리와 비동기 처리

React 애플리케이션이 커질수록 상태 관리가 복잡해지는데, 이 과정에서 Redux, Recoil, Zustand 같은 상태 관리 라이브러리를 사용할 수 있습니다.

3-1. Redux Toolkit과 비동기 처리

Redux Toolkit은 createAsyncThunk를 통해 비동기 작업을 쉽게 처리할 수 있는 방법을 제공합니다.

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

export const fetchData = createAsyncThunk('data/fetchData', async () => {
  const response = await fetch('https://api.example.com/data');
  return response.json();
});

const dataSlice = createSlice({
  name: 'data',
  initialState: { data: null, loading: false, error: null },
  extraReducers: (builder) => {
    builder
      .addCase(fetchData.pending, (state) => {
        state.loading = true;
      })
      .addCase(fetchData.fulfilled, (state, action) => {
        state.loading = false;
        state.data = action.payload;
      })
      .addCase(fetchData.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message;
      });
  },
});

export default dataSlice.reducer;

4. 데이터 패칭 라이브러리 활용

React Query, SWR과 같은 데이터 패칭 라이브러리는 비동기 작업을 효율적으로 처리하고 캐싱 및 리패칭 같은 고급 기능을 제공합니다.

4-1. React Query 사용 예제

import { useQuery } from '@tanstack/react-query';

function FetchDataWithReactQuery() {
  const { data, error, isLoading } = useQuery(['fetchData'], async () => {
    const response = await fetch('https://api.example.com/data');
    return response.json();
  });

  if (isLoading) return

Loading...

;
  if (error) return

Error: {error.message}

;

  return (

Data:

{JSON.stringify(data, null, 2)}
); } export default FetchDataWithReactQuery;

React Query는 비동기 로직을 더 간단하고 직관적으로 관리할 수 있는 도구를 제공합니다.


5. 비동기 처리 시 주의사항

  1. 에러 처리: 비동기 코드는 언제나 실패 가능성을 염두에 두어야 하며, 에러를 적절히 처리해야 합니다.
  2. 성능 최적화: 불필요한 API 호출이나 상태 변경을 방지해 성능을 개선해야 합니다.
  3. 사용자 경험: 로딩 상태, 에러 메시지 등을 UI에 명확히 표현하여 사용자 경험을 향상시킵니다.

6. 결론

React에서 비동기 코드는 데이터 패칭과 같은 핵심 기능을 처리하는 데 중요한 역할을 합니다. useEffect부터 상태 관리 및 데이터 패칭 라이브러리까지 다양한 도구를 적절히 활용하면 효율적이고 유지보수 가능한 코드를 작성할 수 있습니다.

이제 React 프로젝트에서 비동기 코드를 자신 있게 다뤄보세요! 🎉

반응형