react flux

저번까지는 리액트에 대해 알아 봤다.
저 정도만 이해해도 어느정도는 이해 했다고 봐도 될거 같다.
물론 이해정도만?
이번엔 flux에 대해 알아 볼려고 한다.
정확한거는 여길 참고

flux-simple-f8-diagram-with-client-action-1300w

flux는 위와 같은 아키텍처다.
실직적으로 프레임워크? 라이브러리? 라기보다는 아키텍쳐에 더 가깝다.
소스만 봐도 길지 않은 소스다.

위의 그림만 봐도 대충은 알것 같은 느낌이다.
액션이 생기면 Dispatcher가 받고 store로 전달한다음에 뷰로 전달된다.
일단 폴더 구조를 보자.
react-flux

일단 필자는 이렇게 해놨다.
actions 는 이벤트 발생 하는 시점을 말하는거 같다. 예로 버튼을 눌렀을때 액션을 호출해야된다.
실제 여기서 서버와 통신도 하는듯 하다.
components 는 뷰를 구현하는 폴더이다.
constants 는 상수를 정의하는 폴더이다.
core에는 Dispatcher가 포함되어있다.
stores에는 데이터들이 들어있다.
이제 flux을 설치하자

npm install flux

위와 같이 설치가 완료 되었다면 코딩으로 보자. 그게 더 이해하기 빠르니.

components의 Button이라는 컴포넌트다.

import React, { Component } from 'react';
import ButtonStore from '../stores/ButtonStore'
import ButtonCreator from '../actions/ButtonCreator'

export default class Button extends Component {

    constructor() {
        super();
        this._onChange = this._onChange.bind(this);
        this.state = {
            index : 0
        }
    }

    componentDidMount() {
        ButtonStore.addChangeListener(this._onChange);
    }
    componentWillUnmount() {
        ButtonStore.removeChangeListener(this._onChange);
    }
    addClick(index){
        ButtonCreator.addClick(index);
    }
    _onChange() {
        this.setState({index: ButtonStore.getIndex()})
    }
    render(){
        return(
            <div>
                <button onClick={this.addClick.bind(this,1)}>BUTTON</button>
                <input value={this.state.index}></input>
            </div>
        )
    }
}

버튼을 클릭하면 1을 더해서 출력해주는 컴포넌트다.
이벤트를 등록하고 클릭시 이벤트를 action에 전달한다.
액션의 ButtonCreator 파일을 보자

import Dispatcher from '../core/Dispatcher';
import ButtonConstants from '../constants/ButtonConstants';

export default {

    addClick:function(index){
        Dispatcher.handleViewAction({
            actionType: ButtonConstants.BUTTON_CONSTANT,
            index: index
        });
    }
}

액션은 실제 이벤트들이 모여 있는 곳이다.
액션타입과 데이터를 전달하면 된다.
다음으론 상수들을 정의해놓은 ButtonConstants다

export default  {
    BUTTON_CONSTANT: 'BUTTON_CONSTANT'
};

간단하게 상수 정의만 하면된다.
마지막으로 store를 보자

import Dispatcher from '../core/Dispatcher';
import ButtonConstants from '../constants/ButtonConstants';
import { EventEmitter } from 'events';

class ButtonStore extends EventEmitter {

    constructor() {
        super();
        this.subscribe(() => this._registerToActions.bind(this));
        this.index = 0;
    }
    subscribe(actionSubscribe) {
        this._dispatchToken = Dispatcher.register(actionSubscribe());
    }

    emitChange() {
        this.emit('CHANGE');
    }

    addChangeListener(cb) {
        this.on('CHANGE', cb)
    }

    removeChangeListener(cb) {
        this.removeListener('CHANGE', cb);
    }

    _registerToActions(payload) {
        let action = payload.action;
        switch (action.actionType) {
            case ButtonConstants.BUTTON_CONSTANT:
                this.index += action.index;
                break;
            default:
                return true;
        }
        this.emitChange();
        return true;
    }

    getIndex(){
        return this.index;
    }
}

export default new ButtonStore();

이벤트가 왔을 때 해당 액션타입을 보고서 이벤트를 결정한다.
액션에서 정의한 상수와 동일한 값이 전달된다.

완료가 되었다면 다시 컴파일을 해서 확인을 해보자.
버튼이한개 있고 버튼을 클릭하면 1씩증가한다.

근데 만약 저 버튼컴포넌트에서 클릭하면 다른 컴포넌트에 이벤트가 발생했다고 알려줘야되는데 그건 어떻게 하는지 보자.
TextBox라는 클래스를 만들자


import React, { Component } from 'react'; export default class TextBox extends Component { render(){ return( <div> <input value={this.state.text}></input> </div> ) } }

이런 간단한 컴포넌트다. 버튼컴포넌트에서 버튼을 누르면 버튼을 클릭하셨습니다 라고 띄어 줄 것이다.
그럼 간단한 작업만으로 가능하다.

import ButtonStore from '../stores/ButtonStore'
import ButtonCreator from '../actions/ButtonCreator'

...

constructor() {
    super();
    this._onChange = this._onChange.bind(this);
    this.state = {
        text : ""
    }
}

componentDidMount() {
    ButtonStore.addChangeListener(this._onChange);
}
componentWillUnmount() {
    ButtonStore.removeChangeListener(this._onChange);
}

_onChange() {
    this.setState({text: "버튼을 클릭 했습니다."})
}

위와 같이 추가 하자.
ButtonStore에 이벤트를 바인딩 시키자.
그런후에 버튼컴포넌트에 가서 아래와 같이 TextBox를 추가 시키자

import TextBox from '../components/TextBox'

...

<div>
    <button onClick={this.addClick.bind(this,1)}>BUTTON</button>
    <input value={this.state.index}></input>
    <TextBox />
</div>

그런 후에 다시 확인해보자.
그럼 버튼을 클릭하면 input text에 버튼을 클릭 했다고 나올 것이다.
이벤트를 받고 싶다면 해당 컴포넌트에 이벤트를 바인딩 시키면 된다.

이것으로 react와 flux에 대해 조금 알아봤다.
하지만 flux는 좋은 아키텍쳐 이지만 너무 복잡하다.

그래서 flux와 같지만 조금은 덜 복잡하게 만들어진 라이브러리도 존재한다.
그 중에 유명한게 fluxxor 이다.
flux 말고 redux도 좋아 보인다!
관심이 있다면 살펴보는 것도 나쁘지 않다!
이것으로 react는 마무리를 지어야 겠다!

소스는 github 에 올려놨다.