As i wish

[React 틱 택 토] Redux - React 프로젝트 세팅 본문

React JS

[React 틱 택 토] Redux - React 프로젝트 세팅

어면태 2019. 7. 18. 11:46

안녕하세요. 엄티 입니다.

오늘도 역시 리액트 포스팅을 해보겠습니다.

저의 리액트 포스팅은 '제로초' 님의 웹게임 강좌를 바탕으로 포스팅 합니다.

 

제로초 님의 웹게임 강좌

 

리액트 무료 강좌(웹게임) - YouTube

 

www.youtube.com

 

오늘은 Redux 를 적용해 보겠습니다.

일단 개념이 처음에는 잡기 힙든데 몇번 사용하다가 익숙해지면 정말 편한 라이브러이입니다.

한마디로 쉽게 정의하면 '상태 관리 라이브러리' 라고 할 수 있죠.

 

리덕스를 왜 쓸까?

 

리덕스(Redux)를 왜 쓸까? 그리고 리덕스를 편하게 사용하기 위한 발악 (ii) | VELOPERT.LOG

이 포스트는 이어지는 튜토리얼 입니다. 1편 을 먼저 읽고 오시길 바랍니다. 리덕스의 3가지 규칙 리덕스를 프로젝트에서 사용하게 될 때 알아둬야 할 3가지 규칙이 있습니다. 1. 하나의 애플리케이션 안에는 하나의 스토어가 있습니다. 하나의 애플리케이션에선 단 한개의 스토어를 만들어서 사용합니다. 사실, 권장되지는 않습니다. 여러개의 스토어를 만들고 싶다면 만들 수는 있습니다. 특정 업데이트가 너무 빈번하게 일어나거나, 애플리케이션의 특정 부분을 완전히 분

velopert.com

리덕스 소개 및 개념정리

 

Redux (1) 소개 및 개념정리

1-1. 리덕스 소개 리덕스는, 가장 사용률이 높은 상태관리 라이브러리입니다. 리덕스를 사용하면, 여러분이 만들게 될 컴포넌트들의 상태 관련 로직들을 다른 파일들로 분리시켜서 더욱 효율적으로 관리 할 수 있습니다. 또한, 컴포넌트끼리 상태를 공유하게 될 때 여러 컴포넌트를 거치지 않고도 손쉽게 상태 값을 전달 할 수 있습니다. 추가적으로, 리덕스의 미들...

velog.io

이런 Redux 를 React에 적용해 보겠습니다.

한가지 확실히 아셔야 할것이 Redux 는 절대 React의 것이 아닙니다.

Redux란 개념을 어떻게 보면 Normal JS, Angular JS, Vue JS 등 다양한 프레임워크에 적용 할 수 있는데

대부분 React 와 Vue에 적용합니다. 이는 두 프레임워크는 상태가 변화는 것을 바탕으로 동작하기 때문이죠.

쉽게 말해 Flux 패턴을 구현하기 위해 Redux 를 적용하면 쉽게, 유용하게 쓸 수 있기 때문이죠.

 

Flux 와 Redux

 

WebFrameworks.kr - Flux와 Redux

Flux와 Redux 이 글에서는 Facebook에서 React와 함께 소개한 Flux 아키텍처에 대해 알아보고 Flux를 구현한 Redux 라이브러리를 살펴본 후 이를 적용한 간단한 React 애플리케이션을 작성해보겠다. 본문에 사용된 코드는 ​ES2015의 기능을 사용하고 있으므로 ES2015에 익숙하지 않다면 이재호님이 작성한 ES2015와 React를 먼저 읽으면 좋다. MVC 아키텍처의 한계 애플리케이션을 작성해 본 개발자라면 아마 적어도 한

webframeworks.kr

Redux 공식 문서

 

Read Me · Redux

results matching "" No results matching ""

deminoth.github.io

무튼 이정도로 개념을 잡으면 되겠습니다.

또한 만약 더 알고 싶으시면 검색을 통하면 엄청난 양의 데이터들이 나옵니다.

 

오늘 만들 게임은 틱택토 게임으로 삼목이라고 생각하시면 됩니다.

이런식으로 가로, 세로, 대각선으로 세줄을 완성 하면 끝나는 게임이죠.

이를 Redux 를 사용해서 구현해 보겠습니다.

일단 프로젝트를 만들어 보죠

 

리액트 프로젝트 세팅

 

[React JS] 프로젝트 셋팅 및 webpack, hot loader적용

리액트 프로젝트를 수동으로 셋팅 할 때에 필요한 프로젝트 셋팅과 개발의 편의를 위한 웹팩 적용을 포스팅 해보겠습니다. 기존 포스팅 한것을 한곳에 모은 것이기 때문에 링크를 클릭하여 확인해 주시면 되겠습니..

eomtttttt-develop.tistory.com

 

이런식으로 기본적인 프로젝트 구조를 만들고 React Redux 를 사용해 보겠습니다.

그러기 위해선 몇가지 모듈을 설치해야하는데요.

 

$ npm install react-redx redux

redux 와 react 에서 redux 를 사용할 수 있게 해주는 모듈이죠.

 

