Frontend/React

Redux 미들웨어(Middleware) 완벽 이해하기 – Redux Thunk로 비동기 처리하기

sliver__ 2025. 7. 26. 20:39
728x90

Redux를 배우다 보면, 어느 순간 “그럼 API 요청 같은 비동기 작업은 어디서 처리하지?” 라는 의문이 생깁니다.
Reducer 안에서는 안 됩니다.
컴포넌트 안에서 처리? 가능은 하지만 깔끔하지 않습니다.

이때 등장하는 것이 바로 **Redux Middleware(미들웨어)**입니다.


Redux Middleware란 무엇인가?

Redux 미들웨어(Middleware)
액션(action)이 디스패치(dispatch)된 후, 리듀서(reducer)에 도달하기 전에 실행되는 함수입니다.

즉,
Action → Dispatch → (Middleware) → Reducer → Store 업데이트
이 흐름에서 중간(Middle) 단계에서 가로채 작업을 추가할 수 있는 ‘중간 관리자’ 역할을 합니다.


왜 미들웨어가 필요할까?

Redux는 기본적으로 **동기적(synchronous)**입니다.
즉, 액션을 디스패치하면 곧바로 상태(state)가 업데이트됩니다.

하지만 실제 앱에서는 API 호출, 타이머 설정, 로깅(logging) 같은 **비동기 작업(asynchronous)**이 필요합니다.

Reducer는 순수 함수(Pure Function)여야 하므로
 Reducer 안에서 API 호출이나 비동기 작업을 하면 안 됩니다.

그렇다고 모든 API 호출을 컴포넌트에서 하면?
데이터 요청 로직이 여기저기 흩어져 유지보수가 어려워집니다.

이럴 때 Redux 미들웨어가 해답입니다.


Redux Thunk – 가장 많이 쓰는 미들웨어

Redux에서 가장 널리 쓰이는 비동기 처리 미들웨어가 Redux Thunk입니다.

Thunk란?
“지연된 작업을 감싼 함수”를 의미합니다.
액션 대신 함수를 디스패치할 수 있게 만들어 줍니다.

Redux Thunk 동작 방식

컴포넌트에서 **액션 대신 함수(Thunk 함수)**를 디스패치
Redux Thunk 미들웨어가 이 함수를 가로챔
Thunk 함수 안에서 API 요청 실행
데이터가 도착하면 **정상적인 액션(dispatch)**을 실행해 상태 업데이트


Thunk 사용 예제 (동작 흐름)

기존 Redux 동기 액션

dispatch({ type: 'FETCH_POSTS', payload: posts });

📌 Thunk로 비동기 처리

const fetchPosts = () => async (dispatch) => {
  const response = await fetch('/api/posts');
  const data = await response.json();

  // 데이터가 도착한 후 액션을 디스패치
  dispatch({ type: 'FETCH_POSTS', payload: data });
};

➡️ 결과적으로 컴포넌트는 이렇게 간단해집니다:

dispatch(fetchPosts());

👉 API 요청 로직은 Thunk 안에 캡슐화, 컴포넌트는 깨끗하고 단순해집니다.


Redux 미들웨어로 할 수 있는 일

비동기 API 요청 (Redux Thunk)
액션 로깅(logging) – 액션이 언제/어디서 발생했는지 기록
액션 차단/취소 – 조건에 따라 액션이 reducer로 넘어가는 걸 막음
타이머/지연 처리 (setTimeout, setInterval)

즉, **모든 사이드 이펙트(side effects)**는 미들웨어에서 처리하는 게 원칙입니다.


정리

  • Redux는 동기적이기 때문에, 비동기 처리를 위해 미들웨어가 필요하다.
  • Middleware는 dispatch와 reducer 사이에서 실행된다.
  • Redux Thunk는 비동기 API 요청을 가장 많이 처리하는 미들웨어다.
  • Thunk 함수는 액션 대신 ‘함수’를 디스패치할 수 있게 해준다.

다음 글에서는 Redux Thunk 설치와 실제 프로젝트에 적용하는 방법을 코드와 함께 다뤄보겠습니다.

728x90