[typescript] Redux 상태 관리에서의 타입스크립트와 비동기 작업 처리 방법

Redux는 React 애플리케이션의 상태를 효율적으로 관리하는 도구로, 타입스크립트와 함께 사용하면 더욱 강력한 상태 관리를 할 수 있습니다. 여기에서는 Redux와 타입스크립트를 함께 사용하여 비동기 작업을 처리하는 방법을 살펴보겠습니다.

타입스크립트와 함께 Redux 사용하기

Redux를 사용하면 상태의 변화를 예측 가능하고 일관된 방식으로 관리할 수 있습니다. 타입스크립트를 이용하면 액션 및 리듀서와 같은 Redux의 핵심 개념들을 더욱 명확하게 정의할 수 있습니다.

예를 들어, 액션과 상태의 타입을 정의할 때 다음과 같은 코드를 사용할 수 있습니다:

type Todo = {
  id: number;
  text: string;
  completed: boolean;
};

type RootState = {
  todos: Todo[];
  loading: boolean;
  error: string | null;
};

interface AddTodoAction {
  type: 'ADD_TODO';
  payload: Todo;
}

interface DeleteTodoAction {
  type: 'DELETE_TODO';
  payload: number;
}

type Action = AddTodoAction | DeleteTodoAction;

이러한 명확한 타입 정의는 Redux 애플리케이션의 개발을 도와주고, 에러를 사전에 방지할 수 있도록 도와줍니다.

비동기 작업 처리 방법

Redux는 기본적으로 동기적인 작업을 다루기 위한 도구이지만, 비동기 작업을 처리하기 위해 Redux Thunk, Redux Saga, 또는 Redux Observable과 같은 미들웨어를 이용할 수 있습니다. 여기에서는 Redux Thunk를 사용한 비동기 작업 처리 방법을 살펴보겠습니다.

먼저, Redux Thunk를 설치합니다:

npm install @reduxjs/toolkit redux-thunk

그리고 리듀서를 정의할 때 비동기 작업을 처리하기 위해 createAsyncThunk를 사용합니다:

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import { RootState } from './store';

interface Post {
  userId: number;
  id: number;
  title: string;
  body: string;
}

const fetchPosts = createAsyncThunk(
  'posts/fetchPosts',
  async () => {
    const response = await fetch('https://jsonplaceholder.typicode.com/posts');
    return (await response.json()) as Post[];
  }
);

const postsSlice = createSlice({
  name: 'posts',
  initialState: [] as Post[],
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchPosts.fulfilled, (state, action) => {
        return action.payload;
      });
  }
});

export const postsActions = { ...postsSlice.actions, fetchPosts };
export default postsSlice.reducer;

위 코드에서 createAsyncThunk를 이용하여 fetchPosts 액션을 정의하고, extraReducers를 통해 비동기 작업이 완료된 후의 상태 변화를 처리합니다.

이제 이를 컴포넌트에서 사용할 때는 useDispatch 후에 fetchPosts 액션을 디스패치하면 됩니다:

import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchPosts, RootState } from './store';

const PostList = () => {
  const dispatch = useDispatch();
  const posts = useSelector((state: RootState) => state.posts);

  useEffect(() => {
    dispatch(fetchPosts());
  }, [dispatch]);

  // ... UI 렌더링 및 상태 표시
};

이처럼 Redux와 타입스크립트를 함께 사용하여 상태를 효과적으로 관리하고, 비동기 작업을 처리할 수 있습니다. 타입스크립트의 강력함과 Redux의 효율성을 결합하여 안정적이고 확장 가능한 애플리케이션을 개발할 수 있습니다.

참고 자료