🌐 Web/Redux

05. Redux를 이용한 애플리케이션 : state의 변화를 UI에 반영

dlalwl_jpg 2022. 9. 6. 10:52

이전시간에 우리는 action이 일어났을 때 그것을 dispatch에 통해 store에 전달하면 store가 우리가 작성한 reducer를 호출해 최종적인 state값을 결정한다는 것을 배웠다.

그러면 이제 state값이 바뀌면 UI도 바뀌어야 하는데 이때 render를 호출해야 한다.

즉, state이 바뀔 때마다 render가 통보 받아 그때마다 state값을 가져와 화면에 그려야 한다.


with-redux.html

<!DOCTYPE html>
<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>
        <dix id="red"></dix>
        <script>       
            //reducer는 기존의 state값과 action값을 받아야 해서 인자를 state, action 두 가지를 작성해야 한다.
            function reducer(state, action){
                console.log(state, action);
                if(state === undefined){ //state의 값이 정의되지 않았다는 것은 초기값이라는 의미
                    return {color:'yellow'} //초기값 리턴
                }

                var newState;

                if(action.type === 'CHANGE_COLOR'){
                    newState = Object.assign({}, state, {color:'red'}); //state 복제하고 복제된 state값에 red값을 준다.
                }

                return newState; 
            }
            //복붙한 주소에 의해 redux객체가 생성됨
            //createStore 입력값으로 reducer라는 것이 들어가야 한다.     
           var store = Redux.createStore(reducer); //store가 'store'라는 전역변수에 저장하여 애플리케이션 어디서든 실행 가능하도록 한다.
           
            console.log(store.getState()); //state값이 잘 저장 되었는지 확인할 때 getstate를 사용한다.
function red(){
    //red의 기본적인 css 색깔을 위에서 설정한 초기값 색깔로 지정한다.
    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="fire" onclick="
            
                store.dispatch({type:'CHANGE_COLOR', COLOR:'red'}); //store에 dispatch 함수를 호출해 type 객체를 주는데 이것을 반드시 있어야 한다.
            ">
        </div>
    `;
}
red();
        </script>
    </body>
</html>

위 코드에서 UI를 그려주는 red함수는 실행할 때마다 state값을 가져와 그에 따라 자신의 color값을 결정해준다.

따라서 언제든지 호출해도 되는 함수이다.

위 코드는 red();를 통해 강제로 호출하였는데, 이것을 state값이 바뀔 때마다(dispatch를 할 때마다) red 함수가 호출되도록 바꾸려면 어떻게 해야할까?

바로 subscribe에 render를 등록하면 된다. 그러면 dispatch가 state값을 바꾸고 red를 호출하도록 약속된다.

store.subscribe(red);

 

red함수 아래에 위 함수를 추가하면 fire 버튼을 누르면 배경색이 빨간색으로 바뀌게 된다.

state값이 yellow에서 red로 바뀌면서 UI에도 적용된 것을 확인할 수 있다.


추가로 파란색과 초록색도 추가해보자.

with-redux.html

<!DOCTYPE html>
<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>
        <dix id="red"></dix>
        <dix id="blue"></dix>
        <dix id="green"></dix>
        <script>       
            //reducer는 기존의 state값과 action값을 받아야 해서 인자를 state, action 두 가지를 작성해야 한다.
            function reducer(state, action){
                console.log(state, action);
                if(state === undefined){ //state의 값이 정의되지 않았다는 것은 초기값이라는 의미
                    return {color:'yellow'} //초기값 리턴
                }

                var newState;

                if(action.type === 'CHANGE_COLOR'){
                    newState = Object.assign({}, state, {color: action.color}); //state 복제하고 복제된 state값에 red값을 준다.
                }

                return newState; 
            }
            //복붙한 주소에 의해 redux객체가 생성됨
            //createStore 입력값으로 reducer라는 것이 들어가야 한다.     
           var store = Redux.createStore(reducer); //store가 'store'라는 전역변수에 저장하여 애플리케이션 어디서든 실행 가능하도록 한다.
           
            console.log(store.getState()); //state값이 잘 저장 되었는지 확인할 때 getstate를 사용한다.
function red(){
    //red의 기본적인 css 색깔을 위에서 설정한 초기값 색깔로 지정한다.
    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="fire" onclick="
            
                store.dispatch({type:'CHANGE_COLOR', color:'red'}); //store에 dispatch 함수를 호출해 type 객체를 주는데 이것을 반드시 있어야 한다.
            ">
        </div>
    `;
}
store.subscribe(red);
red();

function blue(){
   
    var state = store.getState();
    document.querySelector('#blue').innerHTML = `
        <div class="container" id="component_red" style="background-color:${state.color}"> 
            <h1>blue</h1>
            <input type="button" value="fire" onclick="
            
                store.dispatch({type:'CHANGE_COLOR', color:'blue'}); //store에 dispatch 함수를 호출해 type 객체를 주는데 이것을 반드시 있어야 한다.
            ">
        </div>
    `;
}
store.subscribe(blue);
blue();

function green(){
   
   var state = store.getState();
   document.querySelector('#green').innerHTML = `
       <div class="container" id="component_red" style="background-color:${state.color}"> 
           <h1>green</h1>
           <input type="button" value="fire" onclick="
           
               store.dispatch({type:'CHANGE_COLOR', color:'green'}); //store에 dispatch 함수를 호출해 type 객체를 주는데 이것을 반드시 있어야 한다.
           ">
       </div>
   `;
}
store.subscribe(green);
green();
        </script>
    </body>
</html>

결과화면


redux가 없을 때 vs redux가 있을 때

redux가 없을 때의 코드는 서로 강력하게 의존하고 있다.

따라서 새로운 conponent를 추가하면 기존에 있었던 component 전체를 다 업데이트해야 한다.

우리는 이러한 번거로움을 없애기 위해 redux를 사용한다.

redux라는 중계자를 통해 상태를 중앙집중적으로 관리할 수 있게 되면 각각의 부품들은 state를 dispatch해준다.

그리고 자신이 변화되어야 할 코드를 작성하고 그것을 store에 subscribe시켜 놓으면

state가 바뀔 떄마다 통보를 받기 때문에 UI를 바꿔줄 수 있게 된다. 

따라서 각 함수들은 다른 함수와 상관없이 자신에게만 집중하면 된다. 

 

강의 영상 - https://youtu.be/SnND3Fj3eJc