[번역] FLUX 페이스북 클라이언트 사이드 웹 애플리케이션 아키텍처

조영규의 블로그

2016. 6. 1. 02:28 from Develop


Edit

티스토리 FLUX javascript js facebook

Flux

Flux는 페이스북의 클라이언트 사이드 웹 애플리케이션 구축을 위한 아키텍쳐다. 이것은 한 방향으로의 데이터 흐름을 이용하여 React의 composable view 컴포넌트를 보완한다. 이것은 좀 더 큰 컨셉의 패턴이지, 공식적은 프레임워크는 아니다. 그리고 당신은 Flux를 새로운 코드 없이 바로 시작할 수 있다.

개괄

Flux 애플리케이션들은 3가지 주요한 파트로 구성된다. Dispatcher, Store, 그리고 View들(React 컴포넌트)이 그것이다. 이것들과 Model-View-Controller를 헷갈리지 말아야 한다. Controller는 Flux애플리케이션에도 존재하지만, Controller-View의 형태로만 존재한다. View들은 데이터를 Store에서 받거나, 그들의 자식 Store에게 데이터를 패스하기 위해 최상위 계급에 자주 위치한다. 게다가 Action Creator - Dispatcher의 헬퍼 메소드들 - 는 애플리케이션에서 가능한 모든 변화들을 묘사하기 위해 시멘틱한 API를 지원한다. Flux의 업데이트 사이클의 4가지 파트로서 이것들을 이해하면 상당히 편하다.

Flux는 MVC에서 양방햔 바인딩을 피한다. 유저가 React뷰와 인터렉션할 때, 뷰는 중심의 디스패처를 통하여 애플리케이션의 데이터와 비즈니스 로직 - 영향을 받은 모든 뷰들을 업데이트 하는 - 을 수행하는 다양한 스토어들에 로 Action을 전파한다.

이러한 작업들은 State 사이에서 어떻게 뷰들이 변할지 구체적으로 특정하지 않아도 스토어에게 업데이트들을 보낼 수 있도록 하는 특히 React의 Declarative 프로그래밍 스타일에서 유용하다.

우리는 파생된 데이터를 정확히 다루기 위해서 원래 시작했다. 예를들어 우리는 톡방들에서 아직 읽지 않은 것들의 숫자들을 읽지 않은 톡방이 하이라이트 되면서 톡방의 리스트와 함께 보여주길 바랐다. 한 톡방을 읽었다고 업데이트하면서, 동시에 읽지 않았다는 숫자를 동시에 업데이트 하는 것같은, 이런 일들은 MVC모델로는 다루기가 매우 힘들다. 의존적이고 폭포수처럼 전파되는 업데이트들은 MVC 아키텍쳐를 이용하는 큰 애플리케이션에서 자주 발생한다. 그리고 복잡한 데이터 흐름으로 예상치 못한 결과들을 초래한다.

제어권은 Store에게 역전된다. 스토어들은 업데이트를 받아들이고, 그들의 일관적인 방법으로 데이터를 업데이트 하게되는 외부적인 무언가에 의존하기보다, 그들을 적절하게 조정한다. 어떠한 외부 스토어들도 그 도메인을 위한 데이터들이 어떻게 관리되는지에 대해 전혀 이해하고 있지 않다. 이는 쓸데없는 걱정거리를 만들지 않는다. 스토어들은 어떤 다이렉트 Setter 메소드도 들고있지 않다. 예를 들어 setAsRead()같은. 그러나 대신 새로운 데이터를 그들 속의 세계로 가져오는 한가지 방법만이 존재한다. - 바로 callback이다. Dispatcher로 그들이 등록한.

스트럭쳐와 데이터 흐름

Flux의 데이터들은 한 방향으로만 흐른다.

단방향 데이터 흐름은 Flux 패턴의 중심이다. 그리고 위 다이어그램은 Flux 프로그래머에게 주요 맨탈 모델이어야 한다. 디스패처, 스토어, 뷰들은 명확한 인풋과 아웃풋이 있는 서로 독립적인 노드들이다. Action들은 간단한 오브젝트로, 새로운 데이터를 가지고 있고 어떤 타입의 프로퍼티인지에 대한 정보를 제공한다.

뷰들은 유저의 인터렉션들에 대한 반응과 관련된 새로운 Action을 생성할 것이다. 그리고 이러한 액션들은 시스템에 의해 전파된다.

모든 데이터는 중심 허브로서 Dispatcher를 통해 흐른다. Action은 Action creator 메소드 안에서 디스패처에게 제공된다. 그리고 더 자주는 뷰에서의 유저 인터렉션을 통해 대부분 생성될 것이다.

디스패처는 스토어들이 이미 dispatcher에게 등록했던, 모든 스토어들의 액션들을 스토어들에 전달하고 callback을 호출한다. 스토어 그들이 유지하는 스테이트들과 관련된 어떤 액션이든 등록된 컬벡 내에서 스토어들은 응답하게 된다. 스토어들은 그 후, 데이터 레이어의 변화를 Controller-Views들에게 알리기 위해 change 이벤트를 방출(emit)한다. Controller-View는 이러한 이벤트들을 리스닝하고 있다가 방출이 되면 이벤트 핸들러를 통해 스토어에서 데이터를 가져온다. 컨트롤 뷰는 그들 자신의 setState() 메소드를 스스로를 리렌더하고, 또 컴포넌트 트리의 후손들을 리렌더 하기위해 호출한다.

이 구조는 우리에게 한가지 방법으로 쉽게 애플리케이션을 추론할 수 있도록 한다. functional reactive programming, 혹은 더 구체적으로 data-flow programming 혹은 flow-based programming을 을 연상시키는 방법을 이용해서. 이 방법들에서는 애플리케이션의 데이터 플로우들은 한 뱡향으로 흐른다. 두 방향 바인딩은 없다.
애플리케이션 내의 특정 파트는 하나의 스토어에 의해 매우 decoupled된 채로 상태(state)가 유지된다. 동기적으로 업데이트가 디스패처에 의해 관리되면서, 스토어들의 의존성이 있는 곳에서는 엄격한 계급 체계을 유지한다.

우리는 두 방향의 데이터 바인딩이 한가지 오브젝트의 변화가 다른 오브젝트의 변화를 일으키는 캐스케이딩 업데이트를 발생시킨다는 것을 알았다. 그 뿐만 아니라 그 변화 또한 더 많은 업데이트들을 트리거 할 수 있다. 애플리케이션이 커지면서 이런 케스케이딩 업데이트들은 유저 인터렉션의 결과로서 무엇이 바뀌어 져야 하는지에 대한 결과물에 대한 예측하기 힘들게 한다. 업데이트가 하나의 라운드안에서 데이터를 변경할 때, 시스템은 전체로서 예측가능해진다.

다양한 Flux의 파트를 자세히 보자. 디스패처는 시작으로서 가장 적절한 선택이다.

하나의 Dispatcher

Flux 애플리케이션에서 모든 데이터 플로우를 관리하는 디스패처는 중앙 허브다. 기본적으로 디스패처는 스토어들의 안속의 callback들의 저장소(레지스트리)로 그 스스로는 어떠한 실질적 지능도 없다. 그것은 액션을 스토어로 분배하는 간단한 기계장치다. 각 스토어들은 dispatcher에 그들 스스로 뿐만 아니라 callback도 등록한다. Action creator가 디스패처에게 새로운 액션을 제공할 때, 애플리케이션 내 모든 스토어들은 저장소(레지스트리)안에있는 callbakc들을 통해 액션을 받는다.

애플리케이션의 성장에 따라, 디스패처는 좀 더 활성화된다. 이때 스토어들 사이에서 특정한 순서대로 등록된 callback을 호출해 주어 의존성을 관리하는데 사용될 수도 있다. 스토어는 선언적으로 기다릴 수 있다. 다른 스토어들이 업데이트를 완료하기까지. 그리고 나서 그들 스스로를 그에맞춰 업데이트한다.

페이스북이 프로덕션에서 사용하는 디스패처는 npm, Bower, or GitHub에서 이용할 수 있다.

스토어(Stores)

스토어는 애플리케이션의 스테이트와 로직을 가지고 있다. 그들의 역활은 뭔가 비슷한데, MVC에서의 모델이 그것이다. 그러나 그들은 다양한 오브젝트의 상태(state)를 관리한다. 그들은 ORM 모델이 하듯 하나의 단순한 레코드로 표현될 수 없다. Backbone의 콜렉션과도 마찬가지로 다르다. 간단히 ORM 스타일의 오브젝트를 관리하는 것 그 이상이다. 스토어는 특별한 도메인(책임영역)을 위한 애플리케이션의 상태(state)를 관리한다.

예를 들어보자. 페이스북의 Lookback Video Editor는 계속 재생시간의 위치와 재생 상태를 트래킹하는 TimeStore를 사용한다. 한편, 같은 애플리케이션의 ImageStore는 계속 이미지들의 컬렉션을 트래킹한다. 우리 TodoMVC Example에 있는 TodoStore도 비슷한데 todo 아이템의 컬렉션을 다룬다. 스토어는 2가지 특성을 보인다. 하나는 모델들의 컬렉션이고 또 다른 하나는 논리적인 도메인의 싱글톤 모델이다.

