리액트 강좌: 비동기 처리

리액트(React)는 컴포넌트를 기반으로 한 UI 라이브러리로, 사용자 인터페이스를 구축하는 데 널리 사용됩니다. 특히, 비동기 처리(Asynchronous Processing)는 현대 웹 애플리케이션에서 핵심적인 역할을 하며, API와의 상호작용 및 데이터 로딩을 효율적으로 처리하는데 필수적입니다.

1. 비동기 처리의 이해

비동기 처리는 코드가 실행되는 동안 다른 작업을 진행할 수 있게 해주는 프로그래밍 패러다임입니다. 이는 주로 다음과 같은 상황에서 필요합니다:

  • HTTP 요청을 보내고 응답을 기다리는 동안, 다른 작업을 수행하고 싶을 때
  • 파일을 읽거나 쓰는 작업이 시간이 걸릴 수 있을 때
  • 시간이 일정하게 걸리는 타이머를 설정할 경우

1.1 동기 vs 비동기

동기(Synchronous) 처리는 작업이 순차적으로 이루어지는 방식입니다. 즉, 한 작업이 완료되기 전까지 다음 작업이 시작되지 않습니다. 반면 비동기(Asynchronous) 처리는 작업이 시작되면, 해당 작업의 결과를 기다리지 않고 다른 작업을 동시에 수행할 수 있는 방식입니다.

1.2 비동기 처리의 필요성

웹 애플리케이션에서는 사용자 경험을 최적화하기 위해 비동기 처리가 필요합니다. 예를 들어, 사용자가 버튼을 클릭하여 데이터를 로딩할 때, 비동기적으로 데이터를 요청하면, UI가 멈추지 않고 사용자에게 빠른 피드백을 줄 수 있습니다.

2. 리액트에서 비동기 처리하기

리액트에서 비동기 처리를 구현하는 방법에는 여러 가지가 있으며, 대표적으로는 Promise, async/await, 그리고 리액트의 상태 관리 툴을 통해 수행할 수 있습니다.

2.1 Promise 사용하기

Promise는 비동기 작업의 성공 또는 실패를 나타내는 객체입니다. Promise 객체를 사용하여 비동기 작업을 처리하는 방법은 다음과 같습니다:


const fetchData = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const data = "데이터 로딩 완료!";
            resolve(data);
        }, 2000);
    });
};

fetchData().then(response => {
    console.log(response);
}).catch(error => {
    console.log(error);
});

2.2 async/await 사용하기

async/await 구문은 Promise를 보다 쉽게 사용할 수 있는 문법입니다. 이 구문을 사용하면 비동기 코드가 마치 동기적으로 실행되는 것처럼 보이게 됩니다:


const fetchData = async () => {
    try {
        const response = await new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve("데이터 로딩 완료!");
            }, 2000);
        });
        console.log(response);
    } catch (error) {
        console.log(error);
    }
};

fetchData();

2.3 리액트의 API와 비동기 처리

리액트에서 API와의 비동기 통신은 주로 useEffect 훅을 통해 이루어집니다. useEffect 훅은 컴포넌트가 렌더링될 때 사이드 이펙트를 발생시키는 데 사용됩니다:


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

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

    useEffect(() => {
        const fetchData = async () => {
            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 
로딩 중...
; } return (

데이터:

{JSON.stringify(data, null, 2)}

);
};

export default DataFetchingComponent;

2.4 상태 관리 도구와 비동기 처리

리액트의 상태 관리를 위한 도구들(예: Redux, MobX) 역시 비동기 처리를 지원합니다. Redux는 Redux Thunk 또는 Redux Saga를 통해 비동기 액션을 다룰 수 있도록 해줍니다.

3. 에러 처리 및 로딩 상태 관리

비동기 작업을 수행할 때, 에러 처리 및 로딩 상태를 관리하는 것은 매우 중요합니다. 사용자에게 로딩 스피너를 보여주거나, 에러 메시지를 표시하는 방식으로 UX를 개선할 수 있습니다. 아래는 간단한 에러 처리 및 로딩 상태 관리 예제입니다:


const DataFetchingComponent = () => {
    const [data, setData] = useState(null);
    const [error, setError] = useState(null);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        const fetchData = async () => {
            try {
                const response = await fetch('https://api.example.com/data');
                if (!response.ok) {
                    throw new Error('네트워크 응답이 이상합니다');
                }
                const result = await response.json();
                setData(result);
            } catch (error) {
                setError(error.message);
            } finally {
                setLoading(false);
            }
        };
        fetchData();
    }, []);

    if (loading) return 
로딩 중...
; if (error) return
에러 발생: {error}
; return
{JSON.stringify(data)}
; };

4. 결론

리액트에서 비동기 처리는 주로 API와의 상호작용과 데이터 로딩을 관리하는 데 중요한 역할을 합니다. Promise, async/await 및 다양한 상태 관리 도구를 통해 효율적으로 비동기 작업을 처리할 수 있습니다. 올바른 비동기 처리 방법을 이해하고 구현함으로써, 사용자에게 보다 나은 경험을 제공할 수 있습니다.

5. 추가적인 자료