[typescript] Redux 상태 관리에서의 타입스크립트와 React 연동 방법

Redux는 React 애플리케이션에서 상태를 효과적으로 관리하기 위한 도구로, 상태의 예측 가능성과 변이를 추적하는 데 도움을 줍니다. 타입스크립트(TypeScript)는 JavaScript에 정적 타입을 추가한 언어로, 코드의 안정성과 가독성을 높일 수 있습니다. 이 블로그에서는 Redux와 타입스크립트를 함께 사용하여 React 애플리케이션의 상태 관리를 어떻게 향상시킬 수 있는지에 대해 살펴보겠습니다.

1. Redux와 타입스크립트 설치

먼저, 프로젝트에 Redux와 타입스크립트를 설치해야 합니다. 다음 명령어를 사용하여 패키지를 설치합니다.

npm install redux react-redux @types/react-redux

2. 리덕스 액션 타입 정의

Redux에서 사용할 액션 타입을 정의할 때, 타입스크립트를 활용하여 정적 타입을 지정할 수 있습니다. 예를 들어, 다음과 같이 액션 타입을 정의할 수 있습니다.

// actions.ts
export const ADD_TODO = 'ADD_TODO';
export const TOGGLE_TODO = 'TOGGLE_TODO';

export interface AddTodoAction {
  type: typeof ADD_TODO;
  payload: {
    id: number;
    text: string;
  };
}

export interface ToggleTodoAction {
  type: typeof TOGGLE_TODO;
  payload: {
    id: number;
  };
}

export type TodoAction = AddTodoAction | ToggleTodoAction;

위 예시에서 AddTodoActionToggleTodoAction은 각각 ADD_TODOTOGGLE_TODO라는 문자열 타입의 type 프로퍼티와 payload 프로퍼티를 가진 객체로 정의되어 있습니다. 또한, TodoAction은 이 두 타입 중 하나를 가질 수 있는 유니온 타입으로 정의되어 있습니다.

3. 리덕스 상태 관리

Redux에서 상태와 액션을 관리할 때, 타입스크립트를 사용하여 상태의 타입과 함께 reducer와 action creator 함수의 반환 타입을 명시할 수 있습니다. 예를 들어, 다음과 같이 상태와 reducer를 정의할 수 있습니다.

// types.ts
export interface Todo {
  id: number;
  text: string;
  completed: boolean;
}

export interface TodoState {
  todos: Todo[];
}

// reducer.ts
import { TodoAction } from './actions';
import { TodoState } from './types';

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

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

export default todoReducer;

위 코드에서 TodoTodoState는 각각 할 일 항목과 할 일 상태의 타입을 정의하고, todoReducer에서는 해당 타입을 이용하여 상태와 액션을 관리합니다.

4. 리액트 컴포넌트와 연동

마지막으로, 리덕스 상태를 리액트 컴포넌트와 연동할 때, react-redux 라이브러리를 사용하고 타입스크립트를 활용하여 상태와 디스패치를 전달할 수 있습니다. 예를 들어, 다음과 같이 컴포넌트를 작성할 수 있습니다.

import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { RootState } from '../store';
import { Todo, TodoState } from '../store/types';
import { addTodo, toggleTodo } from '../store/actions';

const TodoList: React.FC = () => {
  const todos = useSelector<RootState, Todo[]>(state => state.todo.todos);
  const dispatch = useDispatch();

  const handleAddTodo = (text: string) => {
    const id = todos.length + 1;
    dispatch(addTodo({ id, text }));
  };

  const handleToggleTodo = (id: number) => {
    dispatch(toggleTodo({ id }));
  };

  return (
    <div>
      {todos.map(todo => (
        <div key={todo.id}>
          <span
            style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}
            onClick={() => handleToggleTodo(todo.id)}
          >
            {todo.text}
          </span>
        </div>
      ))}
      <input type="text" onKeyDown={(e) => {
        if (e.key === 'Enter') {
          handleAddTodo(e.currentTarget.value);
          e.currentTarget.value = '';
        }
      }} />
    </div>
  );
};

export default TodoList;

위 코드에서 useSelector를 사용하여 상태를 가져오고, useDispatch를 사용하여 디스패치를 가져온 후, 해당 상태와 디스패치를 이용하여 상태를 업데이트하고 관리할 수 있습니다.

이러한 방법으로 Redux와 타입스크립트를 함께 사용하여, React 애플리케이션의 상태를 보다 안정적으로 관리할 수 있습니다.

이상으로 Redux와 타입스크립트를 함께 사용하여 상태를 관리하는 방법에 대해 알아보았습니다. 향후 프로젝트 개발 시에 유용하게 활용할 수 있도록 공부하시기 바랍니다.

태그: Redux, TypeScript, React, 상태 관리, 연동 방법