[Front-End] Redux란?

Joosi_Cool·2023년 1월 7일
1

Frond-End

목록 보기
3/8
post-thumbnail

What is Redux?

개발 공부를 하다보면 Redux에 대한 이야기는 필수적으로 나온다.
이번에는 Redux가 정확히 무엇이며, 우리가 왜 이를 사용해야되는지 알아보려한다. 더 나아가 하나의 사이트를 만들면서 어떻게 이를 사용할 수 있을지 한번 알아보자.

Redux란? 이에 대한 공식문서에 들어가보면 Javascript를 위한 예측가능한 상태 저장소라고 한다.

여기서 중요한 말은 예측가능한 , 과 상태 저장소 이다. 이에 대한 건 뒤에 좀 더 자세히 다루어보고, 들어가기 전에 쉽게 Redux를 풀어보자

우리가 component에서 여러 변수와 여러함수를 사용한다. 그럴때 각각의 컴포넌트들이 어떤 변수를 통해 공유되어 지는 상황이 있을 것이다.
이럴때, 각각마다 변수를 선언해서 따로 관리하는 것이 아니라, 한 곳에 몰아놓고 관리 하는 것이다. Redux 에 대해 더 깊게 알아보기 전에 약간의 길이라도 잡았으면 하는 마음에 쉽게 풀어보았다. 이 말이 이해가 안가도 좋다.
Redux를 우선 변수 저장소 라고 생각하자. 그리고 차근차근 들어보자.

우선 우리가 왜 Redux 에 대해 공부해야하며, 이를 왜들 그렇게 언급을 하는지 알아보자.


Why should we use Redux?

각각의 네모를 클릭 시에 모든 네모의 색이 클릭한 네모의 색을 공유하는 웹 사이트를 한번 만든다고 가정해보자.

아래 그림을 한번 봐보자.

우리가 이 두개의 네모의 배경색을 공유하려면 몇개의 logic이 필요할까?
A의 경우, A를 누르면 자기 자신을 blue로 바꾸는 logic하나, B를 blue로 바꿔줄 logic 한개가 필요하다. B도 마찬가지로 red색으로 바꾸기 위해 두개가 필요하다.
그렇다면 총 4개가 필요하다.
네모의 개수를 좀 늘려보자.

네모가 3개가 된 경우, 몇개의 logic이 필요할까?
A의 경우, A를 누르면 자기자신을 바꾸는 logic, B를 바꾸는 logic, C를 바꾸는 logic 총 3개가 필요하다. B,C도 마찬가지로 3개, 총 9개가 필요하다. 이제 무슨 말을 하려는지 이해했을 것이다.

네모가 100개가 되었다면 logic이 몇개가 필요할까?
-> 100 * 100 = 10,000개 필요하다.....
생각만 해도 머리가 아파진다.


위에서 말한 사이트를 아래와 같이 만들어보았다.
1. red 상자, 2. green 상자, 3. blue 상자이며, 각각을 누르면 그 상자의 색깔로 모두 변하게 되는 사이트이다.
아래 예시 코드르 봐보자.

<html>
  <body>
    <style>
      .container {
        border: 5px solid black;
        padding: 10px;
      }
    </style>
    <div id="red"></div>
    <div id="green"></div>
    <div id="blue"></div>

    <script>
      function red() {
        document.querySelector("#red").innerHTML = `
          <div class = "container" id ="component_red">
            <h1>red</h1>
            <input type="button" value = "change" onClick ="
            document.querySelector('#component_red').style.background = 'red';
            document.querySelector('#component_green').style.background = 'red';
            document.querySelector('#component_blue').style.background = 'red';
            "
          </div>  
        `;
      }
      red();

      function green() {
        document.querySelector("#green").innerHTML = `
          <div class = "container" id ="component_green">
            <h1>green</h1>
            <input type="button" value = "change" onClick ="
            document.querySelector('#component_red').style.background = 'green';
            document.querySelector('#component_green').style.background = 'green';
            document.querySelector('#component_blue').style.background = 'green';
            "
          </div>  
        `;
      }
      green();

      function blue() {
        document.querySelector("#blue").innerHTML = `
          <div class = "container" id ="component_blue">
            <h1>blue</h1>
            <input type="button" value = "change" onClick ="
            document.querySelector('#component_red').style.background = 'blue';
            document.querySelector('#component_green').style.background = 'blue';
            document.querySelector('#component_blue').style.background = 'blue';
            "
          </div>  
        `;
      }
      blue();
    </script>
  </body>
