Redux 미들웨어 없이 비동기 처리하기

배경

소규모 어드민 프로젝트를 시작하면서 Redux 미들웨어를 쓰지 않기로 했다. redux-thunk는 간단하지만 액션 크리에이터가 비대해지고, redux-saga는 러닝커브가 있었다. 팀원 모두 Redux를 처음 쓰는 상황이라 더 단순한 방법을 찾았다.

구현 방식

컴포넌트에서 API를 호출하고, 성공/실패 시 동기 액션만 디스패치하는 방식이다.

class UserList extends Component {
  componentDidMount() {
    this.fetchUsers();
  }

  fetchUsers = async () => {
    this.props.dispatch({ type: 'FETCH_USERS_REQUEST' });
    try {
      const response = await fetch('/api/users');
      const users = await response.json();
      this.props.dispatch({ type: 'FETCH_USERS_SUCCESS', payload: users });
    } catch (error) {
      this.props.dispatch({ type: 'FETCH_USERS_FAILURE', payload: error });
    }
  }

  render() {
    // ...
  }
}

Reducer는 동기 액션만 처리하면 되어 간단했다.

function userReducer(state = { loading: false, data: [], error: null }, action) {
  switch (action.type) {
    case 'FETCH_USERS_REQUEST':
      return { ...state, loading: true, error: null };
    case 'FETCH_USERS_SUCCESS':
      return { loading: false, data: action.payload, error: null };
    case 'FETCH_USERS_FAILURE':
      return { ...state, loading: false, error: action.payload };
    default:
      return state;
  }
}

한계

재사용성이 떨어진다. 같은 API를 여러 곳에서 호출하면 로직이 중복된다. 유틸 함수로 분리해도 컴포넌트가 디스패치 로직을 알아야 한다.

규모가 커지면 결국 미들웨어가 필요할 것 같다. 하지만 지금은 이 방식이 팀에게 더 직관적이었다.

Redux 미들웨어 없이 비동기 처리하기