위에도 이야기했듯, 스토어는 그들 스스로를 디스패처에게 callback과 함께 직접 등록한다. 이 callback은 액션을 파래머터로 받는다. 스토어가 등록한 콜벡 안에서, 액션타입에 기반한 switch문은 액션을 번역하는데 사용될 뿐만 아니라 스토어 내부의 메소드들에게 적절한 훅(hook)을 제공하는데 사용된다. 이것은 액션이 디스패처를 통해 스토어의 상태 업데이트를 가능하도록 한다. 스토어가 업데이트 된 후, 그들은 스테이트가 바뀌었다는 이벤트를 내뿜는데, 이를 통해 뷰들은 새로운 상태를 질의할 수 있고, 그들 스스로를 업데이트 한다.

뷰(Views)와 Controller-Views

우리가 뷰레이어에서 필요로 하는 구성 가능한 종류의, 그리고 자유롭게 미리 랜더할 수 있는 뷰들을 React는 제공한다. 얽혀있는 뷰 계급의 최상단을 가까이에서 보면, 어떤 뷰가 의존하는 스토어가 브로드캐스트하는 이벤트들을 리스닝하는 특별한 뷰들이 존재한다. 우리는 이걸 컨트롤 뷰라고 부른다. 그들은 데이터를 스토어에서 가져오거나 혹은 그들의 후손들에게 데이터를 내려주는일을 위한 접착 코드를 제공한다. 우리는 이런 컨트롤 뷰들에게 중요한 섹션 하나를 할당해 주어야 할 것 같다.

이벤트를 스토어에서 받았을 때, 스토어의 public getter 메소드들로 필요한 새 데이터를 먼저 요청한다. 이후 자신의 setState()혹은 forceUpdate()메소드(그것의 render()메소드와 하부 자손들의 render() 메소드들을 실행하는)들을 호출한다.
우리는 자주 스토어의 전체 상태(state)를 뷰들의 체인이 있는 하부로 전달한다. 이것은 다른 후손들이 그들이 필요로 하는 것을 사용할 수 있도록 허락한다. 게다가 가장 최상위에서도 컨트롤러 비슷한 행동을 유지하기, 또 이렇게 우리의 자손 뷰들을 유지하기 위해, 가능한한 기능적으로 퓨어하게 모든 스토어의 상태를 싱글 오브젝트로 하부에 전달하는 것은 우리가 관리해야할 프로퍼티들의 수를 줄여주는 효과가 있다.

가끔, 우리는 안쪽(최상위가 아닌) 컨트롤 뷰를 컴포넌트를 간단히 유지하기 위해 가끔 추가할 필요를 느낀다. 이것은 특정 도메인의 섹션의 계층을 더 낫게 캡슐화 할 수 있게 해주기도 한다. 그러나 안쪽의 컨트롤러뷰는 하나의 데이터 흐름을 깰 수도 있다는 점을 알아야한다. 이런 컨트롤 뷰는 새로운 데이터 흐름을 위한 엔트리 포인트를 만들 수 있으며, 이는 잠재적인 충돌 가능성을 가지고 있다. 안쪽의 컨트롤 뷰를 만들 때는 간단한 컴포넌트의 이점과 복잡한 다수의 업데이트 사이에서 조율을 해야한다. 이러한 다수의 데이터 업데이트는 의도치 않은 영향을 만들 수 있는데, 다른 컨트롤뷰에 의해 계속적으로 호출되는 React의 렌더링 메소드의 getting에서 그렇다. 그리고 이건 잠재적으로 디버깅의 어려움을 증가시킬 수 있다.

액션(Actions)

우리가 스토어에게 분배(dispatch)를 트리거할 수 있도록, 그리고 데이터 페이로드 - 이것이 우리가 부르는 액션 - 를 포함 할 수 있게 디스패처는 한 메소드를 노출시킨다. 시멘틱한 헬퍼 메소드 안에, 엑션의 생성은 아마 래핑되어있을 것이다. 그것은 액션을 디스패처에게 보낸다. 예를들어, 우리는 To-do 아이템의 글자를 To-do List 애플리케이션에서 바꾸길 원할 수 있다. 우리는 TodoActions 모듈 안에 updateText(todoId, newText)같은 함수로 액션을 생성한다. 이 메소드들은 아마 우리의 뷰 이벤트 핸들러에 의해 호출될 것이다. 우리는 이것을 유저 인터렉션의 결과라 부를 수 있다. 이 액션 생성 메소드는 또한 액션에게 타입을 추가한다. 그래서 액션이 스토어에서 해셕될 때, 적절하게 응답할 수 있도록 한다. 우리의 예시에서는 이런 타입은 아마 TODO_UPDATE_TEXT같이 이름 붙여질 것이다.

액션은 아마 다른 장소들에서 올때도 있다, 서버같은 곳에서. 예를들어, 데이터를 초기화하는 동안 이런일이 일어난다. 또 마찬가지로 서버가 에러코드를 반환할때나 혹은 애플리케이션을 업데이트할때 같을때도 일어난다.

디스패처를 좀 더 보면,

아까 얘기했지만, 디스패처는 스토어들 사이의 디펜던시도 관리가 가능하다. 이런 기능은 디스패처 클래스의 waitFor() 메소드를 통해 가능하다. 우리는 지금 이런 메소드를 쓸 필요가 없다. 왜냐면 TodoMVC 애플리케이션이 굉장히 단순하니까. 그러나 이것은 크고 복잡한 애플리케이션에선 활성화될 것이다.

TodoStore의 등록된 콜벡 안에서 우리는 명시적으로 진행전에 다른 디펜던시들이 먼저 업데이트 되도록 기다릴 수 있다.

case 'TODO_CREATE':
Dispatcher.waitFor([
PrependedTextStore.dispatchToken,
YetAnotherStore.dispatchToken
]);

TodoStore.create(PrependedTextStore.getText() + ' ' + action.text);
break;

waitFor()은 한가지 argument만 받는다. 그 argument는 디스패처의 콜백 저장소(레지스트리) 인덱스다. 이것을 우리는 dispatch tokens이라 부른다. 이와같이 waitFor()를 호출하는 스토어는 그것이 그 자신의 스테이트를 어떻게 업데이트 해야하는지 알려주기 위한 다른 스토어의 상태에 의존할 수 있다.

디스패처 토큰은 디스패처에 콜벡을 등록할 때 register()의 반환값이다.

PrependedTextStore.dispatchToken = Dispatcher.register(function (payload) {
// ...
});

waitFor()이나 actions, action creators 그리고 디스패처에 대해 더 자세한걸 원하면 Flux: Actions and the Dispatcher 를 보자.

