비동기 처리는 현대 웹 애플리케이션 개발에서 필수적인 요소입니다. 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. 비동기 처리 시 주의사항
- 에러 처리: 비동기 코드는 언제나 실패 가능성을 염두에 두어야 하며, 에러를 적절히 처리해야 합니다.
- 성능 최적화: 불필요한 API 호출이나 상태 변경을 방지해 성능을 개선해야 합니다.
- 사용자 경험: 로딩 상태, 에러 메시지 등을 UI에 명확히 표현하여 사용자 경험을 향상시킵니다.
6. 결론
React에서 비동기 코드는 데이터 패칭과 같은 핵심 기능을 처리하는 데 중요한 역할을 합니다. useEffect부터 상태 관리 및 데이터 패칭 라이브러리까지 다양한 도구를 적절히 활용하면 효율적이고 유지보수 가능한 코드를 작성할 수 있습니다.
이제 React 프로젝트에서 비동기 코드를 자신 있게 다뤄보세요! 🎉
'React' 카테고리의 다른 글
React에서 setState 비동기 처리 이해하기 (0) | 2024.12.12 |
---|---|
React에서 debounce와 throttle 사용법 (0) | 2024.12.12 |
React에서 key 속성의 중요성 (0) | 2024.12.12 |
React에서 useMemo 훅 사용법 (0) | 2024.12.12 |
React에서 useCallback 훅 사용법 (0) | 2024.12.12 |