본문 바로가기

스터디/React

[React] 강의 8주차 (1) - React _ Redux 만들기

[국비지원교육]  [패스트캠퍼스] React 강의 8주차 (1) - React _ Redux 만들기

[ React ]

- 구독 발행 모델

- 그럴듯 하게 모양내기

- 비동기 처럼 보이는 동기의 한계


 

1. 구독 발행 모델 

 
 
(app.js)
 
function createStore() {
    let state;

    function send() {
        state = worker(state);
    }

    function getState() {
        return state;
    }

    return {
        send,
        getState
    };
}


function worker(state = { count: 0 }) { //state가 아무것도 안들어오면 객체를 만들자
    //do something
    return { ...state, count: state.count + 1 }; //새로운 객체를 만들어 리턴 (얕은 복사)
}

const store = createStore(worker);
store.send();
console.log(store.getState()); //{ count: 1 }
store.send();
console.log(store.getState()); //{ count: 2 }

 

[구독 발행 모델 구현] : 내가 어떤 함수를 줄테니 데이터가 바뀌면 그 함수를 호출해줘
여러 개의 함수가 구독하고 있을 테니 구독 함수들을 배열로 저장해야함.
 
위의 코드를 아래와 같이 수정합니다.
 
function createStore() {
    let state;
    let handlers = [];

    function send(action) {
        state = worker(state, action);
        handlers.forEach(handler => handler());
    }

    function subscribe(handler) {
        handlers.push(handler);
    }

    function getState() {
        return state;
    }

    return {
        send,
        getState,
        subscribe
    };
}


function worker(state = { count: 0 }, action) { //state가 아무것도 안들어오면 객체를 만들자
    //do something
    switch(action.type){
        case 'increase':
            return { ...state, count: state.count + 1 };
        default:
            return { ...state };
    }
}

const store = createStore(worker);

store.subscribe(function() { //store함수를 구독
    console.log(store.getState());
})
store.send({type: 'increase' }); //{ count: 1 }
store.send({type: 'increase' }); //{ count: 2 }
store.send({type: 'increase' }); //{ count: 3 }

 

 

2. 그럴듯 하게 모양내기

스트럭쳐가 번거롭고 수정이 많지만, 상태를 바꾸는 코드가 복잡하지 않고 간단해지는 장점이있다
앱이 아무리 커져도 상태와 같은 변경사항은 상태에서 수정하면됩니다.
하지만 상태가 추가되고 변경될때에 변경되는 부분이 많아서 번거롭기는 합니다.

 

(index.html)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>그럴듯하게 모양내기</title>
</head>
<body>
    <script src="app.js" type="module"></script>
</body>
</html>

 

 

(app.js)

import { createStore, actionCreator } from './redux.js';
import { reducer } from './reducer.js';
import * as Actions from './actions.js';

const store = createStore(reducer);

store.subscribe(function() { //store함수를 구독
    console.log(store.getState());
})
store.dispath(Actions.increase()); //{ count: 1 }
store.dispath(Actions.increase()); //{ count: 2 }
store.dispath(Actions.increase()); //{ count: 3 }
store.dispath(Actions.decrease()); //{ count: 2 }
store.dispath(Actions.reset()); //{ count: 0 }

 

(actions.js)

import { actionCreator } from './redux.js';
import { INCREASE, DECREASE, RESET } from './action-type.js';

export const increase = () => actionCreator(INCREASE);
export const decrease = () => actionCreator(DECREASE);
export const reset = () => actionCreator(RESET);

 

(action-type.js)

export const INCREASE = 'increase';
export const DECREASE = 'decrease';
export const RESET = 'reset';

 

(reducer.js)

import * as ActionType from './action-type.js';

const InitializeStae = { count : 0 }; //초기값
export function reducer(state = InitializeStae, action) { //state가 아무것도 안들어오면 객체를 만들자
    //do something
    switch(action.type){
        case ActionType.INCREASE:
            return { ...state, count: state.count + 1 };
        case ActionType.DECREASE:
            return { ...state, count: state.count - 1 };
        case ActionType.RESET:
            return { ...state, count: 0 };
        default:
            return { ...state };
    }
}

 

(redux.js)