@%5B%uD2F0%uC2A4%uD1A0%uB9AC%2CFLUX%2Cjavascript%2Cjs%2Cfacebook%5D%0A%0A%23Flux%0A%0AFlux%uB294%20%uD398%uC774%uC2A4%uBD81%uC758%20%uD074%uB77C%uC774%uC5B8%uD2B8%20%uC0AC%uC774%uB4DC%20%uC6F9%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%20%uAD6C%uCD95%uC744%20%uC704%uD55C%20%uC544%uD0A4%uD14D%uCCD0%uB2E4.%20%uC774%uAC83%uC740%20%uD55C%20%uBC29%uD5A5%uC73C%uB85C%uC758%20%uB370%uC774%uD130%20%uD750%uB984%uC744%20%uC774%uC6A9%uD558%uC5EC%20React%uC758%20composable%20view%20%uCEF4%uD3EC%uB10C%uD2B8%uB97C%20%uBCF4%uC644%uD55C%uB2E4.%20%uC774%uAC83%uC740%20%uC880%20%uB354%20%uD070%20%uCEE8%uC149%uC758%20%uD328%uD134%uC774%uC9C0%2C%20%uACF5%uC2DD%uC801%uC740%20%uD504%uB808%uC784%uC6CC%uD06C%uB294%20%uC544%uB2C8%uB2E4.%20%uADF8%uB9AC%uACE0%20%uB2F9%uC2E0%uC740%20Flux%uB97C%20%uC0C8%uB85C%uC6B4%20%uCF54%uB4DC%20%uC5C6%uC774%20%uBC14%uB85C%20%uC2DC%uC791%uD560%20%uC218%20%uC788%uB2E4.%0A%0A%23%uAC1C%uAD04%0A%0AFlux%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uB4E4%uC740%203%uAC00%uC9C0%20%uC8FC%uC694%uD55C%20%uD30C%uD2B8%uB85C%20%uAD6C%uC131%uB41C%uB2E4.%20Dispatcher%2C%20Store%2C%20%uADF8%uB9AC%uACE0%20View%uB4E4%28React%20%uCEF4%uD3EC%uB10C%uD2B8%29%uC774%20%uADF8%uAC83%uC774%uB2E4.%20%uC774%uAC83%uB4E4%uACFC%20Model-View-Controller%uB97C%20%uD5F7%uAC08%uB9AC%uC9C0%20%uB9D0%uC544%uC57C%20%uD55C%uB2E4.%20Controller%uB294%20Flux%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC5D0%uB3C4%20%uC874%uC7AC%uD558%uC9C0%uB9CC%2C%20Controller-View%uC758%20%uD615%uD0DC%uB85C%uB9CC%20%uC874%uC7AC%uD55C%uB2E4.%20View%uB4E4%uC740%20%uB370%uC774%uD130%uB97C%20Store%uC5D0%uC11C%20%uBC1B%uAC70%uB098%2C%20%uADF8%uB4E4%uC758%20%uC790%uC2DD%20Store%uC5D0%uAC8C%20%uB370%uC774%uD130%uB97C%20%uD328%uC2A4%uD558%uAE30%20%uC704%uD574%20%uCD5C%uC0C1%uC704%20%uACC4%uAE09%uC5D0%20%uC790%uC8FC%20%uC704%uCE58%uD55C%uB2E4.%20%uAC8C%uB2E4%uAC00%20Action%20Creator%20-%20Dispatcher%uC758%20%uD5EC%uD37C%20%uBA54%uC18C%uB4DC%uB4E4%20-%20%uB294%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC5D0%uC11C%20%uAC00%uB2A5%uD55C%20%uBAA8%uB4E0%20%uBCC0%uD654%uB4E4%uC744%20%uBB18%uC0AC%uD558%uAE30%20%uC704%uD574%20%uC2DC%uBA58%uD2F1%uD55C%20API%uB97C%20%uC9C0%uC6D0%uD55C%uB2E4.%20Flux%uC758%20%uC5C5%uB370%uC774%uD2B8%20%uC0AC%uC774%uD074%uC758%204%uAC00%uC9C0%20%uD30C%uD2B8%uB85C%uC11C%20%uC774%uAC83%uB4E4%uC744%20%uC774%uD574%uD558%uBA74%20%uC0C1%uB2F9%uD788%20%uD3B8%uD558%uB2E4.%0A%0AFlux%uB294%20MVC%uC5D0%uC11C%20%uC591%uBC29%uD594%20%uBC14%uC778%uB529%uC744%20%uD53C%uD55C%uB2E4.%20%uC720%uC800%uAC00%20React%uBDF0%uC640%20%uC778%uD130%uB809%uC158%uD560%20%uB54C%2C%20%uBDF0%uB294%20%uC911%uC2EC%uC758%20%uB514%uC2A4%uD328%uCC98%uB97C%20%uD1B5%uD558%uC5EC%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC758%20%uB370%uC774%uD130%uC640%20%uBE44%uC988%uB2C8%uC2A4%20%uB85C%uC9C1%20-%20%uC601%uD5A5%uC744%20%uBC1B%uC740%20%uBAA8%uB4E0%20%uBDF0%uB4E4%uC744%20%uC5C5%uB370%uC774%uD2B8%20%uD558%uB294%20-%20%uC744%20%uC218%uD589%uD558%uB294%20%uB2E4%uC591%uD55C%20%uC2A4%uD1A0%uC5B4%uB4E4%uC5D0%20%uB85C%20Action%uC744%20%uC804%uD30C%uD55C%uB2E4.%20%0A%0A%uC774%uB7EC%uD55C%20%uC791%uC5C5%uB4E4%uC740%20State%20%uC0AC%uC774%uC5D0%uC11C%20%uC5B4%uB5BB%uAC8C%20%uBDF0%uB4E4%uC774%20%uBCC0%uD560%uC9C0%20%uAD6C%uCCB4%uC801%uC73C%uB85C%20%uD2B9%uC815%uD558%uC9C0%20%uC54A%uC544%uB3C4%20%uC2A4%uD1A0%uC5B4%uC5D0%uAC8C%20%uC5C5%uB370%uC774%uD2B8%uB4E4%uC744%20%uBCF4%uB0BC%20%uC218%20%uC788%uB3C4%uB85D%20%uD558%uB294%20%uD2B9%uD788%20React%uC758%20Declarative%20%uD504%uB85C%uADF8%uB798%uBC0D%20%uC2A4%uD0C0%uC77C%uC5D0%uC11C%20%uC720%uC6A9%uD558%uB2E4.%0A%0A%uC6B0%uB9AC%uB294%20%uD30C%uC0DD%uB41C%20%uB370%uC774%uD130%uB97C%20%uC815%uD655%uD788%20%uB2E4%uB8E8%uAE30%20%uC704%uD574%uC11C%20%uC6D0%uB798%20%uC2DC%uC791%uD588%uB2E4.%20%uC608%uB97C%uB4E4%uC5B4%20%uC6B0%uB9AC%uB294%20%uD1A1%uBC29%uB4E4%uC5D0%uC11C%20%uC544%uC9C1%20%uC77D%uC9C0%20%uC54A%uC740%20%uAC83%uB4E4%uC758%20%uC22B%uC790%uB4E4%uC744%20%uC77D%uC9C0%20%uC54A%uC740%20%uD1A1%uBC29%uC774%20%uD558%uC774%uB77C%uC774%uD2B8%20%uB418%uBA74%uC11C%20%uD1A1%uBC29%uC758%20%uB9AC%uC2A4%uD2B8%uC640%20%uD568%uAED8%20%uBCF4%uC5EC%uC8FC%uAE38%20%uBC14%uB790%uB2E4.%20%uD55C%20%uD1A1%uBC29%uC744%20%uC77D%uC5C8%uB2E4%uACE0%20%uC5C5%uB370%uC774%uD2B8%uD558%uBA74%uC11C%2C%20%uB3D9%uC2DC%uC5D0%20%uC77D%uC9C0%20%uC54A%uC558%uB2E4%uB294%20%uC22B%uC790%uB97C%20%uB3D9%uC2DC%uC5D0%20%uC5C5%uB370%uC774%uD2B8%20%uD558%uB294%20%uAC83%uAC19%uC740%2C%20%uC774%uB7F0%20%uC77C%uB4E4%uC740%20MVC%uBAA8%uB378%uB85C%uB294%20%uB2E4%uB8E8%uAE30%uAC00%20%uB9E4%uC6B0%20%uD798%uB4E4%uB2E4.%20%uC758%uC874%uC801%uC774%uACE0%20%uD3ED%uD3EC%uC218%uCC98%uB7FC%20%uC804%uD30C%uB418%uB294%20%uC5C5%uB370%uC774%uD2B8%uB4E4%uC740%20MVC%20%uC544%uD0A4%uD14D%uCCD0%uB97C%20%uC774%uC6A9%uD558%uB294%20%uD070%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC5D0%uC11C%20%uC790%uC8FC%20%uBC1C%uC0DD%uD55C%uB2E4.%20%uADF8%uB9AC%uACE0%20%uBCF5%uC7A1%uD55C%20%uB370%uC774%uD130%20%uD750%uB984%uC73C%uB85C%20%uC608%uC0C1%uCE58%20%uBABB%uD55C%20%uACB0%uACFC%uB4E4%uC744%20%uCD08%uB798%uD55C%uB2E4.%0A%0A%uC81C%uC5B4%uAD8C%uC740%20Store%uC5D0%uAC8C%20%uC5ED%uC804%uB41C%uB2E4.%20%uC2A4%uD1A0%uC5B4%uB4E4%uC740%20%uC5C5%uB370%uC774%uD2B8%uB97C%20%uBC1B%uC544%uB4E4%uC774%uACE0%2C%20%uADF8%uB4E4%uC758%20%uC77C%uAD00%uC801%uC778%20%uBC29%uBC95%uC73C%uB85C%20%uB370%uC774%uD130%uB97C%20%uC5C5%uB370%uC774%uD2B8%20%uD558%uAC8C%uB418%uB294%20%uC678%uBD80%uC801%uC778%20%uBB34%uC5B8%uAC00%uC5D0%20%uC758%uC874%uD558%uAE30%uBCF4%uB2E4%2C%20%uADF8%uB4E4%uC744%20%uC801%uC808%uD558%uAC8C%20%uC870%uC815%uD55C%uB2E4.%20%uC5B4%uB5A0%uD55C%20%uC678%uBD80%20%uC2A4%uD1A0%uC5B4%uB4E4%uB3C4%20%uADF8%20%uB3C4%uBA54%uC778%uC744%20%uC704%uD55C%20%uB370%uC774%uD130%uB4E4%uC774%20%uC5B4%uB5BB%uAC8C%20%uAD00%uB9AC%uB418%uB294%uC9C0%uC5D0%20%uB300%uD574%20%uC804%uD600%20%uC774%uD574%uD558%uACE0%20%uC788%uC9C0%20%uC54A%uB2E4.%20%uC774%uB294%20%uC4F8%uB370%uC5C6%uB294%20%uAC71%uC815%uAC70%uB9AC%uB97C%20%uB9CC%uB4E4%uC9C0%20%uC54A%uB294%uB2E4.%20%uC2A4%uD1A0%uC5B4%uB4E4%uC740%20%uC5B4%uB5A4%20%uB2E4%uC774%uB809%uD2B8%20Setter%20%uBA54%uC18C%uB4DC%uB3C4%20%uB4E4%uACE0%uC788%uC9C0%20%uC54A%uB2E4.%20%uC608%uB97C%20%uB4E4%uC5B4%20%60setAsRead%28%29%60%uAC19%uC740.%20%uADF8%uB7EC%uB098%20%uB300%uC2E0%20%uC0C8%uB85C%uC6B4%20%uB370%uC774%uD130%uB97C%20%uADF8%uB4E4%20%uC18D%uC758%20%uC138%uACC4%uB85C%20%uAC00%uC838%uC624%uB294%20%uD55C%uAC00%uC9C0%20%uBC29%uBC95%uB9CC%uC774%20%uC874%uC7AC%uD55C%uB2E4.%20%20-%20%uBC14%uB85C%20callback%uC774%uB2E4.%20Dispatcher%uB85C%20%uADF8%uB4E4%uC774%20%uB4F1%uB85D%uD55C.%0A%0A%23%uC2A4%uD2B8%uB7ED%uCCD0%uC640%20%uB370%uC774%uD130%20%uD750%uB984%0A%0AFlux%uC758%20%uB370%uC774%uD130%uB4E4%uC740%20%uD55C%20%uBC29%uD5A5%uC73C%uB85C%uB9CC%20%uD750%uB978%uB2E4.%0A%0A%21%5BAlt%20text%5D%28./1451462507641.png%29%0A%0A%uB2E8%uBC29%uD5A5%20%uB370%uC774%uD130%20%uD750%uB984%uC740%20Flux%20%uD328%uD134%uC758%20%uC911%uC2EC%uC774%uB2E4.%20%uADF8%uB9AC%uACE0%20%uC704%20%uB2E4%uC774%uC5B4%uADF8%uB7A8%uC740%20Flux%20%uD504%uB85C%uADF8%uB798%uBA38%uC5D0%uAC8C%20%uC8FC%uC694%20%uB9E8%uD0C8%20%uBAA8%uB378%uC774%uC5B4%uC57C%20%uD55C%uB2E4.%20%uB514%uC2A4%uD328%uCC98%2C%20%uC2A4%uD1A0%uC5B4%2C%20%uBDF0%uB4E4%uC740%20%uBA85%uD655%uD55C%20%uC778%uD48B%uACFC%20%uC544%uC6C3%uD48B%uC774%20%uC788%uB294%20%uC11C%uB85C%20%uB3C5%uB9BD%uC801%uC778%20%uB178%uB4DC%uB4E4%uC774%uB2E4.%20Action%uB4E4%uC740%20%uAC04%uB2E8%uD55C%20%uC624%uBE0C%uC81D%uD2B8%uB85C%2C%20%uC0C8%uB85C%uC6B4%20%uB370%uC774%uD130%uB97C%20%uAC00%uC9C0%uACE0%20%uC788%uACE0%20%uC5B4%uB5A4%20%uD0C0%uC785%uC758%20%uD504%uB85C%uD37C%uD2F0%uC778%uC9C0%uC5D0%20%uB300%uD55C%20%uC815%uBCF4%uB97C%20%uC81C%uACF5%uD55C%uB2E4.%0A%0A%uBDF0%uB4E4%uC740%20%uC720%uC800%uC758%20%uC778%uD130%uB809%uC158%uB4E4%uC5D0%20%uB300%uD55C%20%uBC18%uC751%uACFC%20%uAD00%uB828%uB41C%20%uC0C8%uB85C%uC6B4%20Action%uC744%20%uC0DD%uC131%uD560%20%uAC83%uC774%uB2E4.%20%uADF8%uB9AC%uACE0%20%uC774%uB7EC%uD55C%20%uC561%uC158%uB4E4%uC740%20%uC2DC%uC2A4%uD15C%uC5D0%20%uC758%uD574%20%uC804%uD30C%uB41C%uB2E4.%0A%21%5BAlt%20text%5D%28./1451462712969.png%29%0A%0A%uBAA8%uB4E0%20%uB370%uC774%uD130%uB294%20%uC911%uC2EC%20%uD5C8%uBE0C%uB85C%uC11C%20Dispatcher%uB97C%20%uD1B5%uD574%20%uD750%uB978%uB2E4.%20Action%uC740%20Action%20creator%20%uBA54%uC18C%uB4DC%20%uC548%uC5D0%uC11C%20%uB514%uC2A4%uD328%uCC98%uC5D0%uAC8C%20%uC81C%uACF5%uB41C%uB2E4.%20%uADF8%uB9AC%uACE0%20%uB354%20%uC790%uC8FC%uB294%20%uBDF0%uC5D0%uC11C%uC758%20%uC720%uC800%20%uC778%uD130%uB809%uC158%uC744%20%uD1B5%uD574%20%uB300%uBD80%uBD84%20%uC0DD%uC131%uB420%20%uAC83%uC774%uB2E4.%20%0A%0A%uB514%uC2A4%uD328%uCC98%uB294%20%uC2A4%uD1A0%uC5B4%uB4E4%uC774%20%uC774%uBBF8%20dispatcher%uC5D0%uAC8C%20%uB4F1%uB85D%uD588%uB358%2C%20%uBAA8%uB4E0%20%uC2A4%uD1A0%uC5B4%uB4E4%uC758%20%uC561%uC158%uB4E4%uC744%20%uC2A4%uD1A0%uC5B4%uB4E4%uC5D0%20%uC804%uB2EC%uD558%uACE0%20callback%uC744%20%uD638%uCD9C%uD55C%uB2E4.%20%uC2A4%uD1A0%uC5B4%20%uADF8%uB4E4%uC774%20%uC720%uC9C0%uD558%uB294%20%uC2A4%uD14C%uC774%uD2B8%uB4E4%uACFC%20%uAD00%uB828%uB41C%20%uC5B4%uB5A4%20%uC561%uC158%uC774%uB4E0%20%uB4F1%uB85D%uB41C%20%uCEEC%uBCA1%20%uB0B4%uC5D0%uC11C%20%uC2A4%uD1A0%uC5B4%uB4E4%uC740%20%uC751%uB2F5%uD558%uAC8C%20%uB41C%uB2E4.%20%uC2A4%uD1A0%uC5B4%uB4E4%uC740%20%uADF8%20%uD6C4%2C%20%uB370%uC774%uD130%20%uB808%uC774%uC5B4%uC758%20%uBCC0%uD654%uB97C%20Controller-Views%uB4E4%uC5D0%uAC8C%20%uC54C%uB9AC%uAE30%20%uC704%uD574%20change%20%uC774%uBCA4%uD2B8%uB97C%20%uBC29%uCD9C%28emit%29%uD55C%uB2E4.%20Controller-View%uB294%20%uC774%uB7EC%uD55C%20%uC774%uBCA4%uD2B8%uB4E4%uC744%20%uB9AC%uC2A4%uB2DD%uD558%uACE0%20%uC788%uB2E4%uAC00%20%uBC29%uCD9C%uC774%20%uB418%uBA74%20%uC774%uBCA4%uD2B8%20%uD578%uB4E4%uB7EC%uB97C%20%uD1B5%uD574%20%uC2A4%uD1A0%uC5B4%uC5D0%uC11C%20%uB370%uC774%uD130%uB97C%20%uAC00%uC838%uC628%uB2E4.%20%uCEE8%uD2B8%uB864%20%uBDF0%uB294%20%uADF8%uB4E4%20%uC790%uC2E0%uC758%20setState%28%29%20%uBA54%uC18C%uB4DC%uB97C%20%uC2A4%uC2A4%uB85C%uB97C%20%uB9AC%uB80C%uB354%uD558%uACE0%2C%20%uB610%20%uCEF4%uD3EC%uB10C%uD2B8%20%uD2B8%uB9AC%uC758%20%uD6C4%uC190%uB4E4%uC744%20%uB9AC%uB80C%uB354%20%uD558%uAE30%uC704%uD574%20%uD638%uCD9C%uD55C%uB2E4.%0A%0A%21%5BAlt%20text%5D%28./1451463358648.png%29%0A%0A%uC774%20%uAD6C%uC870%uB294%20%uC6B0%uB9AC%uC5D0%uAC8C%20%uD55C%uAC00%uC9C0%20%uBC29%uBC95%uC73C%uB85C%20%uC27D%uAC8C%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC744%20%uCD94%uB860%uD560%20%uC218%20%uC788%uB3C4%uB85D%20%uD55C%uB2E4.%20%20%60functional%20reactive%20programming%60%2C%20%uD639%uC740%20%uB354%20%uAD6C%uCCB4%uC801%uC73C%uB85C%20%60data-flow%20programming%60%20%uD639%uC740%20%60flow-based%20programming%60%uC744%20%uC744%20%uC5F0%uC0C1%uC2DC%uD0A4%uB294%20%uBC29%uBC95%uC744%20%uC774%uC6A9%uD574%uC11C.%20%20%uC774%20%uBC29%uBC95%uB4E4%uC5D0%uC11C%uB294%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC758%20%uB370%uC774%uD130%20%uD50C%uB85C%uC6B0%uB4E4%uC740%20%uD55C%20%uBC61%uD5A5%uC73C%uB85C%20%uD750%uB978%uB2E4.%20%uB450%20%uBC29%uD5A5%20%uBC14%uC778%uB529%uC740%20%uC5C6%uB2E4.%0A%uC560%uD50C%uB9AC%uCF00%uC774%uC158%20%uB0B4%uC758%20%uD2B9%uC815%20%uD30C%uD2B8%uB294%20%uD558%uB098%uC758%20%uC2A4%uD1A0%uC5B4%uC5D0%20%uC758%uD574%20%uB9E4%uC6B0%20decoupled%uB41C%20%uCC44%uB85C%20%uC0C1%uD0DC%28state%29%uAC00%20%uC720%uC9C0%uB41C%uB2E4.%20%uB3D9%uAE30%uC801%uC73C%uB85C%20%uC5C5%uB370%uC774%uD2B8%uAC00%20%uB514%uC2A4%uD328%uCC98%uC5D0%20%uC758%uD574%20%uAD00%uB9AC%uB418%uBA74%uC11C%2C%20%uC2A4%uD1A0%uC5B4%uB4E4%uC758%20%uC758%uC874%uC131%uC774%20%uC788%uB294%20%uACF3%uC5D0%uC11C%uB294%20%uC5C4%uACA9%uD55C%20%uACC4%uAE09%20%uCCB4%uACC4%uC744%20%uC720%uC9C0%uD55C%uB2E4.%0A%0A%uC6B0%uB9AC%uB294%20%uB450%20%uBC29%uD5A5%uC758%20%uB370%uC774%uD130%20%uBC14%uC778%uB529%uC774%20%uD55C%uAC00%uC9C0%20%uC624%uBE0C%uC81D%uD2B8%uC758%20%uBCC0%uD654%uAC00%20%uB2E4%uB978%20%uC624%uBE0C%uC81D%uD2B8%uC758%20%uBCC0%uD654%uB97C%20%uC77C%uC73C%uD0A4%uB294%20%uCE90%uC2A4%uCF00%uC774%uB529%20%uC5C5%uB370%uC774%uD2B8%uB97C%20%uBC1C%uC0DD%uC2DC%uD0A8%uB2E4%uB294%20%uAC83%uC744%20%uC54C%uC558%uB2E4.%20%uADF8%20%uBFD0%uB9CC%20%uC544%uB2C8%uB77C%20%uADF8%20%uBCC0%uD654%20%uB610%uD55C%20%uB354%20%uB9CE%uC740%20%uC5C5%uB370%uC774%uD2B8%uB4E4%uC744%20%uD2B8%uB9AC%uAC70%20%uD560%20%uC218%20%uC788%uB2E4.%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC774%20%uCEE4%uC9C0%uBA74%uC11C%20%uC774%uB7F0%20%uCF00%uC2A4%uCF00%uC774%uB529%20%uC5C5%uB370%uC774%uD2B8%uB4E4%uC740%20%uC720%uC800%20%uC778%uD130%uB809%uC158%uC758%20%uACB0%uACFC%uB85C%uC11C%20%uBB34%uC5C7%uC774%20%uBC14%uB00C%uC5B4%20%uC838%uC57C%20%uD558%uB294%uC9C0%uC5D0%20%uB300%uD55C%20%uACB0%uACFC%uBB3C%uC5D0%20%uB300%uD55C%20%uC608%uCE21%uD558%uAE30%20%uD798%uB4E4%uAC8C%20%uD55C%uB2E4.%20%uC5C5%uB370%uC774%uD2B8%uAC00%20%uD558%uB098%uC758%20%uB77C%uC6B4%uB4DC%uC548%uC5D0%uC11C%20%uB370%uC774%uD130%uB97C%20%uBCC0%uACBD%uD560%20%uB54C%2C%20%uC2DC%uC2A4%uD15C%uC740%20%uC804%uCCB4%uB85C%uC11C%20%uC608%uCE21%uAC00%uB2A5%uD574%uC9C4%uB2E4.%0A%0A%uB2E4%uC591%uD55C%20Flux%uC758%20%uD30C%uD2B8%uB97C%20%uC790%uC138%uD788%20%uBCF4%uC790.%20%uB514%uC2A4%uD328%uCC98%uB294%20%uC2DC%uC791%uC73C%uB85C%uC11C%20%uAC00%uC7A5%20%uC801%uC808%uD55C%20%uC120%uD0DD%uC774%uB2E4.%0A%0A%23%uD558%uB098%uC758%20Dispatcher%0A%0AFlux%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC5D0%uC11C%20%uBAA8%uB4E0%20%uB370%uC774%uD130%20%uD50C%uB85C%uC6B0%uB97C%20%uAD00%uB9AC%uD558%uB294%20%uB514%uC2A4%uD328%uCC98%uB294%20%uC911%uC559%20%uD5C8%uBE0C%uB2E4.%20%uAE30%uBCF8%uC801%uC73C%uB85C%20%uB514%uC2A4%uD328%uCC98%uB294%20%uC2A4%uD1A0%uC5B4%uB4E4%uC758%20%uC548%uC18D%uC758%20callback%uB4E4%uC758%20%uC800%uC7A5%uC18C%28%uB808%uC9C0%uC2A4%uD2B8%uB9AC%29%uB85C%20%uADF8%20%uC2A4%uC2A4%uB85C%uB294%20%uC5B4%uB5A0%uD55C%20%uC2E4%uC9C8%uC801%20%uC9C0%uB2A5%uB3C4%20%uC5C6%uB2E4.%20%uADF8%uAC83%uC740%20%uC561%uC158%uC744%20%uC2A4%uD1A0%uC5B4%uB85C%20%uBD84%uBC30%uD558%uB294%20%uAC04%uB2E8%uD55C%20%uAE30%uACC4%uC7A5%uCE58%uB2E4.%20%uAC01%20%uC2A4%uD1A0%uC5B4%uB4E4%uC740%20dispatcher%uC5D0%20%uADF8%uB4E4%20%uC2A4%uC2A4%uB85C%20%uBFD0%uB9CC%20%uC544%uB2C8%uB77C%20callback%uB3C4%20%uB4F1%uB85D%uD55C%uB2E4.%20Action%20creator%uAC00%20%uB514%uC2A4%uD328%uCC98%uC5D0%uAC8C%20%uC0C8%uB85C%uC6B4%20%uC561%uC158%uC744%20%uC81C%uACF5%uD560%20%uB54C%2C%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%20%uB0B4%20%uBAA8%uB4E0%20%uC2A4%uD1A0%uC5B4%uB4E4%uC740%20%uC800%uC7A5%uC18C%28%uB808%uC9C0%uC2A4%uD2B8%uB9AC%29%uC548%uC5D0%uC788%uB294%20callbakc%uB4E4%uC744%20%uD1B5%uD574%20%uC561%uC158%uC744%20%uBC1B%uB294%uB2E4.%20%0A%0A%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC758%20%uC131%uC7A5%uC5D0%20%uB530%uB77C%2C%20%uB514%uC2A4%uD328%uCC98%uB294%20%uC880%20%uB354%20%uD65C%uC131%uD654%uB41C%uB2E4.%20%uC774%uB54C%20%uC2A4%uD1A0%uC5B4%uB4E4%20%uC0AC%uC774%uC5D0%uC11C%20%uD2B9%uC815%uD55C%20%uC21C%uC11C%uB300%uB85C%20%uB4F1%uB85D%uB41C%20callback%uC744%20%uD638%uCD9C%uD574%20%uC8FC%uC5B4%20%uC758%uC874%uC131%uC744%20%uAD00%uB9AC%uD558%uB294%uB370%20%uC0AC%uC6A9%uB420%20%uC218%uB3C4%20%uC788%uB2E4.%20%uC2A4%uD1A0%uC5B4%uB294%20%uC120%uC5B8%uC801%uC73C%uB85C%20%uAE30%uB2E4%uB9B4%20%uC218%20%uC788%uB2E4.%20%uB2E4%uB978%20%uC2A4%uD1A0%uC5B4%uB4E4%uC774%20%uC5C5%uB370%uC774%uD2B8%uB97C%20%uC644%uB8CC%uD558%uAE30%uAE4C%uC9C0.%20%uADF8%uB9AC%uACE0%20%uB098%uC11C%20%uADF8%uB4E4%20%uC2A4%uC2A4%uB85C%uB97C%20%uADF8%uC5D0%uB9DE%uCDB0%20%uC5C5%uB370%uC774%uD2B8%uD55C%uB2E4.%0A%0A%uD398%uC774%uC2A4%uBD81%uC774%20%uD504%uB85C%uB355%uC158%uC5D0%uC11C%20%uC0AC%uC6A9%uD558%uB294%20%uB514%uC2A4%uD328%uCC98%uB294%20npm%2C%20Bower%2C%20or%20GitHub%uC5D0%uC11C%20%uC774%uC6A9%uD560%20%uC218%20%uC788%uB2E4.%0A%0A%23%uC2A4%uD1A0%uC5B4%28Stores%29%0A%0A%uC2A4%uD1A0%uC5B4%uB294%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC758%20%uC2A4%uD14C%uC774%uD2B8%uC640%20%uB85C%uC9C1%uC744%20%uAC00%uC9C0%uACE0%20%uC788%uB2E4.%20%uADF8%uB4E4%uC758%20%uC5ED%uD65C%uC740%20%uBB54%uAC00%20%uBE44%uC2B7%uD55C%uB370%2C%20MVC%uC5D0%uC11C%uC758%20%uBAA8%uB378%uC774%20%uADF8%uAC83%uC774%uB2E4.%20%uADF8%uB7EC%uB098%20%uADF8%uB4E4%uC740%20%uB2E4%uC591%uD55C%20%uC624%uBE0C%uC81D%uD2B8%uC758%20%uC0C1%uD0DC%28state%29%uB97C%20%uAD00%uB9AC%uD55C%uB2E4.%20%uADF8%uB4E4%uC740%20ORM%20%uBAA8%uB378%uC774%20%uD558%uB4EF%20%uD558%uB098%uC758%20%uB2E8%uC21C%uD55C%20%uB808%uCF54%uB4DC%uB85C%20%uD45C%uD604%uB420%20%uC218%20%uC5C6%uB2E4.%20Backbone%uC758%20%uCF5C%uB809%uC158%uACFC%uB3C4%20%uB9C8%uCC2C%uAC00%uC9C0%uB85C%20%uB2E4%uB974%uB2E4.%20%uAC04%uB2E8%uD788%20ORM%20%uC2A4%uD0C0%uC77C%uC758%20%uC624%uBE0C%uC81D%uD2B8%uB97C%20%uAD00%uB9AC%uD558%uB294%20%uAC83%20%uADF8%20%uC774%uC0C1%uC774%uB2E4.%20%uC2A4%uD1A0%uC5B4%uB294%20%uD2B9%uBCC4%uD55C%20%uB3C4%uBA54%uC778%28%uCC45%uC784%uC601%uC5ED%29%uC744%20%uC704%uD55C%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC758%20%uC0C1%uD0DC%28state%29%uB97C%20%uAD00%uB9AC%uD55C%uB2E4.%20%0A%0A%uC608%uB97C%20%uB4E4%uC5B4%uBCF4%uC790.%20%uD398%uC774%uC2A4%uBD81%uC758%20Lookback%20Video%20Editor%uB294%20%uACC4%uC18D%20%uC7AC%uC0DD%uC2DC%uAC04%uC758%20%uC704%uCE58%uC640%20%uC7AC%uC0DD%20%uC0C1%uD0DC%uB97C%20%uD2B8%uB798%uD0B9%uD558%uB294%20TimeStore%uB97C%20%uC0AC%uC6A9%uD55C%uB2E4.%20%20%uD55C%uD3B8%2C%20%uAC19%uC740%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC758%20ImageStore%uB294%20%uACC4%uC18D%20%uC774%uBBF8%uC9C0%uB4E4%uC758%20%uCEEC%uB809%uC158%uC744%20%uD2B8%uB798%uD0B9%uD55C%uB2E4.%20%uC6B0%uB9AC%20TodoMVC%20Example%uC5D0%20%uC788%uB294%20TodoStore%uB3C4%20%uBE44%uC2B7%uD55C%uB370%20todo%20%uC544%uC774%uD15C%uC758%20%uCEEC%uB809%uC158%uC744%20%uB2E4%uB8EC%uB2E4.%20%uC2A4%uD1A0%uC5B4%uB294%202%uAC00%uC9C0%20%uD2B9%uC131%uC744%20%uBCF4%uC778%uB2E4.%20%uD558%uB098%uB294%20%uBAA8%uB378%uB4E4%uC758%20%uCEEC%uB809%uC158%uC774%uACE0%20%uB610%20%uB2E4%uB978%20%uD558%uB098%uB294%20%uB17C%uB9AC%uC801%uC778%20%uB3C4%uBA54%uC778%uC758%20%uC2F1%uAE00%uD1A4%20%uBAA8%uB378%uC774%uB2E4.%0A%0A%uC704%uC5D0%uB3C4%20%uC774%uC57C%uAE30%uD588%uB4EF%2C%20%uC2A4%uD1A0%uC5B4%uB294%20%uADF8%uB4E4%20%uC2A4%uC2A4%uB85C%uB97C%20%uB514%uC2A4%uD328%uCC98%uC5D0%uAC8C%20callback%uACFC%20%uD568%uAED8%20%uC9C1%uC811%20%uB4F1%uB85D%uD55C%uB2E4.%20%uC774%20callback%uC740%20%uC561%uC158%uC744%20%uD30C%uB798%uBA38%uD130%uB85C%20%uBC1B%uB294%uB2E4.%20%uC2A4%uD1A0%uC5B4%uAC00%20%uB4F1%uB85D%uD55C%20%uCF5C%uBCA1%20%uC548%uC5D0%uC11C%2C%20%uC561%uC158%uD0C0%uC785%uC5D0%20%uAE30%uBC18%uD55C%20switch%uBB38%uC740%20%uC561%uC158%uC744%20%uBC88%uC5ED%uD558%uB294%uB370%20%uC0AC%uC6A9%uB420%20%uBFD0%uB9CC%20%uC544%uB2C8%uB77C%20%uC2A4%uD1A0%uC5B4%20%uB0B4%uBD80%uC758%20%uBA54%uC18C%uB4DC%uB4E4%uC5D0%uAC8C%20%uC801%uC808%uD55C%20%uD6C5%28hook%29%uC744%20%uC81C%uACF5%uD558%uB294%uB370%20%uC0AC%uC6A9%uB41C%uB2E4.%20%uC774%uAC83%uC740%20%uC561%uC158%uC774%20%uB514%uC2A4%uD328%uCC98%uB97C%20%uD1B5%uD574%20%uC2A4%uD1A0%uC5B4%uC758%20%uC0C1%uD0DC%20%uC5C5%uB370%uC774%uD2B8%uB97C%20%uAC00%uB2A5%uD558%uB3C4%uB85D%20%uD55C%uB2E4.%20%uC2A4%uD1A0%uC5B4%uAC00%20%uC5C5%uB370%uC774%uD2B8%20%uB41C%20%uD6C4%2C%20%uADF8%uB4E4%uC740%20%uC2A4%uD14C%uC774%uD2B8%uAC00%20%uBC14%uB00C%uC5C8%uB2E4%uB294%20%uC774%uBCA4%uD2B8%uB97C%20%uB0B4%uBFDC%uB294%uB370%2C%20%uC774%uB97C%20%uD1B5%uD574%20%uBDF0%uB4E4%uC740%20%uC0C8%uB85C%uC6B4%20%uC0C1%uD0DC%uB97C%20%uC9C8%uC758%uD560%20%uC218%20%uC788%uACE0%2C%20%uADF8%uB4E4%20%uC2A4%uC2A4%uB85C%uB97C%20%uC5C5%uB370%uC774%uD2B8%20%uD55C%uB2E4.%0A%0A%23%uBDF0%28Views%29%uC640%20Controller-Views%0A%0A%uC6B0%uB9AC%uAC00%20%uBDF0%uB808%uC774%uC5B4%uC5D0%uC11C%20%uD544%uC694%uB85C%20%uD558%uB294%20%uAD6C%uC131%20%uAC00%uB2A5%uD55C%20%uC885%uB958%uC758%2C%20%uADF8%uB9AC%uACE0%20%uC790%uC720%uB86D%uAC8C%20%uBBF8%uB9AC%20%uB79C%uB354%uD560%20%uC218%20%uC788%uB294%20%uBDF0%uB4E4%uC744%20React%uB294%20%uC81C%uACF5%uD55C%uB2E4.%20%uC5BD%uD600%uC788%uB294%20%uBDF0%20%uACC4%uAE09%uC758%20%uCD5C%uC0C1%uB2E8%uC744%20%uAC00%uAE4C%uC774%uC5D0%uC11C%20%uBCF4%uBA74%2C%20%uC5B4%uB5A4%20%uBDF0%uAC00%20%uC758%uC874%uD558%uB294%20%uC2A4%uD1A0%uC5B4%uAC00%20%uBE0C%uB85C%uB4DC%uCE90%uC2A4%uD2B8%uD558%uB294%20%uC774%uBCA4%uD2B8%uB4E4%uC744%20%uB9AC%uC2A4%uB2DD%uD558%uB294%20%uD2B9%uBCC4%uD55C%20%uBDF0%uB4E4%uC774%20%uC874%uC7AC%uD55C%uB2E4.%20%uC6B0%uB9AC%uB294%20%uC774%uAC78%20%uCEE8%uD2B8%uB864%20%uBDF0%uB77C%uACE0%20%uBD80%uB978%uB2E4.%20%uADF8%uB4E4%uC740%20%uB370%uC774%uD130%uB97C%20%uC2A4%uD1A0%uC5B4%uC5D0%uC11C%20%uAC00%uC838%uC624%uAC70%uB098%20%uD639%uC740%20%uADF8%uB4E4%uC758%20%uD6C4%uC190%uB4E4%uC5D0%uAC8C%20%uB370%uC774%uD130%uB97C%20%uB0B4%uB824%uC8FC%uB294%uC77C%uC744%20%uC704%uD55C%20%uC811%uCC29%20%uCF54%uB4DC%uB97C%20%uC81C%uACF5%uD55C%uB2E4.%20%uC6B0%uB9AC%uB294%20%uC774%uB7F0%20%uCEE8%uD2B8%uB864%20%uBDF0%uB4E4%uC5D0%uAC8C%20%uC911%uC694%uD55C%20%uC139%uC158%20%uD558%uB098%uB97C%20%uD560%uB2F9%uD574%20%uC8FC%uC5B4%uC57C%20%uD560%20%uAC83%20%uAC19%uB2E4.%0A%0A%uC774%uBCA4%uD2B8%uB97C%20%uC2A4%uD1A0%uC5B4%uC5D0%uC11C%20%uBC1B%uC558%uC744%20%uB54C%2C%20%uC2A4%uD1A0%uC5B4%uC758%20public%20getter%20%uBA54%uC18C%uB4DC%uB4E4%uB85C%20%uD544%uC694%uD55C%20%uC0C8%20%uB370%uC774%uD130%uB97C%20%uBA3C%uC800%20%uC694%uCCAD%uD55C%uB2E4.%20%uC774%uD6C4%20%uC790%uC2E0%uC758%20%60setState%28%29%60%uD639%uC740%20%60forceUpdate%28%29%60%uBA54%uC18C%uB4DC%28%uADF8%uAC83%uC758%20%60render%28%29%60%uBA54%uC18C%uB4DC%uC640%20%uD558%uBD80%20%uC790%uC190%uB4E4%uC758%20%60render%28%29%60%20%uBA54%uC18C%uB4DC%uB4E4%uC744%20%uC2E4%uD589%uD558%uB294%29%uB4E4%uC744%20%uD638%uCD9C%uD55C%uB2E4.%20%0A%uC6B0%uB9AC%uB294%20%uC790%uC8FC%20%uC2A4%uD1A0%uC5B4%uC758%20%uC804%uCCB4%20%uC0C1%uD0DC%28state%29%uB97C%20%uBDF0%uB4E4%uC758%20%uCCB4%uC778%uC774%20%uC788%uB294%20%uD558%uBD80%uB85C%20%uC804%uB2EC%uD55C%uB2E4.%20%uC774%uAC83%uC740%20%uB2E4%uB978%20%uD6C4%uC190%uB4E4%uC774%20%uADF8%uB4E4%uC774%20%uD544%uC694%uB85C%20%uD558%uB294%20%uAC83%uC744%20%uC0AC%uC6A9%uD560%20%uC218%20%uC788%uB3C4%uB85D%20%uD5C8%uB77D%uD55C%uB2E4.%20%uAC8C%uB2E4%uAC00%20%uAC00%uC7A5%20%uCD5C%uC0C1%uC704%uC5D0%uC11C%uB3C4%20%uCEE8%uD2B8%uB864%uB7EC%20%uBE44%uC2B7%uD55C%20%uD589%uB3D9%uC744%20%uC720%uC9C0%uD558%uAE30%2C%20%uB610%20%uC774%uB807%uAC8C%20%uC6B0%uB9AC%uC758%20%uC790%uC190%20%uBDF0%uB4E4%uC744%20%uC720%uC9C0%uD558%uAE30%20%uC704%uD574%2C%20%uAC00%uB2A5%uD55C%uD55C%20%uAE30%uB2A5%uC801%uC73C%uB85C%20%uD4E8%uC5B4%uD558%uAC8C%20%uBAA8%uB4E0%20%uC2A4%uD1A0%uC5B4%uC758%20%uC0C1%uD0DC%uB97C%20%uC2F1%uAE00%20%uC624%uBE0C%uC81D%uD2B8%uB85C%20%uD558%uBD80%uC5D0%20%uC804%uB2EC%uD558%uB294%20%uAC83%uC740%20%uC6B0%uB9AC%uAC00%20%uAD00%uB9AC%uD574%uC57C%uD560%20%uD504%uB85C%uD37C%uD2F0%uB4E4%uC758%20%uC218%uB97C%20%uC904%uC5EC%uC8FC%uB294%20%uD6A8%uACFC%uAC00%20%uC788%uB2E4.%0A%0A%uAC00%uB054%2C%20%uC6B0%uB9AC%uB294%20%uC548%uCABD%28%uCD5C%uC0C1%uC704%uAC00%20%uC544%uB2CC%29%20%uCEE8%uD2B8%uB864%20%uBDF0%uB97C%20%uCEF4%uD3EC%uB10C%uD2B8%uB97C%20%uAC04%uB2E8%uD788%20%uC720%uC9C0%uD558%uAE30%20%uC704%uD574%20%uAC00%uB054%20%uCD94%uAC00%uD560%20%uD544%uC694%uB97C%20%uB290%uB080%uB2E4.%20%uC774%uAC83%uC740%20%uD2B9%uC815%20%uB3C4%uBA54%uC778%uC758%20%uC139%uC158%uC758%20%uACC4%uCE35%uC744%20%uB354%20%uB0AB%uAC8C%20%uCEA1%uC290%uD654%20%uD560%20%uC218%20%uC788%uAC8C%20%uD574%uC8FC%uAE30%uB3C4%20%uD55C%uB2E4.%20%uADF8%uB7EC%uB098%20%uC548%uCABD%uC758%20%uCEE8%uD2B8%uB864%uB7EC%uBDF0%uB294%20%uD558%uB098%uC758%20%uB370%uC774%uD130%20%uD750%uB984%uC744%20%uAE70%20%uC218%uB3C4%20%uC788%uB2E4%uB294%20%uC810%uC744%20%uC54C%uC544%uC57C%uD55C%uB2E4.%20%uC774%uB7F0%20%uCEE8%uD2B8%uB864%20%uBDF0%uB294%20%uC0C8%uB85C%uC6B4%20%uB370%uC774%uD130%20%uD750%uB984%uC744%20%uC704%uD55C%20%uC5D4%uD2B8%uB9AC%20%uD3EC%uC778%uD2B8%uB97C%20%uB9CC%uB4E4%20%uC218%20%uC788%uC73C%uBA70%2C%20%uC774%uB294%20%uC7A0%uC7AC%uC801%uC778%20%uCDA9%uB3CC%20%uAC00%uB2A5%uC131%uC744%20%uAC00%uC9C0%uACE0%20%uC788%uB2E4.%20%uC548%uCABD%uC758%20%uCEE8%uD2B8%uB864%20%uBDF0%uB97C%20%uB9CC%uB4E4%20%uB54C%uB294%20%uAC04%uB2E8%uD55C%20%uCEF4%uD3EC%uB10C%uD2B8%uC758%20%uC774%uC810%uACFC%20%uBCF5%uC7A1%uD55C%20%uB2E4%uC218%uC758%20%uC5C5%uB370%uC774%uD2B8%20%uC0AC%uC774%uC5D0%uC11C%20%uC870%uC728%uC744%20%uD574%uC57C%uD55C%uB2E4.%20%uC774%uB7EC%uD55C%20%uB2E4%uC218%uC758%20%uB370%uC774%uD130%20%uC5C5%uB370%uC774%uD2B8%uB294%20%uC758%uB3C4%uCE58%20%uC54A%uC740%20%uC601%uD5A5%uC744%20%uB9CC%uB4E4%20%uC218%20%uC788%uB294%uB370%2C%20%uB2E4%uB978%20%uCEE8%uD2B8%uB864%uBDF0%uC5D0%20%uC758%uD574%20%uACC4%uC18D%uC801%uC73C%uB85C%20%uD638%uCD9C%uB418%uB294%20React%uC758%20%uB80C%uB354%uB9C1%20%uBA54%uC18C%uB4DC%uC758%20getting%uC5D0%uC11C%20%uADF8%uB807%uB2E4.%20%uADF8%uB9AC%uACE0%20%uC774%uAC74%20%uC7A0%uC7AC%uC801%uC73C%uB85C%20%uB514%uBC84%uAE45%uC758%20%uC5B4%uB824%uC6C0%uC744%20%uC99D%uAC00%uC2DC%uD0AC%20%uC218%20%uC788%uB2E4.%0A%0A%23%20%uC561%uC158%28Actions%29%0A%0A%uC6B0%uB9AC%uAC00%20%uC2A4%uD1A0%uC5B4%uC5D0%uAC8C%20%uBD84%uBC30%28dispatch%29%uB97C%20%uD2B8%uB9AC%uAC70%uD560%20%uC218%20%uC788%uB3C4%uB85D%2C%20%uADF8%uB9AC%uACE0%20%uB370%uC774%uD130%20%uD398%uC774%uB85C%uB4DC%20-%20%uC774%uAC83%uC774%20%uC6B0%uB9AC%uAC00%20%uBD80%uB974%uB294%20%uC561%uC158%20-%20%uB97C%20%uD3EC%uD568%20%uD560%20%uC218%20%uC788%uAC8C%20%uB514%uC2A4%uD328%uCC98%uB294%20%uD55C%20%uBA54%uC18C%uB4DC%uB97C%20%uB178%uCD9C%uC2DC%uD0A8%uB2E4.%20%uC2DC%uBA58%uD2F1%uD55C%20%uD5EC%uD37C%20%uBA54%uC18C%uB4DC%20%uC548%uC5D0%2C%20%uC5D1%uC158%uC758%20%uC0DD%uC131%uC740%20%uC544%uB9C8%20%uB798%uD551%uB418%uC5B4%uC788%uC744%20%uAC83%uC774%uB2E4.%20%uADF8%uAC83%uC740%20%uC561%uC158%uC744%20%uB514%uC2A4%uD328%uCC98%uC5D0%uAC8C%20%uBCF4%uB0B8%uB2E4.%20%uC608%uB97C%uB4E4%uC5B4%2C%20%uC6B0%uB9AC%uB294%20To-do%20%uC544%uC774%uD15C%uC758%20%uAE00%uC790%uB97C%20To-do%20List%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC5D0%uC11C%20%uBC14%uAFB8%uAE38%20%uC6D0%uD560%20%uC218%20%uC788%uB2E4.%20%uC6B0%uB9AC%uB294%20TodoActions%20%uBAA8%uB4C8%20%uC548%uC5D0%20%60updateText%28todoId%2C%20newText%29%60%uAC19%uC740%20%uD568%uC218%uB85C%20%uC561%uC158%uC744%20%uC0DD%uC131%uD55C%uB2E4.%20%uC774%20%uBA54%uC18C%uB4DC%uB4E4%uC740%20%uC544%uB9C8%20%uC6B0%uB9AC%uC758%20%uBDF0%20%uC774%uBCA4%uD2B8%20%uD578%uB4E4%uB7EC%uC5D0%20%uC758%uD574%20%uD638%uCD9C%uB420%20%uAC83%uC774%uB2E4.%20%uC6B0%uB9AC%uB294%20%uC774%uAC83%uC744%20%uC720%uC800%20%uC778%uD130%uB809%uC158%uC758%20%uACB0%uACFC%uB77C%20%uBD80%uB97C%20%uC218%20%uC788%uB2E4.%20%uC774%20%uC561%uC158%20%uC0DD%uC131%20%uBA54%uC18C%uB4DC%uB294%20%uB610%uD55C%20%uC561%uC158%uC5D0%uAC8C%20%uD0C0%uC785%uC744%20%uCD94%uAC00%uD55C%uB2E4.%20%uADF8%uB798%uC11C%20%uC561%uC158%uC774%20%uC2A4%uD1A0%uC5B4%uC5D0%uC11C%20%uD574%uC155%uB420%20%uB54C%2C%20%uC801%uC808%uD558%uAC8C%20%uC751%uB2F5%uD560%20%uC218%20%uC788%uB3C4%uB85D%20%uD55C%uB2E4.%20%uC6B0%uB9AC%uC758%20%uC608%uC2DC%uC5D0%uC11C%uB294%20%uC774%uB7F0%20%uD0C0%uC785%uC740%20%uC544%uB9C8%20TODO_UPDATE_TEXT%uAC19%uC774%20%uC774%uB984%20%uBD99%uC5EC%uC9C8%20%uAC83%uC774%uB2E4.%0A%0A%uC561%uC158%uC740%20%uC544%uB9C8%20%uB2E4%uB978%20%uC7A5%uC18C%uB4E4%uC5D0%uC11C%20%uC62C%uB54C%uB3C4%20%uC788%uB2E4%2C%20%uC11C%uBC84%uAC19%uC740%20%uACF3%uC5D0%uC11C.%20%uC608%uB97C%uB4E4%uC5B4%2C%20%uB370%uC774%uD130%uB97C%20%uCD08%uAE30%uD654%uD558%uB294%20%uB3D9%uC548%20%uC774%uB7F0%uC77C%uC774%20%uC77C%uC5B4%uB09C%uB2E4.%20%uB610%20%uB9C8%uCC2C%uAC00%uC9C0%uB85C%20%uC11C%uBC84%uAC00%20%uC5D0%uB7EC%uCF54%uB4DC%uB97C%20%uBC18%uD658%uD560%uB54C%uB098%20%uD639%uC740%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC744%20%uC5C5%uB370%uC774%uD2B8%uD560%uB54C%20%uAC19%uC744%uB54C%uB3C4%20%uC77C%uC5B4%uB09C%uB2E4.%0A%0A%23%20%uB514%uC2A4%uD328%uCC98%uB97C%20%uC880%20%uB354%20%uBCF4%uBA74%2C%0A%0A%uC544%uAE4C%20%uC598%uAE30%uD588%uC9C0%uB9CC%2C%20%uB514%uC2A4%uD328%uCC98%uB294%20%uC2A4%uD1A0%uC5B4%uB4E4%20%uC0AC%uC774%uC758%20%uB514%uD39C%uB358%uC2DC%uB3C4%20%uAD00%uB9AC%uAC00%20%uAC00%uB2A5%uD558%uB2E4.%20%uC774%uB7F0%20%uAE30%uB2A5%uC740%20%uB514%uC2A4%uD328%uCC98%20%uD074%uB798%uC2A4%uC758%20waitFor%28%29%20%uBA54%uC18C%uB4DC%uB97C%20%uD1B5%uD574%20%uAC00%uB2A5%uD558%uB2E4.%20%uC6B0%uB9AC%uB294%20%uC9C0%uAE08%20%uC774%uB7F0%20%uBA54%uC18C%uB4DC%uB97C%20%uC4F8%20%uD544%uC694%uAC00%20%uC5C6%uB2E4.%20%uC65C%uB0D0%uBA74%20TodoMVC%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC774%20%uAD49%uC7A5%uD788%20%uB2E8%uC21C%uD558%uB2C8%uAE4C.%20%uADF8%uB7EC%uB098%20%uC774%uAC83%uC740%20%uD06C%uACE0%20%uBCF5%uC7A1%uD55C%20%uC560%uD50C%uB9AC%uCF00%uC774%uC158%uC5D0%uC120%20%uD65C%uC131%uD654%uB420%20%uAC83%uC774%uB2E4.%0A%0ATodoStore%uC758%20%uB4F1%uB85D%uB41C%20%uCF5C%uBCA1%20%uC548%uC5D0%uC11C%20%uC6B0%uB9AC%uB294%20%uBA85%uC2DC%uC801%uC73C%uB85C%20%uC9C4%uD589%uC804%uC5D0%20%uB2E4%uB978%20%uB514%uD39C%uB358%uC2DC%uB4E4%uC774%20%uBA3C%uC800%20%uC5C5%uB370%uC774%uD2B8%20%uB418%uB3C4%uB85D%20%uAE30%uB2E4%uB9B4%20%uC218%20%uC788%uB2E4.%20%0A%0A%60%60%60%0Acase%20%27TODO_CREATE%27%3A%0A%20%20Dispatcher.waitFor%28%5B%0A%20%20%20%20PrependedTextStore.dispatchToken%2C%0A%20%20%20%20YetAnotherStore.dispatchToken%0A%20%20%5D%29%3B%0A%0A%20%20TodoStore.create%28PrependedTextStore.getText%28%29%20+%20%27%20%27%20+%20action.text%29%3B%0A%20%20break%3B%0A%0A%60%60%60%0A%0A%60waitFor%28%29%60%uC740%20%uD55C%uAC00%uC9C0%20argument%uB9CC%20%uBC1B%uB294%uB2E4.%20%uADF8%20argument%uB294%20%uB514%uC2A4%uD328%uCC98%uC758%20%uCF5C%uBC31%20%uC800%uC7A5%uC18C%28%uB808%uC9C0%uC2A4%uD2B8%uB9AC%29%20%uC778%uB371%uC2A4%uB2E4.%20%uC774%uAC83%uC744%20%uC6B0%uB9AC%uB294%20dispatch%20tokens%uC774%uB77C%20%uBD80%uB978%uB2E4.%20%uC774%uC640%uAC19%uC774%20waitFor%28%29%uB97C%20%uD638%uCD9C%uD558%uB294%20%uC2A4%uD1A0%uC5B4%uB294%20%uADF8%uAC83%uC774%20%uADF8%20%uC790%uC2E0%uC758%20%uC2A4%uD14C%uC774%uD2B8%uB97C%20%uC5B4%uB5BB%uAC8C%20%uC5C5%uB370%uC774%uD2B8%20%uD574%uC57C%uD558%uB294%uC9C0%20%uC54C%uB824%uC8FC%uAE30%20%uC704%uD55C%20%uB2E4%uB978%20%uC2A4%uD1A0%uC5B4%uC758%20%uC0C1%uD0DC%uC5D0%20%uC758%uC874%uD560%20%uC218%20%uC788%uB2E4.%0A%0A%uB514%uC2A4%uD328%uCC98%20%uD1A0%uD070%uC740%20%uB514%uC2A4%uD328%uCC98%uC5D0%20%uCF5C%uBCA1%uC744%20%uB4F1%uB85D%uD560%20%uB54C%20%60register%28%29%60%uC758%20%uBC18%uD658%uAC12%uC774%uB2E4.%0A%0A%60%60%60%0APrependedTextStore.dispatchToken%20%3D%20Dispatcher.register%28function%20%28payload%29%20%7B%0A%20%20//%20...%0A%7D%29%3B%0A%0A%60%60%60%0A%60waitFor%28%29%60%uC774%uB098%20actions%2C%20action%20creators%20%uADF8%uB9AC%uACE0%20%uB514%uC2A4%uD328%uCC98%uC5D0%20%uB300%uD574%20%uB354%20%uC790%uC138%uD55C%uAC78%20%uC6D0%uD558%uBA74%20%20%5BFlux%3A%20Actions%20and%20the%20Dispatcher%5D%28http%3A//facebook.github.io/react/blog/2014/07/30/flux-actions-and-the-dispatcher.html%29%20%uB97C%20%uBCF4%uC790.

comments powered by Disqus
태그, 트랙백, 검색 상자 토글