[typescript] Redux 상태 관리에서의 타입스크립트와 코드 가독성 향상

Redux는 React 애플리케이션에서 상태를 관리하는 데 유용한 도구입니다. 하지만 Redux를 사용할 때 코드의 복잡성이 증가하여 유지보수와 가독성에 어려움을 겪을 수 있습니다. 여기서 타입스크립트를 Redux와 함께 사용하여 코드의 가독성을 향상시키는 방법에 대해 살펴보겠습니다.

1. 액션과 액션 크리에이터에 타입 적용

먼저 Redux에서 액션과 액션 크리에이터에 타입을 적용하는 것이 중요합니다. 이를 통해 코드에서 액션의 유형을 명확히 알 수 있고, 실수를 줄일 수 있습니다.

예를 들어, 다음과 같이 actions.ts 파일을 만들어 액션과 액션 크리에이터를 정의할 수 있습니다.

// actions.ts

export enum ActionType {
  ADD_TODO = 'ADD_TODO',
  COMPLETE_TODO = 'COMPLETE_TODO',
}

export type AddTodoAction = {
  type: ActionType.ADD_TODO;
  payload: string;
};

export type CompleteTodoAction = {
  type: ActionType.COMPLETE_TODO;
  payload: number;
};

export type TodoAction = AddTodoAction | CompleteTodoAction;

export const addTodo = (text: string): AddTodoAction => ({
  type: ActionType.ADD_TODO,
  payload: text,
});

export const completeTodo = (index: number): CompleteTodoAction => ({
  type: ActionType.COMPLETE_TODO,
  payload: index,
});

위의 예제에서 ActionType 열거형을 사용하여 액션의 유형을 정의하고, 각 액션에 대한 타입을 정의했습니다. 또한 액션 크리에이터도 해당 타입을 반환하도록 정의하여 타입 안정성을 확보했습니다.

2. 리듀서에 타입 적용

다음으로, 리듀서 함수에 타입을 적용하여 상태 변화에 대한 안정성을 높일 수 있습니다.

// reducers.ts

import { ActionType, TodoAction } from './actions';

export type Todo = {
  text: string;
  completed: boolean;
};

export type TodoState = {
  todos: Todo[];
};

const initialState: TodoState = {
  todos: [],
};

const todoReducer = (state: TodoState = initialState, action: TodoAction): TodoState => {
  switch (action.type) {
    case ActionType.ADD_TODO:
      return {
        ...state,
        todos: [...state.todos, { text: action.payload, completed: false }],
      };
    case ActionType.COMPLETE_TODO:
      return {
        ...state,
        todos: state.todos.map((todo, index) =>
          index === action.payload ? { ...todo, completed: true } : todo
        ),
      };
    default:
      return state;
  }
};

export default todoReducer;

위의 예제에서 TodoTodoState 타입을 정의하여 상태의 모양을 명확히 했습니다. 또한 리듀서 함수에는 액션의 타입을 받아오도록 정의하여 올바른 액션만 처리할 수 있도록 했습니다.

3. 타입 관련 유틸리티 함수 사용

마지막으로, 타입 관련 유틸리티 함수를 사용하여 Redux 코드를 더 가독성 있게 작성할 수 있습니다. 예를 들어, ReturnType 유틸리티 타입을 사용하여 액션 크리에이터 함수의 반환 타입을 추론하거나, useSelector 훅을 활용하여 상태 선택자를 타입 안전하게 사용할 수 있습니다.

import { useSelector } from 'react-redux';
import { RootState } from './store';

const todos = useSelector((state: RootState) => state.todos);

위의 코드에서 RootState는 Redux 상태 전체의 타입을 정의하는 루트 상태 타입입니다. 이를 사용하여 useSelector 훅을 통해 상태를 선택할 때 타입 안전성을 확보할 수 있습니다.

결론

타입스크립트를 Redux와 함께 사용하여 코드의 가독성을 향상시킬 수 있습니다. 액션과 액션 크리에이터, 리듀서, 그리고 타입 관련 유틸리티 함수를 활용하여 타입 안정성을 높이고, 코드를 보다 명확하게 작성할 수 있습니다.

참고 자료: