[Chapter 3-3] 5주 차 회고 - React 심화

2022. 9. 1. 15:03WIL

오늘은 3주 동안 진행한 주특기 기간의  마지막 날이다.

 

내일부터는 항해 6주 차의 시작으로 백엔드 개발자분들과 협업해서 미니 프로젝트를 진행한다.

 

 

심화 주차에 학습한 몇 가지 정리


Redux 미들웨어

리덕스에서 dispatch를 하면 action 이 리듀서로 전달이 되고, 리듀서는 새로운 state를 반환한다. 근데 미들웨어를 사용하면 이 과정 사이에 하고 싶은 작업들을 넣을 수 있다.

 

만약 counter 프로그램에서 더하기 버튼을 클릭했을 때 바로 1을 더하지 않고 3초를 기다렸다가, 1을 더하도록 구현하려면 미들웨어를 사용하지 않고서는 구현할 수 없다. 왜냐하면 dispatch가 되자마자 바로 action이 리듀서로 달려가서 새로운 state를 반환해버리기 때문이다. 즉, 3초를 기다리는 작업을 미들웨어가 해주는 것이다.

 

보통 리덕스 미들웨어를 사용하는 이유는 서버와의 통신을 위해서 사용하는 것이 대부분이고, 그중에서도 많이 사용되고 있는 리덕스 미들웨어는 redux-thunk라는 것이다.

 

Redux Thunk

Thunk는 리덕스에서 많이 사용하고 있는 미들웨어 중에 하나로 dispatch를 할 때 객체가 아닌 함수를 dispatch 할 수 있게 해 준다. 그래서 중간에 우리가 하고자 하는 작업을 함수를 통해 넣을 수 있고, 그 함수가 중간에 실행되는 것이다.

dispatch(함수) → 함수 실행 → 함수 안에서 dispatch(객체)

위와 같이 실행이 되며, 이 함수를 thunk 함수라고 부른다.

 

Redux Thunk 예제

Redux Toolkit에서는 createAsyncThunk라는 API를 사용해서 thunk 함수를 생성할 수 있다. 이 API는 함수인데, 첫 번째 인자에는 action value, 두 번째 인자에는 콜백 함수가 들어간다. 즉, 콜백 함수에서 원하는 작업을 구현하면 된다.

// src/redux/modules/counterSlice.js

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";

export const addNumberThunk = createAsyncThunk(
	// 첫번째 인자 : action value
  "addNumber", 
	// 두번째 인자 : 콜백함수 
  (payload, thunkAPI) => {
    setTimeout(() => {
      thunkAPI.dispatch(addNumber(payload));
    }, 3000);
  }
);

const initialState = {
  number: 0,
};

const counterSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {
    addNumber: (state, action) => {
      state.number = state.number + action.payload;
    },

    minusNumber: (state, action) => {
      state.number = state.number - action.payload;
    },
  },
});


export const { addNumber, minusNumber } = counterSlice.actions;
export default counterSlice.reducer;

setTimeout을 이용해 3초를 기다리고 thunkAPI 안에 있는 dispatch를 통해서 addNumber라는 action creator를 넣었다.

 

 

이제 컴포넌트에서 counterSlice에 있는 thunk 함수를 dispatch 하면 된다.

// src/App.jsx

import React from "react";
import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { minusNumber, addNumberThunk } from "./redux/modules/counterSlice";

const App = () => {
  const dispatch = useDispatch();
  const [number, setNumber] = useState(0);
  const globalNumber = useSelector((state) => state.counter.number);

  const onChangeHandler = (evnet) => {
    const { value } = evnet.target;
    setNumber(+value);
  };

  // thunk 함수를 dispatch한다. payload는 thunk함수에 넣어주면,
  // 리덕스 모듈에서 payload로 받을 수 있다.
  const onClickAddNumberHandler = () => {
    dispatch(addNumberThunk(number));
  };

  const onClickMinusNumberHandler = () => {
    dispatch(minusNumber(number));
  };

  return (
    <div>
      <div>{globalNumber}</div>
      <input type="number" onChange={onChangeHandler} />
      <button onClick={onClickAddNumberHandler}>더하기</button>
      <button onClick={onClickMinusNumberHandler}>빼기</button>
    </div>
  );
};

