코드숨 리액트 6기 5차 회고

redux를 통해 react 앱에서 비즈니스 로직을 관리하는 reducer들을 추출했던 지난 시간에 이어서 이번주에는 redux-thunk를 활용하여 redux에서 비동기 로직 역시 구현하는 시간을 가졌습니다:)

redux-thunk를 middleware로 추가하면 기존에 action type과 payload를 반환하던 action외에도 dispatch와 getState 두개의 함수를 인자로 받는 callback함수를 반환하는 action을 사용할 수 있습니다.

해당 함수는 비동기 함수로서 동작하여 api 통신 등 비동기적인 동작 이후에 원하는 시점에 dispatch를 실행할 수 있습니다.

과제를 수행하면서 비동기 action에 대해서는 어떤식으로 테스트를 작성해야 할 지 고민을 많이 했습니다.

먼저 기본의 redux코드에 대한 구조와 테스트 방식은 다음과 같이 진행해왔습니다.

action: 데이터를 받아서 action type과 payload를 만들어 반환

// action.jsexport function setRegions(regions) {  return {    type: ACTION_TYPES.SET_REGIONS,    payload: { regions },  };}

reducer: action에서 만든 데이터의 action type을 기반으로 어떤 action이 발생했는지 확인하고 payload를 적절히 가공하여 store를 업데이트

// reducer.jsexport default function reducer(state = initialState, action) {
if (action.type === ACTION_TYPES.SET_REGIONS) {
return {
...state, regions: action.payload.regions, } } return state;}

테스트: reducer에 테스트하려는 action을 주입하고 원하는 결과값이 반환되는지 확인

// reducer.test.jsit('returns state with new regions', () => {  const regions = [{ id: 1, name: '서울' }];  const state = reducer(undefined, setRegions(regions));  expect(state.regions).toEqual(regions);});

반면 비동기 action의 경우 반환하는 값이 action type과 payload가 아닌 callback 함수를 반환합니다. 기존처럼 리턴값이 reducer에 들어가는것이 아니라 리턴값인 함수가 내부적으로 dispatch를 실행합니다.

// actoin.jsexport function fetchRegions() {  return async (dispatch, getState) => {    const regions = await apiService.fetchRegions();    dispatch(setRegions(regions));  };}

action이 의도한 callback함수를 잘 반환하는지 테스트하는 방향으로 테스트 코드를 작성했습니다. callback 함수는 fetch 등 비동기 통신을 하는 service 레이어의 코드를 사용하고 있기 때문에 service를 모킹하여 dispatch가 원하는 인자와 함께 호출 되는지를 테스트했습니다.

// action.test.jsconst fetchedRegions = [{ id: 1, name: '서울' }];
const dispatch = jest.fn();
it('callback calls dispatch', async () => { const callback = fetchRegions(); await callback(dispatch, () => ({ regions: [] })); expect(dispatch).toBeCalledWith(setRegions(fetchedRegions));});

이 외에도 fetch를 호출하는 Service 레이어의 코드는 fetch를 모킹하여 적절하게 호출되는지를 테스트해보았고,

아직도 헤메고는 있지만 트레이너님의 리뷰를 받아가며 describe, context, it의 적절한 사용방법과 합리적인 테스트 코드를 구성하는 방법에 대해 연습하고 있습니다.

때로는 describe 내부에 다시 describe가 들어가거나, describe의 하위 개념이라고 생각했던 context 내부에 상위 개념이라고 생각했던 describe가 들어갈 수도 있다는 것을 배웠고, 아마 실무에서는 구성원들간의 충분한 토론과 합의를 통해서 적절한 컨벤션을 채택하지 않을까라는 생각이 들었습니다:)

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store