기은P
시간이 멈추는 장소
기은P
  • Programming (272)
    • 개발노트 (1)
    • FrontEnd (56)
      • ES&JS 문법 (14)
      • HTML&CSS (4)
      • React 기본 (18)
      • React 심화 (12)
      • React 이슈 (2)
      • Project 연습 (1)
      • Next.js (5)
    • Backend&Devops (33)
      • AWS (2)
      • Docker (9)
      • Jenkins (6)
      • Nginx (6)
      • Node.js (1)
      • ElasticSearch (5)
      • 프레임워크&아키텍처 (2)
      • 암호화 (0)
      • 기타 (2)
    • 알고리즘 (3)
    • C# (8)
      • WPF (8)
    • Java (51)
      • 순수 Java (18)
      • RDF&Jena (12)
      • RCP&GEF (9)
      • JMX (5)
      • JMapper (3)
      • 오류해결 (4)
    • Database (21)
      • RDBMS (9)
      • NoSQL (2)
      • TSDB (1)
      • GraphQL (1)
      • Hibernate (3)
      • 데이터베이스 이론 (4)
      • Redis (1)
    • 프로토콜 (11)
      • Netty (4)
      • gRPC (5)
      • 프로토콜 개념 (2)
    • Server (4)
      • Linux (4)
    • 2020 정보처리기사 필기 (43)
      • 목차 (1)
      • 기출문제 (1)
      • 1과목 - 소프트웨어 설계 (6)
      • 2과목 - 소프트웨어 개발 (7)
      • 3과목 - 데이터베이스 구축 (8)
      • 4과목 - 프로그래밍 언어 활용 (7)
      • 5과목 - 정보시스템 구축 관리 (10)
    • 2020 정보처리기사 실기 (31)
      • 목차 (4)
      • 기출예상문제 (19)
      • 실기요약 (8)
    • 빅데이터분석기사 필기 (4)
      • 목차 (0)
      • 필기 요약 (3)
    • 전기 공학 (1)
      • CIM (1)
    • 산업자동화시스템 (3)
      • SCADA (1)
      • OPC UA (2)
    • 디자인패턴 (1)
    • 휴지통 (0)

공지사항

  • 공지사항/포스팅 예정 항목

최근 댓글

최근 글

전체 방문자
오늘
어제

티스토리

hELLO · Designed By 정상우.
기은P

시간이 멈추는 장소

[React] Redux 사용하기(1) - 개념과 흐름
FrontEnd/React 심화

[React] Redux 사용하기(1) - 개념과 흐름

2022. 6. 21. 11:06
반응형

1. 개요

React 기반으로 웹 프로젝트를 개발할때, 컴포넌트의 상태 관리를 해야할 경우가 생기는데, 이때 사용하는 것이 Redux입니다. 리액트의 꽃이라고 할 수 있고, 처음 접하는 사람에게 굉장히 러닝 커브가 높은 부분입니다.(저도 그랬습니다.)

(상태 관리 하는 이유 : 리렌더링에 의한 자원 소모를 줄이기 위해서)

사실 Redux가 어렵기도 해서 사용하기 쉽게 라이브러리들이 개발이 되어서 MobX, xstate, recoil, zustand 등 여러가지 라이브러리가 등장하고, Redux를 굳이 사용하지 않아도 위 라이브러리로 간편하게 상태 관리를 할 수 있게 되었습니다.

하지만, 리액트 프로그래밍을 시작하는 사람으로서 어떤 맥락으로 상태관리가 이루어지는지 파악하는 것은 중요하다고 생각합니다.

 

 

2. 중요 키워드 및 개념

액션

 사용자에 의해서 상태의 변화(ex: 버튼을 눌렀을 경우)가 생길때 이것을 액션이 발생되었다고 말합니다.

아래와 같이 타입과 value로 이루어져있습니다. type은 무조건 들어가야하며 value는 자유롭게 작성해도 됩니다.

 

{
  type: "PUSH_BUTTON"
  button: "pushed"
}

// 혹은

{
  type: "PUSH_BUTTON"
  isToggle: true
}

 

 

 

액션 생성함수

 액션을 만드는 함수입니다. 파라미터(data)를 받아와서 액션 객체 형태로 리턴해서, 사용자가 사전에 지정한 액션을 호출할 수 있게 합니다.

export function pushButton(data) {
  return {
    type: "PUSH_BUTTON",
    data
  };
}

 

 

 

리듀서

 변화를 일으키는 함수입니다. useReducer()와 똑같은 형태를 가지고 있으며, 현재의 상태(state)와 전달받은 액션(action)을 파라미터로 받고, 새로운 상태의 값(return +-1, 증분된 값)을 반환합니다.

// 카운터 기능을 예로 들었을 경우입니다.
function counter(state, action) {
  switch (action.type) {
    case 'INCREASE':
      return state + 1;
    case 'DECREASE':
      return state - 1;
    default:
      return state;
  }
}