export default App;

비동기 처리와 프로미스(Promise)

자바스크립트에서 비동기 처리란 특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행하는 자바스크립트의 특성을 의미한다.

 

프로미스는 자바스크립트 비동기 연산이 종료된 이후 결과를 알기 위해 사용되는 객체로 전통적인 콜백 패턴으로 인한 콜백 지옥 때문에 ES6에서 도입한 또 다른 비동기 처리 패턴이다. 프로미스를 사용하면 비동기 메서드를 동기적으로 값을 반환할 수 있고 비동기 처리 시점에 대한 명확한 표현이 가능하다.

 

프로미스에는 다음과 같은 세 가지 상태가 있다.

  • 대기(pending): 이행하지도, 거부하지도 않은 초기 상태
  • 이행(fulfilled): 연산이 성공적으로 완료됨
  • 거부(rejected): 연산이 실패함

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise

 

Promise - JavaScript | MDN

Promise 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냅니다.

developer.mozilla.org

 

Axios

Axios는 Promise 기반 HTTP 클라이언트 라이브러리로 브라우저에서는 XMLHttpRequests를 사용한다. 즉, 클라이언트에서 서버와 HTTP 통신을 할 때 사용하는 라이브러리다.

https://axios-http.com/kr/docs/intro

 

시작하기 | Axios Docs

시작하기 브라우저와 node.js에서 사용할 수 있는 Promise 기반 HTTP 클라이언트 라이브러리 Axios란? Axios는 node.js와 브라우저를 위한 Promise 기반 HTTP 클라이언트 입니다. 그것은 동형 입니다(동일한 코

axios-http.com

 

Immer

immer는 react에서 불변성을 유지하는 코드를 작성하기 쉽게 해주는 라이브러리다. 기존에는 불변성을 지켜주기 위해 spread 연산자를 통해 기존 객체를 복사하거나 내장 함수(map, filter, reduce 등)를 사용했다.

 

immer를 이용해 불변성을 지켜주면 예상치 못한 부수 효과를 방지하고 프로그래밍을 단순하게 유지시키며 상태 업데이트를 효율적으로 할 수 있다.

import produce from "immer";

const baseState = [
  {
    todo: "Learn typescript",
    done: true
  },
  {
    todo: "Try immer",
    done: false
  }
];

const nextState = produce(baseState, draftState => {
  draftState.push({ todo: "Learn react" });
  draftState[1].done = true;
});

immer에서 사용할 함수는 produce만 알면 된다. produce의 파라미터 첫 번째는 수정하고 싶은 객체나 배열이고 두 번째는 첫 번째 파라미터에 할당된 객체나 배열을 바꾸는 함수다.

 

Prototype

자바스크립트의 모든 객체는 프로토타입(prototype)이라는 객체를 가지고 있다. 모든 객체는 그들의 프로토타입으로부터 프로퍼티와 메서드를 상속받는다. 이처럼 자바스크립트의 모든 객체는 최소한 하나 이상의 다른 객체로부터 상속을 받으며, 이때 상속되는 정보를 제공하는 객체를 프로토타입(prototype)이라고 한다.

https://developer.mozilla.org/ko/docs/Learn/JavaScript/Objects/Object_prototypes

 

Object prototypes - Web 개발 학습하기 | MDN

Javascript에서는 객체를 상속하기 위하여 프로토타입이라는 방식을 사용합니다. 본 문서에서는 프로토타입 체인이 동작하는 방식을 설명하고 이미 존재하는 생성자에 메소드를 추가하기 위해 프

developer.mozilla.org

 

 

반응형