</html>

보면 알 수 있듯이 상자를 3개만 만들었는데도 코드가 복잡해지고 document.querySelector('#component_red').style.background = 'blue'; 이러한 총 9개의 logic이 필요한 것을 볼 수 있다. 여기서 문제가 발생한다.

궁극적인 Redux 사용 이유

우리가 하나의 서비스를 만들어내기 위해 여러 component들을 만들어낸다.

위에 그림으로 예를 들어보자. 만약 child Component4의 test라는 변수를 child Component5 라는 곳에서 쓰고 싶다면 어떻게 해야 될까? 아래와 같이 props를 넘겨줘야 할 것이다.

child Component4 -> child Component1 -> Parent Component
-> child Component2 -> child Component5

후... 너무 복잡하다.....

요즘 시대에 사용자와 상호작용 하는 서비스가 많아지고, 각각의 컴포넌트들이 상호작용하는 것은 매우 자주 일어나고 있다. 따라서 위와 같이 어떤 값(state)를 관리를 해야할 때가 필수적이다. 그럴때마다 props로 값들을 전달해주며, 값을 바꿔주기 위해 각각 컴포넌트마다 거기에 맞춘 logic(함수)들을 만들어낼 것인가? 그때마다 이런식으로 코드를 짤 것인가?

이때 발생하는 것이 복잡성 의 문제이다. 프로그래밍 개발에 있어서 이 복잡성 은 코드를 개발하기에도, 수정하기에도 굉장히 어려워진다.


이 때문에 나온 것이 Redux이다.

아래 그림을 참고하면 Redux가 어떻게 이루어지는지 알 수 있다.

우리는 중간에 있는 검정색 동그라미 처럼 state 를 관리하는 하나의 저장소를 만들어낼 것이다. 이는 Redux에서 store라고 부른다. 용어는 뒤에서 좀 더 다루기로 하고 넘어가보겠다.

만약 C를 클릭한다면 어떻게 이루어지는가?
먼저 C에서 클릭하면 저장소에 변화를 전달한다. 그렇다면 저장소에선 A,B에게 값이 변경되었으니, 알아서들 변화해! 라고 한다.
이렇다면 몇 개의 logic이 필요할까?
C 기준으로 클릭시에 변화를 전달해주는 logic 하나, 저장소에서 값이 변화되었을떄, 자기자신을 변화하는 logic 하나두개 가 필요하다.
따라서 A,B,C 총 3개 일때는 2*3=6 개가 필요하다.

그렇다면 100개 라면? 그렇다 모두 2 * 100 =200개만이 필요하다.
이전엔 10,000개가 필요하던게 200개로 줄었다.

또한 store에서 저장되어진 데이터(state) 같은 값을 각각의 컴포넌트에서 props같은 과정없이 바로 불러와서 쓸 수 있다. 이렇게 된다면 한쪽에서 이 state를 변화시키면 다른 컴포넌트에서도 바로 렌더링이 이루어진다.

Redux를 사용하기 전과 차이가 느껴지는가?

이렇듯 Redux는 state를 Store라는 한 곳에 몰아놓고 관리한다. 그리고 각각의 component에서 이를 가져다가 쓰는 방식이다.


How to use Redux

이제 왜 써야 하는지 느꼈다면, 이를 어떻게 쓸까?
쓰는 방법에 들어가기 전에 Redux가 어떻게 사용되는지와 중요한 용어들에 대해 알아보도록 하자
아래 그림 예시(생활코딩 자료 참고)을 보면서 아래 용어를 공부해보자.

Redux 필수 용어 정리

1. Store란?

정보(state)가 저장되는 곳을 말한다. 우리가 공유하고 싶어하는 값들을 저장해놓는다. 여기에 저장되어 있는 값들은 우리가 마음대로 접근할 수 없다. 접근하는 방법은 따로 정해져있는데 이를 이용해야만 가능하다. 이 떄문에 여러 장점들이 있다. 이 장점에 대해선 뒤에서 알아보겠다. 여기선 좀 더 언어 대한 개념을 알아보자. 앞서 공유되어지는 값을 몰아놓고 관리한다고 했는데, 몰아놓는 곳이 store 이다.

