[React] React-thunk ์•Œ์•„๋ณด๊ธฐ
728x90

redux-thunk?

๋ฆฌ๋•์Šค์— ๊ด€ํ•ด์„œ ๊ณต๋ถ€ํ•˜๋‹ค ๋ณด๋ฉด '๋ฏธ๋“ค์›จ์–ด'๋ผ๋Š” ๊ฒƒ์„ ํ•œ ๋ฒˆ์ฏค ๋“ค์–ด๋ณด์•˜์„ ๊ฒƒ์ด๋‹ค.

redux-thunk, redux-saga, ๊ทธ ์™ธ์—๋„ redux-promise-middleware ๋“ฑ ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ๋Š”๋ฐ ์˜ค๋Š˜์€ ๊ทธ์ค‘์—์„œ๋„ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘ ํ•˜๋‚˜์ธ redux-thunk์— ๋Œ€ํ•˜์—ฌ ์ •๋ฆฌํ•ด๋ณด๋ ค ํ•œ๋‹ค.

 

 

๋ฆฌ๋•์Šค ๋ฏธ๋“ค์›จ์–ด?

๋จผ์ € ๋ฏธ๋“ค์›จ์–ด์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณผ๊นŒ ํ•œ๋‹ค.

๋ฆฌ๋•์Šค๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์•˜๋‹ค๋ฉด ์œ„์™€ ๊ฐ™์€ ๊ตฌ์กฐ๋กœ ๋ฆฌ๋•์Šค๊ฐ€ ์ƒˆ๋กœ์šด state๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์„ ๊ฒƒ์ด๋‹ค.

dispatch๋ฅผ ํ†ตํ•ด ๋ฆฌ๋“€์„œ๋กœ ์ „๋‹ฌ๋œ ์•ก์…˜์ด ๋ฆฌ๋“€์„œ๋กœ ์ „๋‹ฌ๋˜์–ด state๊ฐ€ ๋ณ€๊ฒฝ๋œ๋‹ค๋Š” ๊ฒƒ!

๋ฆฌ๋•์Šค ๋ฏธ๋“ค์›จ์–ด๋Š” ์—ฌ๊ธฐ์„œ ์•ก์…˜์ด ๋””์ŠคํŒจ์น˜๋˜๊ณ  ๋ฆฌ๋“€์„œ์— ์ „๋‹ฌ๋˜๊ธฐ ์ „์— ์ถ”๊ฐ€์ ์ธ ์ž‘์—…์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๋ณดํ†ต ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•˜๋ฉฐ ๋น„๋™๊ธฐ์ž‘์—…์„ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.

์œ„์— ์–ธ๊ธ‰ํ•œ ๋ฏธ๋“ค์›จ์–ด๋“ค๋„ ๋ชจ๋‘ ๋น„๋™๊ธฐ ์ž‘์—…์— ๊ด€๋ จ๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด๋‹ค.

๊ทธ๋Ÿผ ์ด์ œ ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ๋ญ”์ง€ ์•Œ์•˜์œผ๋‹ˆ ๊ตฌ์ฒด์ ์œผ๋กœ redux-thunk์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

 

 

 

redux-thunk

๋น„๋™๊ธฐ ์ž‘์—… ์ฒ˜๋ฆฌ์— ๊ฐ€์žฅ ๋งŽ์ด ์ด์šฉํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด์ธ thunk์˜ ๊ฐ€์žฅ ํฐ ํŠน์ง•์€ ์•ก์…˜ ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ, ํ•จ์ˆ˜๋ฅผ dispatch ํ•  ์ˆ˜ ์žˆ๋‹ค.
์—ฌ๊ธฐ์„œ์˜ dispatch ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ thunk ํ•จ์ˆ˜๋ผ๊ณ  ํ•œ๋‹ค.

thunk ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋Š” createAsyncThunk ๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•œ๋‹ค.
์ด ํ•จ์ˆ˜์—๋Š” ๋‘ ๊ฐœ์˜ ์ธ์ž๊ฐ€ ๋“ค์–ด๊ฐ€๋Š”๋ฐ, ์ฒซ ๋ฒˆ์งธ๋Š” action value, ๋‘ ๋ฒˆ์งธ๋Š” ํ•จ์ˆ˜๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค. ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ์ž‘์—…์ด ์žˆ๋‹ค๋ฉด ๋‘ ๋ฒˆ์งธ ์ธ์ž์˜ ํ•จ์ˆ˜์—์„œ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค.

 

 