일단 저는 기본적으로 actions.js, reducers.js, store.js 만들었습니다.

 

actions.js

actions 는 reducers로 전달 되는 액션을 의미합니다. 

저기 게임에서는 셀을 클릭하는 경우, 우승자를 선정, O->X -> O 처럼 턴을 바꿔주는 경우, 게임을 리셋 하는 경우 이정도가 될 수 있겠죠.

export const CLICK_CELL= 'CLICK_CELL';
export const SET_WINNER = 'SET_WINNER';
export const CHANGE_TURN = 'CHANGE_TURN';
export const RESET_GAME = 'RESET_GAME';

export const clickCell = (rowIndex, columnIndex, turn) => {
  return {
    type: CLICK_CELL,
    rowIndex: rowIndex,
    columnIndex: columnIndex,
    turn: turn
  };
};

export const setWinner = (winner) => {
  return {
    type: SET_WINNER,
    winner: winner
  };
};

export const changeTurn = () => {
  return {
    type: CHANGE_TURN
  };
};

export const resetGame = () => {
  return {
    type: RESET_GAME
  };
};

중요한 점은 action 함수에는 반드시 type이 포함되어야 하고 그 외에는 커스텀하게 구성 할 수 있습니다.

 

두 번째로 reducers는 액션을 받았을 때에 해야할 일들을 설정해주는 곳이죠.

때에 따라 state를 바꿔 줄 수도 있고, 비동기 통신을 하라고 말할 수도 있고 명령 같은거죠.

state를 한곳에 모아두기 때문에 처음에 언급 했던 '상태 관리' 가 가능해 지고 UI 적인 부분을 제외하고는 각 Component 에서는 state 를 사용할 필요가 없게 되죠.(후에 언급하겠지만 각 Component 에서는 props 를 통해서 정보를 전달 받고 사용합니다.)

import * as actions from './actions';

const initState = {
  winner: '',
  turn: 'O',
  tableData: [
    ['', '', ''],
    ['', '', ''],
    ['', '', ''],
  ],
  recentCell: [-1, -1]
}

const reducer = (state=initState, action) => {
  switch (action.type) {
    case actions.CLICK_CELL:
      const tableData = [...state.tableData];
      tableData[action.rowIndex] = [...tableData[action.rowIndex]];
      tableData[action.rowIndex][action.columnIndex] = action.turn;
      return {
        ...state,
        tableData,
        recentCell: [action.rowIndex, action.columnIndex]
      };
    case actions.SET_WINNER:
    console.log('set winnner', state.turn);
      return {
        ...state,
        winner: 'Winner is ' + state.turn
      };
    case actions.CHANGE_TURN:
      return {
        ...state,
        turn: state.turn === 'O' ? 'X' : 'O'
      };
    case actions.RESET_GAME:
      return {
        ...state,
        turn: 'O',
        tableData: [
          ['', '', ''],
          ['', '', ''],
          ['', '', ''],
        ],
        recentCell: [-1, -1]
      };
    default:
      return state;
  }
};

export default reducer;

여기서 중요한 점은 state 에 불변성을 지켜야 한다는 점입니다. 이건 지난 React에 기본이 되는 부분이기 때문에 기존 Component 에서도 state 변경 시 불변성을 지켜줬기 때문에 크게 어려움은 없으나, 사실 저 코드를 보면 가독성이 떨어지는건 사실이죠.

그로 인하여 Immer 또는 Immutable 라이브러리를 사용 할 수 있는데 이는 추후에 포스팅 해보겠습니다.

 

마지막으로  store.js 입니다.

import { createStore } from 'redux';

import reducers from './reducers';

const create = () => {
    return createStore(reducers);
}

export default create;

딱히 어려운것은 없고 우리가 만든 reducers를 등록만 해주면 됩니다.

 

이렇게 등록된 store를 우리앱에 사용하기 위한 방법은 아주 간단합니다.

 

client.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';

import create from './store';
import { hot } from 'react-hot-loader/root';

import TicTacToe from './components/Tictactoe'; // Class 사용

const Store = create();
const Hot = hot(TicTacToe);

ReactDOM.render(
  <Provider store={Store}>
    <Hot />
  </Provider>,
  document.getElementById('root')
); // Class 사용

 

위처럼  react-redux 라이브러리에서 제공해주는 Provider 로 우리 앱(TicTacToe)을 감싸주기만 하면 끝입니다.

 

마지막으로 정리를 해보면

state 를 한 곳에 모아 놓고 각각의 Component 들이 state를 props로 받죠.

또한 action을 통하여 특정한 일을 했을 때에 reducers 들이 알아 채려서 각각에 맞게 state를 바꾸죠.

이러한 reducers를 store에 등록하죠.

그럼 state를 props로 받고 있던 Component 는 자동으로 그 변경사항을 적용하게 되죠.

 

위와 같이 되면 부모 -> 자식 -> 자식의 자식 -> 자식의 자식의 자식 ->... 처럼 event 나, props를 계속 넘겨줄 필요가 없어지죠.

 

이렇게 사용법 준비 포스팅을 끝내겠습니다.

실질적인 TicTacToe 포스팅, Redux 사용법은 다음 포스팅에 해보겠습니다.

 

Comments