[POB#34] Assignment 9 : 페이워크 기업 과제. Redux-Saga 이용해 비동기 네트워크 통신

dongwon·2021년 9월 2일
1

원티드-프리온보딩

목록 보기
25/25
post-thumbnail

Assignment 9: 페이워크 기술 과제 정리 글입니다.

Redux-Saga를 이용한 비동기 네트워크 통신

json-server로 만든 임시 서버와 Redux-Saga를 이용해 비동기 네트워크 통신을 진행했습니다. Redux-Saga를 이용해 Todo Item을 생성하는 과정을 정리해봤습니다.

action, reducer, saga 생성

Todo Item을 생성하는 action, reducer, saga 생성 과정입니다.

action

Todo Item을 생성 요청, 성공, 실패를 처리하기 위해 각각 액션 타입과 액션 생성 함수를 생성했습니다.

요청 함수에는 Item 생성에 필요한 데이터성공 함수에는 전역 상태에 추가할 데이터를 받았습니다.

// store/actions
export const CREATE_TODO_REQUEST = "CREATE_TODO_REQUEST" as const;
export const CREATE_TODO_SUCCESS = "CREATE_TODO_SUCCESS" as const;
export const CREATE_TODO_FAILURE = "CREATE_TODO_FAILURE" as const;

export const createTodoRequest = ({ content, isCheck, createAt }: ITodo) => ({
  type: CREATE_TODO_REQUEST,
  content,
  isCheck,
  createAt,
});

export const createTodoSuccess = (payload: ITodo) => ({
  type: CREATE_TODO_SUCCESS,
  payload,
});

export const createTodoFailure = (payload: Error) => ({
  type: CREATE_TODO_SUCCESS,
  payload,
});

export type TodoAction =
  | ReturnType<typeof createTodoRequest>
  | ReturnType<typeof createTodoSuccess>
  | ReturnType<typeof createTodoFailure>;

reducer

Action Type 별로 전역 변수를 관리합니다. 로딩과 에러 처리를 위해 createLoading, createError 변수를 이용했습니다.
CREATE_TODO_SUCCESS Action 시에 전달받은 새로운 Todo Item을 spread 연산자를 이용해 불변성을 유지한 채 기존의 todos에 추가했습니다.

// store/reducers/todo
export const initialState = {
  todos: [],
  createLoading: false,
  createError: false,
};

type TodoState = {
  todos: ITodo[];
  createLoading: boolean;
  createError: boolean;
};

const todo = (
  state: TodoState = initialState,
  action: TodoAction
): TodoState => {
  switch (action.type) {
    case CREATE_TODO_REQUEST:
      return {
        ...state,
        createLoading: true,
        createError: false,
      };
    case CREATE_TODO_SUCCESS:
      return {
        ...state,
        todos: [...state.todos, { ...action.payload }],
        createLoading: false,
        createError: false,
      };
    case CREATE_TODO_FAILURE:
      return {
        ...state,
        createLoading: false,
        createError: true,
      };
  }
};

sagas

비동기 통신을 담당하는 saga 부분입니다.

takeLatest effects를 이용해 dispatch로 Action이 호출될 때 마지막 요청의 응답만을 얻을 수 있습니다. 첫 번째 인자로 Action, 두 번째 인자로 Action이 dispatch 됐을 때 실행할 함수를 적습니다.

먼저 액션 생성 함수에서 전달받은 변수들을 action을 통해 받을 수 있습니다. 비구조화 할당 문법을 통해 미리 선언했습니다.

saga 함수에선 callput effects를 사용했습니다.
call effect를 이용해 네트워크 통신 함수를 실행시킵니다. 일반 함수는 함수 뒤에 괄호를 이용해 인자를 전달하지만, call effect두 번째 인자에 전달한 인수들을 적습니다.

call effect는 함수를 동기적으로 실행합니다. 마치 함수 앞에 await를 준 효과를 줄 수 있어 네트워크 응답을 받은 후 다음 로직을 실행할 수 있습니다. 비동기적으로 실행하려면 call 대신 fork effect를 사용합니다.

putdispatch와 같은 effect입니다. 앞의 call effect로 응답을 제대로 받았다면 성공 Action을 dispatch, 응답받는 과정에서 오류가 생겼다면 실패 Action을 호출합니다. payload 변수를 통해 성공 시 응답을, 실패 시 에러를 전달했습니다.

// store/sagas/todo
function* createTodoSaga(action: ReturnType<typeof createTodoRequest>) {
  try {
    const { content, isCheck, createAt } = action;

    //export const createTodoData = ({ content, isCheck, createAt }: ITodo) =>
    //axios.post(`${BASE_URL}/${END_POINT}`, { content, isCheck, createAt });

    const response: AxiosResponse = yield call(authApi.createTodoData, {
      content,
      isCheck,
      createAt,
    });

    yield put({
      type: CREATE_TODO_SUCCESS,
      payload: response.data,
    });
  } catch (e) {
    yield put({
      type: CREATE_TODO_FAILURE,
      payload: e,
    });
  }
}

export function* todoSaga() {
  yield takeLatest(CREATE_TODO_REQUEST, createTodoSaga);
}

흐름 정리

  1. 컴포넌트에서 dispatch를 통해 요청 Action 호출
  2. reducer에서 요청 Action 호출 -> 전역 상태 관리
  3. Redux-saga에서 Action 호출 후 saga 함수 실행
  4. saga 함수에서 동기적으로 네트워크 요청 처리 후 다음 Action 실행 ( 성공 혹은 실패 Action )
  5. reducer에서 다음 Action 호출 -> 전역 상태 관리
profile
데이원컴퍼니 프론트엔드 개발자입니다.

0개의 댓글