체인의정석

Redux와 Thunk, CreateAsyncThunk 본문

개발/frontend

Redux와 Thunk, CreateAsyncThunk

체인의정석 2025. 7. 10. 18:49
728x90

Thunk

Tunk는 지연된 작업을 수행하는 코드를 의미하는 프로그래밍 용어.

지금 로직을 실행하는 대신 나중에 해당 작업을 수행하는 데 사용할 수 있는 함수 본문이나 코드를 작성 할 수 있다.

Redux의 경우 Thunk는 Redux 스토어 및 dispatch, get state메서드와 상호 작용할 수 있는 논리를 내장한 함수를 작성하는 패턴

 

만약 redux 앱에서 비동기 로직을 작성하게 된다면 thunk를 사용하는 것이 표준이다. (동기에서도 사용가능하긴 함)

const thunkFunction = (dispatch, getState) => {
  // logic here that can dispatch actions or read state
}

store.dispatch(thunkFunction)

thunk 함수는 dispatch 함수와 getState 함수 2개를 인자 값으로 받는다. Thunk 함수는 어플리케이션 코드에서 바로 불리는게 아니고 store.dispatch()를 통해 전달된다.

여기서는 sync, async같은 함수들을 모두 호출할 수 있다.

export const fetchTodoById = todoId => async dispatch => {
  const response = await client.get(`/fakeApi/todo/${todoId}`)
  dispatch(todosLoaded(response.todos))
}

예를 들어 위와 같은 함수가 thunk로 있다고 한다면, 다른 redux 액션을 전달하는것과 동일하게 다음과 같이 액션 생성자를 호출하여 전달한다.

function TodoComponent({ todoId }) {
  const dispatch = useDispatch()

  const onFetchClicked = () => {
    // Calls the thunk action creator, and passes the thunk function to dispatch
    dispatch(fetchTodoById(todoId))
  }
}

Thunks 의 장점은 redux의 store와 상관 없이도 사용이 가능하다는 점이며, 실행하는 타이밍의 영향을 받지도 않으며 어떤 redux store를 쓸지 모르고도 작성하여 추후에 접근할 수 있다는 점이다.

출처 : https://redux.js.org/usage/writing-logic-thunks#thunk-overview

 

Writing Logic with Thunks | Redux

Usage > Redux Logic > Thunks: writing logic that interacts with the store

redux.js.org

CreateAsyncThunk

Redux에서는 Thunk를 만들어주는 create async Tunk라는 함수도 내장모듈로 존재한다. 이 부분은 예시를 통해 살펴보겠다. thunk를 먼저 만들고, 정의해 준다. Create Async Thunk 함수를 써서 fetchUserByID 라는 tunk를 먼저 만들었다. 이후 create Slice를 하고  reducers에서 자동으로 생성이 되는 표준 reducer actions를 다룬 후에, extraReducers에서 추가적인 action type에 해당되는 부분을 넣을 때 thunk를 넣을 수 있다. fetchUserByID를 extraReducer에 넣은 후에 그 안에 내부적으로 정의할 수 잇으며, slice안에 정의된 thunk는 나중에 app에서 사용할 때 dispatch를 통해서 불러올 수 있다.

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import { userAPI } from './userAPI'

// First, create the thunk
const fetchUserById = createAsyncThunk(
  'users/fetchByIdStatus',
  async (userId: number, thunkAPI) => {
    const response = await userAPI.fetchById(userId)
    return response.data
  },
)

interface UsersState {
  entities: User[]
  loading: 'idle' | 'pending' | 'succeeded' | 'failed'
}

const initialState = {
  entities: [],
  loading: 'idle',
} satisfies UserState as UsersState

// Then, handle actions in your reducers:
const usersSlice = createSlice({
  name: 'users',
  initialState,
  reducers: {
    // standard reducer logic, with auto-generated action types per reducer
  },
  extraReducers: (builder) => {
    // Add reducers for additional action types here, and handle loading state as needed
    builder.addCase(fetchUserById.fulfilled, (state, action) => {
      // Add user to the state array
      state.entities.push(action.payload)
    })
  },
})

// Later, dispatch the thunk as needed in the app
dispatch(fetchUserById(123))

https://redux-toolkit.js.org/api/createAsyncThunk 

 

createAsyncThunk | Redux Toolkit

 

redux-toolkit.js.org

더 자세한 사항은 위링크를 참고

728x90
반응형
Comments