액션에서 지정한 type을 switch-case로 확인하고, 전달받은 state 파라미터에 +1또는 -1를 추가해서 반환합니다.

이 현재의 state와 반환되는 state가 가장 중요합니다.

먼저 아래 스토어(store)에 대해 확인하겠습니다.

 

 

 

스토어

 리덕스에서는 단 하나의 스토어를 만들게 되는데, 이 스토어 내부에는 현재의 앱 상태(state)와 리듀서(reducer)가 들어가 있습니다.

위와 같이 카운터를 만들었다고 가정하고, 리듀서 쪽에서 정의한 state를 다시 확인해보겠습니다.

카운터로 인해 숫자가 늘어나고 줄어드는 텍스트 박스(컴포넌트)가 있으며, 이 상태를 저희는 redux를 이용해 상태 관리를 하려고 합니다.

위 컴포넌트를 redux로 사용할 경우, 아래와 같이 useSelector()라는 함수를 이용해서 스토어(store)에 저장된 현재의 상태(state)를 가져와서 초기화를 해줍니다.

  const count = useSelector((state: RootState) => state.counter.count);
  
  return (
  	<div>{count}</div>
  )

저희가 +1버튼을 누르거나 -1버튼을 누를때, 디스패치(dispatch)라는 것을 통해 액션 생성함수를 호출하도록 합니다.

 

 

 

 

디스패치

 디스패치는 스토어(store)에서 제공하는 함수중의 하나로 액션을 발생시켜주는 도구입니다.

 const dispatch = useDispatch(); // 디스패치 함수를 가져옵니다

  // 각 액션들을 디스패치하는 함수들을 만들어줍니다
  const onIncrease = () => {
    dispatch(increase());
  };

  const onDecrease = () => {
    dispatch(decrease());
  };

위와 같이 디스패치 함수 안에 액션 생성함수를 지정하고, onIncrease()(액션 생성함수)를 호출하면, 액션 생성함수로 인해 액션이 생성되고, 그 다음 리듀서가 호출되며 현재의 상태(텍스트 박스의 숫자가 3이면 3, 혹은 19면 19)에 리듀서에서 지정한 return state +1이 반환되며, 이 값이 스토어(store)에 저장됩니다.

useSelector()는 스토어에 있는 값을 가져다가 텍스트 박스를 갱신시켜주게 되고, 결과적으로 +1이 된 값이 사용자에게 보여 지게 됩니다.

이 흐름!이 가장 중요하고 이 흐름을 이해하셨으면 리덕스를 다 이해하신 거라고 보면 됩니다.

원래라면 전체 코드를 딱 적고, 그 코드에 대한 설명을 하는게 편하긴 하지만, 리덕스 같은 경우는 전반적인 이해와 전체적인 흐름에 대한 이해가 필수적으로 들어가야 했기 때문에 이 글에 대해서는 흐름만 이해할 수 있도록 작성했습니다.

 

*위 그림에서 Middleware는 크게 중요하지 않기 때문에 그냥 넘어가셔도 무방합니다.

 

 

 

 

컴포넌트 쪽에서 작성한 전체코드는 아래와 같습니다.

const CounterContainer = (props: CounterContainerProps) => {
  // 상태를 조회합니다. 상태를 조회 할 때에는 state 의 타입을 RootState 로 지정해야합니다.
  const count = useSelector((state: RootState) => state.counter.count);
  const dispatch = useDispatch(); // 디스패치 함수를 가져옵니다

  // 각 액션들을 디스패치하는 함수들을 만들어줍니다
  const onIncrease = () => {
    dispatch(increase());
  };

  const onDecrease = () => {
    dispatch(decrease());
  };

  const onIncreaseBy = (diff: number) => {
    dispatch(increaseBy(diff));
  };

  return (
    <Counter
      count={count}
      onIncrease={onIncrease}
      onDecrease={onDecrease}
      onIncreaseBy={onIncreaseBy}
    />
  );
};

 

실제로 Redux를 사용해서 상태관리를 하는 부분에 대한 자세한 코드는 다음 글에서 작성하도록 하겠습니다.

 

반응형
저작자표시 변경금지 (새창열림)

'FrontEnd > React 심화' 카테고리의 다른 글

[React] Redux Toolkit 사용법  (1) 2022.09.19
[React] Redux 사용하기(2) - 카운터 구현  (0) 2022.06.21
[React] Immer (produce)  (0) 2022.04.04
[React] Async & Await란?  (0) 2022.03.07
[React] Promise란?  (0) 2022.03.07
    'FrontEnd/React 심화' 카테고리의 다른 글
    • [React] Redux Toolkit 사용법
    • [React] Redux 사용하기(2) - 카운터 구현
    • [React] Immer (produce)
    • [React] Async & Await란?
    기은P
    기은P
    기은P의 블로그 일상과 개발 관련 포스팅 #React #Typescript #Next #Nest https://github.com/kimdongjang

    티스토리툴바