2. reducer란?

Redux에서 이 개념이 제일 어렵고 중요하다.
reducer는 이전 값과 action값을 참고하여 업데이트 시키고 싶은 state를 리턴한다.
쉽게 말하면 이전 값더하기 해줘!!라는 action을 가지고 이전 값에 더하기라는 action을 취해 더해진 값을 return 해줘서 이를 store에 저장해놓는 것이다.
이전 값 + 더해줘! => 새로운 state

3. reder란?

reder는 우리가 사용자들에게 보여주는 UI부분이다. 우리가 React나 HTML 등등으로 만든 UI부분을 말한다.

4. getState

이 함수는 store에 저장되어있는 값을 불러오는 역할을 합니다. store에 저장되어진 값들은 마음대로 가져오거나 조정할 수 없다고 했는데, 값을 얻어오고 싶을때 쓰는 함수입니다.

5. subscribe

구독이라는 뜻을 가진 이 함수는 store에 값이 변화되어질때, 이를 UI에 반영시키는 일을 한다.
만약, store에 있는 값이 변화될때 UI부분을 변화시키고 싶다면 UI를 담고 있는 reder함수를 인자로 넣으면 store의 값에 맞춰서 UI가 업데이트 된다. subscibe(render함수)를 넣으면 된다.

6. dispatch

버튼을 클릭한다던지에 action이 발생했을때, 이 dispatch는 두가지 일을 한다.
1. reducer를 호출시켜서 store에 있는 state를 변화시킨다.
2. subscribe에 등록된 render함수의 UI를 업데이트 시킨다.

정리

위에 용어들을 들었을때, 너무 추상적이고 무슨말인지 이해 못했을 것이라고 생각한다. 사진을 가져오면서 예시를 들어보려한다.

자 이제 red 영역의 chage부분을 눌러서 각각의 영역을 red로 바꾸려 할 것이다.
1. 현재 store에는 초기값 {color = "yellow"} 라고 저장되어있다.
2. red의 change버튼 클릭!! (action) -> dispatch발동
3. dispatch -> reducer를 통해서 store에 있는 {color = "yellow"} -> {color = "red"} 로 변경
4. dispatch -> subscribe에 있는 render()함수를 모두 실행
이때, render함수는 red 영역, green영역, blue 영역이 된다.
이를 실행하기 전에 subscribe에는 위에 세개의 render 함수가 담겨있다.
5. render함수가 실행되면서 getState를 통해서 업데이트 된 값을 가져오고 이를 사용자들에게 보여주게 된다.

이런식의 구조가 된다.

Redux 활용 방법

구조가 이해가 되었다면 각각이 어떻게 만들어지는지 코드를 참고하면서 봐보자.

1. Store

   var store = Redux.createStore(reducer);

이 코드는 store라는 저장소를 하나 생성한 것이고, store의 값을 바꿔주기 위해 항상 reducer이라는 함수를 하나 인자로 가지고 있어야 한다.

2. reducer

      function reducer(state, action) {
        var newState;
        if (action.type === "CHANGE_COLOR") {
          newState = Object.assign({}, state, { color: action.color });
        }
        return newState;
      }

이 부분이 매우 중요하다. reducer이전 값인 state와 바꿔달라는 요청인 action값 두개를 받게 된다.
reducer가 실행되면 새로운 state를 리턴하게 되고 이를 store에 저장해둔다.

3. reder + getState + dispatch

function red() {
    var state = store.getState();
    document.querySelector("#red").innerHTML = `
      <div class = "container" id ="component_red" 
      style="background-color:${state.color}">
        <h1>red</h1>
        <input type="button" value = "change" onClick ="
              store.dispatch({type:'CHANGE_COLOR',color:'red'});
            "
      </div>  
        `;
      }

