관리 메뉴

거니의 velog

(6) 리덕스를 사용하여 리액트 애플리케이션 상태 관리하기 1 본문

React/React_리액트 심화

(6) 리덕스를 사용하여 리액트 애플리케이션 상태 관리하기 1

Unlimited00 2023. 12. 13. 15:53

* 이번 장에서는 리덕스를 사용하여 리액트 애플리케이션 상태를 관리하는 방법을 알아보자. 소규모 프로젝트에서는 컴포넌트가 가진 state를 사용하는 것만으로도 충분하지만, 프로젝트의 규모가 커짐에 따라 상태 관리가 번거로워질 수 있다.

* 리액트 애플리케이션에서 리덕스를 사용하면, 상태 업데이트에 관한 로직을 모듈로 따로 분리하여 컴포넌트 파일과 별개로 관리할 수 있으므로 코드를 유지 보수하는 데 도움이 된다. 또한, 여러 컴포넌트에서 동일한 상태를 공유해야 할 때 매우 유용하며, 실제 업데이트가 필요한 컴포넌트만 리렌더링되도록 쉽게 최적화해 줄 수 있다.

* 앞에서 바닐라 자바스크립트 환경에서 리덕스를 사용할 때 스토어의 내장 함수인 store.dispatch와 store.subscribe 함수를 사용했다. 리액트 애플리케이션에서 리덕스를 사용할 때는 store 인스턴스를 직접 사용하기보다는 주로 react-redux라는 라이브러리에서 제공하는 유틸 함수(connect)와 컴포넌트(Provider)를 사용하여 리덕스 관련 작업을 처리한다.

* 이번 실습은 다음과 같은 흐름으로 진행된다.


1. 작업 환경 설정

* 리액트 프로젝트를 생성하고, 해당 프로젝트에 리덕스를 적용해 보자.

* 먼저 create-react-app을 사용하여 새로운 리액트 프로젝트를 생성하자.

$ yarn create react-app react-redux-tutorial

* 생성한 프로젝트 디렉터리에 yarn 명령어를 사용하여 리덕스와 react-redux 라이브러리를 설치하자.

$ cd react-redux-tutorial
$ yarn add redux react-redux

* Prettier를 적용하고 싶다면 디렉터리에 다음과 같이 .prettierrc 파일을 작성하자.

{
    "singleQuote": true,
    "semi": true,
    "useTabs": false,
    "tabWidth": 2,
    "trailingComma": "all",
    "printWidth": 80
}

2. UI 준비하기

* 리액트 프로젝트에서 리덕스를 사용할 때 가장 많이 사용하는 패턴은 프레젠테이셔널 컴포넌트와 컨테이너 컴포넌트를 분리하는 것이다. 여기서 프레젠테이셔널 컴포넌트란 주로 상태 관리가 이루어지지 않고, 그저 props를 받아 와서 화면에 UI를 보여 주기만 하는 컴포넌트를 말한다. 이와 달리 컨테이너 컴포넌트는 리덕스와 연동되어 있는 컴포넌트로, 리덕스로부터 상태를 받아 오기도 하고 리덕스 스토어에 액션을 디스패치하기도 한다.

* 이러한 패턴은 리덕스를 사용하는 데 필수 사항은 아니다. 다만 이 패턴을 사용하면 코드의 재사용성도 높아지고, 관심사의 분리가 이루어져 UI를 작성할 때 좀 더 집중할 수 있다.

* 이 장의 프로젝트에서는 이 패턴을 사용하여 코드를 작성해 볼 것이다. UI에 관련된 프레젠테이셔널 컴포넌트는 src/components 경로에 저장하고, 리덕스와 연동된 컨테이너 컴포넌트는 src/containers 컴포넌트에 작성한다.


(1) 카운터 컴포넌트 만들기

* 숫자를 더하고 뺄 수 있는 카운터 컴포넌트를 만들어 보자. components 디렉터리를 생성한 뒤, 그 안에 Counter 컴포넌트를 작성하자.

import React from 'react';

const Counter = ({ number, onIncrease, onDecrease }) => {
  return (
    <div>
      <h1>{number}</h1>
      <div>
        <button onClick={onIncrease}>+1</button>
        <button onClick={onDecrease}>-1</button>
      </div>
    </div>
  );
};

export default Counter;

* 이제 이 컴포넌트를 App 컴포넌트에서 렌더링한다.

[App.js]

import React from 'react';
import Counter from './components/Counter';

const App = () => {
  return (
    <div>
      <Counter number={0} />
    </div>
  );
};

export default App;

* yarn start 명령어를 입력해서 개발 서버를 실행해 보자. 다음과 같이 카운터 컴포넌트가 나타날 것이다.


(2) 할 일 목록 컴포넌트 만들기

* 이번에는 해야 할 일을 추가하고, 체크하고, 삭제할 수 있는 할 일 목록 컴포넌트를 만들어 보겠다. components 디렉터리에 Todos 컴포넌트를 다음과 같이 작성하자.

import React from 'react';

const TodoItem = ({ todo, onToggle, onRemove }) => {
  return (
    <div>
      <input type="checkbox" />
      <span>예제 텍스트</span>
      <button>삭제</button>
    </div>
  );
};

const Todos = ({
  input, // 인풋에 입력하는 텍스트
  todos, // 할 일 목록이 들어 있는 객체
  onChangeInput,
  onInsert,
  onToggle,
  onRemove,
}) => {
  const onSubmit = (e) => {
    e.preventDefault();
  };
  return (
    <div>
      <form onSubmit={onSubmit}>
        <input />
        <button type="submit">등록</button>
      </form>
      <div>
        <TodoItem />
        <TodoItem />
        <TodoItem />
        <TodoItem />
        <TodoItem />
      </div>
    </div>
  );
};

export default Todos;

* 파일 하나에 두 컴포넌트를 선언했다. 취향에 따라 Todos 컴포넌트와 TodoItem 컴포넌트를 파일 두 개로 분리해도 되고, 위 코드 처럼 파일 하나에 작성해도 무방하다.

* 위 컴포넌트들이 받아 오는 props는 나중에 사용하겠다.

* 컴포넌트를 다 만들었다면 App 컴포넌트에서 카운터 아래에 렌더링해 주자. hr 태그를 사용하여 사이에 구분선을 그려 줄 것이다.

[App.js]

import React from 'react';
import Counter from './components/Counter';
import Todos from './components/Todos';

const App = () => {
  return (
    <div>
      <Counter number={0} />
      <hr />
      <Todos />
    </div>
  );
};

export default App;

할 일 목록 UI