export const actionCreator = type => payload => ({
    type,
    payload,
});

export function createStore(reducer) {
    let state;
    let handlers = [];

    function dispath(action) {
        state = reducer(state, action);
        handlers.forEach(handler => handler());
    }

    function subscribe(handler) {
        handlers.push(handler);
    }

    function getState() {
        return state;
    }

    return {
        dispath,
        getState,
        subscribe
    };
}

 

3. 비동기 처럼 보이는 동기의 한계
import { createStore } from './redux.js';
import { reducer } from './reducer.js';
import * as Actions from './actions.js';

const store = createStore(reducer);

store.subscribe(function() { //store함수를 구독
    console.log('sub => ', store.getState());
})
store.dispath(Actions.increase()); //{ count: 1 }
console.log('dis =>', store.getState());
store.dispath(Actions.increase()); //{ count: 2 }
console.log('dis =>', store.getState());
store.dispath(Actions.increase()); //{ count: 3 }
console.log('dis =>', store.getState());
store.dispath(Actions.decrease()); //{ count: 2 }
console.log('dis =>', store.getState());
store.dispath(Actions.reset()); //{ count: 0 }
console.log('dis =>', store.getState());

 

 

순서대로 나타나는 동기코드를 볼 수 있습니다.

리덕스는 동기적인 코드로 작성이 되있습니다. 
만약 reset Action이 reducer 안으로 들어가면, 작동할지 않할지 곰곰히 생각해보자! 

(reducer.js)

import * as ActionType from './action-type.js';

const InitializeState = { count : 0 }; //초기값

export function reducer(state = InitializeState, action) { //state가 아무것도 안들어오면 객체를 만들자
    //do something
    switch(action.type){
        case ActionType.INCREASE:
            return { ...state, count: state.count + 1 };
        case ActionType.DECREASE:
            return { ...state, count: state.count - 1 };
        case ActionType.RESET:
            fetch('/reset')
                .then(response => response.json())
                .then(result => {
                    if(result) {
                        return { ...state, count: 0 };
                    }
                })
        default:
            return { ...state };
    } 
}
 

 


[참고사이트]

1) grommet 리액트 UI 프레임웍

https://v2.grommet.io/

2) uuid 

https://www.npmjs.com/package/uuid  

3) styled-components

https://styled-components.com/

 

4) flux 아키텍처

https://facebook.github.io/flux/docs/in-depth-overview

https://velog.io/@alskt0419/FLUX-%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90%EB%9E%80

 

FLUX 아키텍쳐란?

해당 게시글에서는 Flux 구조에 대해 다룹니다. MVC 아키텍쳐의 한계 우선 Flux 아케텍쳐에 대해 알아보기 전에 MVC 아키텍쳐에 대해 간단히 얘기해 보겠습니다. Flux 아키텍쳐는 Facebook에서 개발한

velog.io

 

5) redux toolkit

https://redux-toolkit.js.org/

 

Redux Toolkit | Redux Toolkit

The official, opinionated, batteries-included toolset for efficient Redux development

redux-toolkit.js.org

 

6)React에서 Redux가 왜 필요할까?

https://devlog-h.tistory.com/26

 

React에서 Redux가 왜 필요할까?

안녕하세요! 휴몬랩 초보 개발자 수달입니다. :) 리액트를 이용한 웹을 개발하다 보면, State 관리에서 빈번한 오류 발생과 현재의 값 확인이 매우 복잡한 경우가 존재합니다. props와 state를 사용하

devlog-h.tistory.com

 

7)[React] Hook 동작(구현) 원리 간단히 알아보기

https://it-eldorado.tistory.com/155

 

[React] Hook 동작(구현) 원리 간단히 알아보기

요즘에는 React로 개발할 때 클래스를 많이 사용하지 않는 듯하다. React 16.8 버전부터 도입된 Hook API가 상당한 인기를 얻고 있기 때문이다. 필자 역시도 React를 처음 공부할 때는 클래스 컴포넌트를

it-eldorado.tistory.com

 


[ React ]

문제 정의 어떤 코드가 상태를 어디서 바꾸나

- 해결책 만들기

- 구독 발행 모델

- 그럴듯 하게 모양내기

- 비동기 처럼 보이는 동기의 한계