์นด์šดํ„ฐ๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ์•„๋ž˜ ํ•จ์ˆ˜๋Š” 3์ดˆ ํ›„์— thunk ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ dispatch๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.
์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์•Œ๊ฒ ์ง€๋งŒ, ๋‘ ๋ฒˆ์งธ ํ•จ์ˆ˜์—์„œ๋Š” payload์™€ thunkAPI ์ธ์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
payload๋Š” ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ณด๋‚ธ payload ์ด๊ณ , thunkAPI๋Š” thunk๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์—ฌ๋Ÿฌ API๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

export const __addNumber = createAsyncThunk('addNumber', (payload, thunkAPI) => {
  setTimeout(() => {
    thunkAPI.dispatch(addNumber(payload));
  }, 3000);
});

thunk ํ•จ์ˆ˜์˜ ์‚ฌ์šฉ์€ ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ์˜ ๊ธฐ๋ณธ ๋ฆฌ๋“€์„œ์˜ action creator๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹๊ณผ ๋™์ผํ•˜๋‹ค.

 

 

 

thunk๋กœ Promise ํ•ธ๋“ค๋ง

thunkAPI๋ฅผ ํ†ตํ•ด์„œ Promise๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋‹ค. (Promise๋Š” ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ๊ฐ์ฒด!)
์š”์ฒญ์ด ์„ฑ๊ณตํ•œ ๊ฒฝ์šฐ dispatch ํ•˜๋Š” fulfillWithValue, ์‹คํŒจํ–ˆ์„ ๊ฒฝ์šฐ dispatch ํ•˜๋Š” rejectWithValue ๊ฐ™์€ API๋“ค๋กœ thunk ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ dispatch ํ•  ์ˆ˜ ์žˆ๋‹ค.

export const __getTodos = createAsyncThunk('todos/getTodos', async (payload, thunkAPI) => {
  try {
    const data = await axios.get('http://localhost:3001/todos');
    return thunkAPI.fulfillWithValue(data.data);
  } catch (error) {
    return thunkAPI.rejectWithValue(error);
  }
});

 

 

์œ„ ์ฝ”๋“œ๋งŒ ๋ด์„œ๋Š” ์–ด๋–ค ๋ฆฌ๋“€์„œ์—๊ฒŒ dispatch๋ฅผ ์ „๋‹ฌํ•ด์ฃผ๋Š”์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค.
๋ฆฌ๋“€์„œ์— thunk ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ, thunk ํ•จ์ˆ˜๋Š” Reducers ์™ธ๋ถ€์—์„œ ์ž‘์„ฑ๋œ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— extraReducers๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

์•„๋ž˜์˜ ์ฝ”๋“œ๋Š” ๋ฐ˜ํ™˜๋œ Prmomise์ธ ๋กœ๋”ฉ์ƒํƒœ(pending, fulfilled, rejected)์— ๋”ฐ๋ผ์„œ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ๋‹ค.


์œ„์˜ thunk ํ•จ์ˆ˜์—์„œ fulfillWithValue ๋˜์—ˆ๋‹ค๋ฉด extraReducers์˜ [__getTodos.fulfilled] ๋ถ€๋ถ„์œผ๋กœ dispatch๊ฐ€ ์ „๋‹ฌ๋œ๋‹ค.

export const todosSlice = createSlice({
  name: 'todos',
  initialState,
  reducers: {},
  extraReducers: {
    [__getTodos.pending]: (state) => { // ๋กœ๋”ฉ์ค‘์ผ ๋•Œ
      state.isLoading = true;
    },
    [__getTodos.fulfilled]: (state, action) => { // ์„ฑ๊ณตํ–ˆ์„ ๋•Œ
      state.isLoading = false;
      state.todos = action.payload;
    },
    [__getTodos.rejected]: (state, action) => { // ์‹คํŒจํ–ˆ์„ ๋•Œ
      state.isLoading = false;
      state.error = action.payload;
    },
  },
});

์ข€ ๋” ๊ณต๋ถ€ํ•ด๋ด์•ผ๊ฒ ์ง€๋งŒ redux-thunk๋ฅผ ์ด์šฉํ•ด์„œ ๋ฆฌ๋•์Šค์—์„œ์˜ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ข€ ๋” ํŽธํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค!

 

 

 

 

 

 

728x90