render 부분에서 중요한건 getState, dispatch이다. store에서 getState()를 통해 state값을 불러오고, 이를 reder부분에 적용시키고 있다. 또한 버튼을 클릭시에 store에 dispatch를 발동시키는 것을 볼 수 있다.
앞써 말한 reducer에 두 인자값중에 action 값을 전달해주어야 한다. 이때 중요한 점이 type을 전달해주어야 한다. 이를 가지고 여러함수를 만들어낼 수 있다.
1. a type => 색을 이걸로 바꿔줘!!
2. b type => 박스 크기를 이만큼 키워줘!!

4. subscribe

 store.subscribe(red);

이는 간단하게 store에 원하는 reder를 인자로 주어, subscribe 시키면 된다.

총 코드

위를 바탕으로 각각의 네모를 클릭 시에 모든 네모의 색이 클릭한 네모의 색을 공유하는 웹 사이트를 만든다면 아래와 같다.

<html>
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.2.0/redux.js"></script>
  </head>
  <body>
    <style>
      .container {
        border: 5px solid black;
        padding: 10px;
      }
    </style>
    <div id="red"></div>
    <div id="green"></div>
    <div id="blue"></div>

    <script>
      function reducer(state, action) {
        console.log(state, action);
        if (state === undefined) {
          return { color: "yellow" };
        }
        var newState;
        if (action.type === "CHANGE_COLOR") {
          newState = Object.assign({}, state, { color: action.color });
        }

        return newState;
      }

      var store = Redux.createStore(reducer);

      function red() {
        var state = store.getState();
        document.querySelector("#red").innerHTML = `
          <div class = "container" id ="component_red" 
          style="background-color:${state.color}">
            <h1>red</h1>
            <input type="button" value = "change" onClick ="
              store.dispatch({type:'CHANGE_COLOR',color:'red'});
            "
          </div>  
        `;
      }

      function green() {
        var state = store.getState();
        document.querySelector("#green").innerHTML = `
          <div class = "container" id ="component_green" 
          style="background-color:${state.color}">
            <h1>green</h1>
            <input type="button" value = "change" onClick ="
              store.dispatch({type:'CHANGE_COLOR',color:'green'});
            "
          </div>  
        `;
      }

      function blue() {
        var state = store.getState();
        document.querySelector("#blue").innerHTML = `
          <div class = "container" id ="component_blue" 
          style="background-color:${state.color}">
            <h1>blue</h1>
            <input type="button" value = "change" onClick ="
              store.dispatch({type:'CHANGE_COLOR',color:'blue'});
            "
          </div>  
        `;
      }

      store.subscribe(red);
      red();
      store.subscribe(green);
      green();
      store.subscribe(blue);
      blue();
    </script>
  </body>
</html>

위의 코드를 보면 render 부분 UI부분이 많은것이지, 실제로 보면 확실히 코드에서의 logic 이 줄었다. getState를 통해 값 color 값을 받아오는 logic 하나, 클릭 시에 action을 보내주는 dispatch 두개 뿐인 것이다.

정리

Redux가 많이 어려운 내용이 있다. 하지만 간단하게 생각하자.
이를 정리하면 공유 변수 관리 시스템 이라고 정리 하고 싶다. 여러 컴포넌트에서 store를 통해 이 변수를 공유할 수 있다. 또한 reducer 만을 통해서 값의 변화를 줄 수 있다. 이 점이 굉장히 중요한데, 이렇게 되면 관리하기 매우 쉬워진다. 코드를 짜다보면 변수에 값이 매우 이상할 때가 있다. 하지만 Redux를 쓰면 이때 오류를 찾기에 훨씬 쉬워진다. 왜? reducer만을 가지고 state를 바꾸기 때문이다. 이래서 예측가능한 이라는 단어가 붙는 것이다. reducer만을 가지고 state를 관리하기 때문에 값 변화에 대한 예측이 쉬워진다. 그래서 Redux를 예측가능한 상태 저장소라고 하는 것이다.


이처럼 Redux는 우리가 개발할때, 변수에 대해 관리를 수월하게 해주는 React Library이다.

참고

  1. 생활코딩 유튜브
    https://www.youtube.com/watch?v=Jr9i3Lgb5Qc&list=PLuHgQVnccGMB-iGMgONoRPArZfjRuRNVc&index=1

  2. 리덕스(Redux)란 무엇일까? - blog
    https://chanhuiseok.github.io/posts/redux-1/

profile
집돌이 FE개발자의 노트

0개의 댓글