Redux) typesafe-actions에 대해, redux-toolkit 차이

·2022년 10월 31일
0

typesafe-actions vs redux-toolkit

회사에서 사용하고 있는 리덕스를 공부하던 중
typesafe-actions 이라는 라이브러리를 발견했다.

공식 설명으로는 아래와 같이 소개된다.

✌ Redux 아키텍처에서 유형의 장황함과 복잡성을 줄이기 위해 설계된 Typesafe 유틸리티입니다. (번역)

🤔그동안 공부하면서 이걸 왜 처음 들었지 싶었는데,
리덕스를 사용했을 때 부터 그동안 쭉 redux-toolkitredux-thunk 을 사용해왔기 때문이었다. 나에게 리덕스를 사용한다는 것은 당연히 이 두가지를 함께 사용하는 것과 같았다. 그래서 특별히 리덕스에 대한 보일러플레이트 불만이 없는 편이었다. 물론 recoil의 간편함에 비할 바는 아니지만..

아무튼 사용해보기 전 typesafe-actions와 redux-toolkit의 장단점과 차이를 알고 싶었다. 무엇보다 이 차이를 공부하다 보면 redux에 대해 더 깊이 이해할 수 있을 것 같다.

이에 간략히 검색해보니 아래의 대략적인 차이를 알 수 있었다.

  1. redux-toolkit은 redux 공식 개발 툴이다.
    그만큼 유지보수가 원활함. 글을 쓰는 시점에도 하루 전에 publish가 되어있지만 typesafe-actions는 3년전이다..

  2. redux-toolkit의 thunk,immer 내장
    redux-thunk는 미들웨어로써 redux에서 비동기 작업을 다루어야 할 때 많이 쓰인다. 액션객체를 그저 생성하는 것이 아닌, 액션 함수에서 여러가지 작업을 할 수 있게 만든다. redux 공식에서 권장하고 있는 방법이며, 굉장히 편리하다👍

사실 위의 두가지 만으로도 typesafe-actions이 아닌 redux-toolkit을 사용할 이유는 충분해 보인다. 또한 툴킷의 여러가지 유용한 api들도 무시할 수 없으니 나는 앞으로도 툴킷을 사용해야겠다고 판단했다.

하지만, 현재 회사 서비스는 툴킷 이전에 개발 되었기 때문에 쭉 typesafe-actions를 사용해오고 있다. 그런데 툴킷을 사용하지 않는다고 서비스에 문제가 있는 것도 아니며 이 라이브러리 또한 redux를 효율적으로 사용할 수 있도록 많은 도움을 준다.
그리고 무엇보다 어차피 나에겐 선택권이 없으니 typesafe-actions에 대해 간단히 알아보자


예시

🤷‍♀️ 각설하고 우선 코드부터 보자.

https://react.vlpt.us/using-typescript/05-ts-redux.html
위 블로그를 참고해 간단 예시를 적어보자면
기존 리덕스는

const INCREASE = 'counter/INCREASE' as const;
export const increase = (num:number) => ({
  	type: INCREASE
});

와 같이 선언하고 액션 생성 함수를 직접 만들어야 했으나

const ADD_TODO = createAction('counter/INCREASE')

로 끝낼 수 있게 된다.

확실히 보일러플레이팅을 줄어들고 더 보기 좋게 코드를 작성할 수 있으며 타입선언을 보다 편하게 도와주고 있다.

  import { 
    ActionType, 
    createAction, 
    getType, 
    isActionOf, 
    createAsyncAction, 
  } from 'typesafe-actions'

내가 공부하려고 하는 소스코드는 위의 api들로 스토어를 구성하고 있는데 역할을 하나씩 정리해보았다.

자주 쓰는 API

ActionType

type helper api라고 적혀있는 이 api는 리덕스에서 nested구조로 복잡하게 되어있는 액션이어도 한번에 액션 type으로 정의해준다.

import { ActionType } from 'typesafe-actions';

// with "import * as ..."
import * as todos from './actions';
export type TodosAction = ActionType<typeof todos>;
// TodosAction: { type: 'action1' } | { type: 'action2' } | { type: 'action3' }

// with nested action-creator map case
const actions = {
  action1: createAction('action1'),
  nested: {
    action2: createAction('action2'),
    moreNested: {
      action3: createAction('action3'),
    },
  },
};
export type RootAction = ActionType<typeof actions>;
// RootAction: { type: 'action1' } | { type: 'action2' } | { type: 'action3' }

출처 : https://github.com/piotrwitek/typesafe-actions

createAction

액션 함수를 생성해준다.

export const addTodo = createAction(ADD_TODO, action => (text: string) =>
  action({
    id: nextId++,
    text
  })
);

출처 : https://react.vlpt.us/using-typescript/05-ts-redux.html

파라미터를 기반한 payload를 설정하는 action 객체를 만드는 함수이다. 단순 createAction으로 싸매지 않고 action만 리턴하는 함수를 만들어도 구현은 가능하나, action-helpers-api(액션 타입을 체크하는 api)지원이 되지 않는다고 한다. 대표적으로 getType/isActionOf가 있다.

createCustomAction

비슷하지만 사용법이 다른 createCustomAction 이라는 메소드도 있다.

const add = createCustomAction('todos/ADD', type => {
  return (title: string) => ({ type, id: cuid(), title, completed: false });
});

createAction은 콜백에 type을 넣어줘야하지만 createCustomAction은 콜백에 포함해줘야하는, 말 그대로 커스텀 액션이다.

getType & isActionOf

타입을 체크하는 action-helpers-api. actionCreator로 생성한 것들만 체크된다. 일반 action은 X

getType
actionCreator의 type을 가져옴

getType(actionCreator)
switch (action.type) {
  case getType(add):
    // action type is { type: "ADD"; payload: number; }
    return state + action.payload;
 
  default:
    return state;
}

isActionOf
action이 주어진 actionCreator인자와 동일한 type인지 체크함

isActionOf(actionCreator, action)
[action1, action2, ...actionN]
  .filter(isActionOf([addTodo, removeTodo])) // only actions with type `ADD` or 'REMOVE' will pass
  .do((action) => {
    // action type is { type: "todos/ADD"; payload: Todo; } | { type: "todos/REMOVE"; payload: Todo; }
    ...

출처 : https://www.npmjs.com/package/typesafe-actions

createAsyncAction

axios와 같은 비동기 흐름 처리를 단순화 하기 위해, 3가지로 구분된 액션 생성 함수를 포함하는 개체를 생성한다.

const fetchUsersAsync = createAsyncAction(
  'FETCH_USERS_REQUEST',
  'FETCH_USERS_SUCCESS',
  'FETCH_USERS_FAILURE'
)<string, User[], Error>();

출처 : https://www.npmjs.com/package/typesafe-actions


전체적으로 typesafe-actions는 redux의 보일러플레이팅을 보조해준다는 느낌이고, redux-toolkit은 리덕스의 버전업?이라는 개인적인 느낌이 든다.

처음 회사에서 소스를 봤을 땐 rxjs와 redux-observable을 사용해서 스토어와 types가 상당히 복잡하게 얽혀있다. 이는 내가 rxjs를 아직 제대로 이해하지 못했기 때문에 미들웨어 부분은 추후 다시 공부해야 할 것 같다.

누군가 글에 틀린 점을 발견하셨다면 댓글 부탁드립니다!😘

profile
나 예인쓰, 응애인디

0개의 댓글