brunch

매거진 개발개발

You can make anything
by writing

C.S.Lewis

by 워니 Feb 08. 2018

MobX + React 10분 튜토리얼

상태 관리 솔루션 MobX 튜토리얼 

* 이 글은 MobX의 MobX and React 튜토리얼을 번역한 글입니다.

** 오역 및 오탈자가 있을 수 있습니다. 발견하시면 제보해주세요!




개요

MobX은 간단하고 확장 가능하며 테스트를 거친 상태 관리 솔루션입니다. 이 튜토리얼은 10분 안에 MobX의 중요한 컨셉들을 모두 소개합니다. MobX는 독립적인 라이브러리지만 대부분의 사람들은 React와 함께 사용합니다. 그래서 이 튜토리얼은 MobX와 React의 조합에 중점을 두고 설명합니다.



The core idea

상태는 각 애플리케이션의 핵심입니다. 버그를 만드는 관리가 되지 않는 애플리케이션을 만드는 가장 빠른 방법은 주변의 로컬 변수들과 동기화 되지 않는 상태나 일관성 없는 상태를 만드는 것입니다. 그래서 많은 상태 관리 솔루션들이 상태를 변할 수 없게 만드는 식으로 상태를 수정할 수 있는 방법들을 제한하려고 합니다. 하지만 이 방법은 새로운 문제들을 생성합니다. 데이터를 표준화 해야 하고 참조 무결성이 보장되지 않으며 프로토타입과 같은 유용한 컨셉들을 활용하지 못하게 됩니다.


MobX는 일관성 없는 상태를 만들 수 없도록 주요 문제를 해결하여 상태 관리를 간단하게 만들었습니다. 이를 위한 전략은 간단합니다. 애플리케이션 상태로부터 파생될 수 있는 모든 것들을 자동으로 파생되도록 하는 것입니다.


개념적으로 MobX는 애플리케이션을 스프레드시트로 간주합니다.

1. 가장 먼저 애플리케이션 상태가 있습니다. 애플리케이션의 모델을 채우는 객체, 배열, 원시, 참조의 그래프입니다. 이 값들은 애플리케이션의 "데이터 셀"입니다.

2. 둘째로 파생 값이 있습니다. 기본적으로 애플리케이션으로부터 자동으로 계산될 수 있는 모든 값들입니다. 이 파생 값이나 계산된 값들은 완료되지 않은 todo들의 수와 같이 간단한 값부터 todo의 시각적 HTML 표현과 같은 복잡한 내용까지 다양합니다. 스프레드시트 용어로는 애플리케이션의 공식이나 차트가 있습니다.

3. 리액션은 파생 값과 매우 비슷합니다. 주된 차이점은 값을 생성하지 않는 함수라는 점입니다. 대신 자동으로 특정 작업들을 수행시킵니다. 대체로 I/O와 관련된 작업입니다. 리액션은 적당할 때에 자동으로 DOM이 업데이트되거나 네트워크 요청을 하도록 만듭니다.

4. 마지막으로 액션이 있습니다. 액션은 상태를 변경하는 모든 것들을 말합니다. MobX는 모든 사용자의 액션으로 발생하는 상태 변화들이 전부 자동으로 파생 값과 리액션으로 처리되도록 합니다. 동기화되고 결함이 없습니다.



간단한 todo store

이론은 충분합니다. 위의 내용을 유심히 읽는 것보다 실제 예시를 보는 것이이해하기 아마도 더 쉽습니다. 아주 간단한 ToDo store을 가지고 시작해봅시다. 아래의 모든 코드 블록들은 수정이 가능하므로 run code  버튼을 클릭하여 실행시킬 수 있습니다. 아래의 코드는  todo 목록이 포함된 매우 직관적인 TodoStore입니다. MobX는 아직 포함되지 않았습니다.


우리는 todos 목록이 있는 todoStore 인스턴스를 이제 막 만들었습니다. 어떤 객체들로 todoStore을 채울 시간입니다. 변경 사항들을 보기 위해 각 변화 이후에 todoStore.report를 호출하고 로그를 남깁니다. 레포트는 의도적으로 항상 첫 번째 할 일만 출력합니다. 이 때문에 예시가 좀 인위적이지만 아래에서 볼 수 있듯이 MobX의 의존성 추적이 동적임을 잘 보여줍니다.


결과:



반응형으로 만들기

지금까지 이 코드에서 특별한 것은 아무것도 없었습니다. 그러나 report를 명시적으로 호출할 필요가 없다면 어떨까요? 각 상태가 변할 때마다 report가 호출되길 원한다고 선언할 수 있습니까? 그러면 report에 영향을 줄 수도 있는 모든 코드에서 report를 호출해야 합니다. 최신의 report가 출력되기를 원하지만 그것을 모두 작성하고 싶지는 않습니다.


운이 좋게도 이것은 MobX가 여러분을 위해 동작하는 것입니다. 자동으로 상태에 연관되어 있는 코드를 실행합니다. 그래서 report 함수는 스프레드시트의 차트와 같이 자동으로 업데이트 됩니다. 이를 위해 TodoStore를 관찰할 수 있어야 MobX가 모든 변경 사항들을 추적할 수 있습니다. 이를 수행하도록 클래스를 변경해봅시다.


또한 completedTodosCount 속성은 자동으로 todo 목록에서 파생될 수 있습니다. @observable@computed 데코레이터를 사용하여 객체에서 관찰할 수 있는 속성들을 생성할 수 있습니다.


이게 끝입니다! 시간에 따라 변할 수 있는 값들을 MobX에게 알려주기 위해 @observable를 표시했습니다. 계산은 상태로부터 파생될 수 있는 것들을 확인하기 위해 @computed를 사용하여 표시됩니다.


pendingRequrestsassignee 속성들은 지금까지 사용되지 않았지만 앞으로 이 튜토리얼에서 사용됩니다. 이 페이지의 모든 예시들을 짧게 만들기 위해 ES6와 JSX 그리고 데코레이터를 사용합니다. MobX의 모든 데코레이터들은 ES5 부분들을 가지고 있으니 걱정하지 마세요.


생성자에 report를 출력하는 작은 함수를 만들고 autorun으로 감쌌습니다. Autorun은 한 번 동작되는 리액션을 만들고 함수 안에서 사용되는 관찰 가능한 모든 데이터들이 변경될 때마다 자동으로 다시 실행합니다. report는 관찰 가능한 todos 속성을 사용하기 때문에 적절할 때 레포트를 출력합니다. 이것은 다음 리스트에서 설명됩니다. 실행 버튼을 눌러보세요:


report은 자동으로 동시에 중간 값을 빼먹지 않고 출력하였습니다. 유심히 로그를 보면 새로운 로그에서는 4번째 줄이 없는 것을 발견할 수 있습니다. 뒤의 데이터가 변경되는 것으로 report가 실제로 변경되지 않기 때문입니다. 반면에 첫 번째 할일의 이름이 바뀐 것은 report에서 실제로 사용되는 이름이기 때문에 report를 업데이트 하였습니다. 이것은 todos 배열이 autorun에 의해 관찰되는 것이 아니라 todo 아이템들 안에 있는 개별적인 속성을 관찰하고 있다는 것을 잘 설명해줍니다.



반응형 React 만들기

지금까지 바보 같은 report를 반응형으로 만들었습니다. 이제 이 store에서 반응형 유저 인터페이스를 만들 시간입니다. React 컴포넌트들은 이름값을 못하고 반응형이 아닙니다. mobx-react 패키지의 @observer 데코레이터는 React 컴포넌트 render 함수를 autorun으로 감싸 자동으로 상태에 따라 컴포넌트가 동기되도록 만듭니다. 개념적으로 이전에 report를 가지고 했던 것과 다르지 않습니다.


다음 코드는 몇 개의 React 컴포넌트를 정의합니다. 이 안의 MobX는 @observer 데코레이터 뿐입니다. 이것으로 충분히 데이터가 변경될 때 각 컴포넌트가 개별적으로 다시 렌더링하도록 만들 수 있습니다. 더이상 setState를 호출할 필요가 없으며 설정이 필요한 셀렉터나 상위 컴포넌트를 사용하는 상태의 적절한 부분을 찾을 필요도 없습니다. 기본적으로 모든 컴포넌트들은 더 똑똑해졌지만 아직 부족합니다.


아래의 코드를 보기 위해 run code 버튼을 클릭하세요. 코드는 수정이 가능하므로 자유롭게 동작시킬 수 있습니다. 예를 들어 @observer 호출을 모두 지우거나 TodoView의 데코레이터만 지워보세요. 오른쪽의 미리보기에서 숫자들은 컴포넌트가 렌더링될 때마다 표시합니다. 


다음 코드는 다른 작업을 수행하지 않고 데이터를 변경해야 한다는 것을 잘 보여줍니다. MobX는 자동으로 store의 상태에 따라 유저 인터페이스의 적절한 부분들을 다시 파생하고 업데이트합니다.



참조 사용하기 

지금까지 관찰가능한 객체(프로토타입과 일반 객체 둘 다)와 배열, 원시를 만들었습니다. MobX에서 참고를 다루는 방법에 대해 궁금하지 않나요? 상태가 그래프를 형성할 수 있나요? 이전 코드에서는 todos의 assignee 속성이 있는 것을 알았을 것입니다. 또 다른 "store"을 생성하여 assignee에 포함되는 사람들의 값을 전달하고 그들에게 할일이 할당해줍시다.


두 개의 독립적인 store이 있습니다. 하나는 사람들이 있고 하나는 할 일들이 있습니다. 사람 store의 사람을 assignee에 할당하기 위해 참조를 할당했습니다. 변경사항들은 TodoView에 의해 자동으로 선택됩니다. MobX를 사용하면 데이터를 표준화할 필요가 없고 업데이트될 컴포넌트들을 지정하기 위해 셀렉터를 작성할 필요가 없습니다. 실제로 데이터가 어디에 저장되는지는 중요하지 않습니다. 오랫동안 객체들은 관찰가능하게 만들어졌고 MobX는 그것들을 추적할 수 있습니다. 실제 JavaScript 참조가 동작합니다. MobX는 파생과 관련이 있으면 자동으로 그것들을 추적합니다. 테스트 해보기위해 다음의 인풋 박스에 이름을 변경해보세요. (먼저 위의 Run code 버튼을 클릭했는지 확인해보세요)


위의 인풋 박스의 HTML은 간단합니다:



비동기 액션

작은 Todo 애플리케이션에 있는 모든 것들은 상태로부터 파생되기 때문에 언제 상태가 변화하는지는 중요하지 않습니다. 비동기 액션을 만드는 것은 매우 수월합니다. 새로운 할일 아이템을 비동기적으로 로드하려면 아래의 버튼을 여러번 클릭하세요.


코드는 매우 직관적입니다. UI가 현재 로딩되는 상태를 반영하도록 store의 pendingRequests 속성을 업데이트하는 것으로 시작합니다. 로딩이 끝날 때 store의 todos를 업데이트하고 pendingReqeust 카운터를 증가시킵니다. 이 스니펫을 이전 TodoList 정의와 비교하여 pendingRequests 속성이 어떻게 사용되는지 확인하세요.



개발자 도구

mobx-react-devtools 패키지는 화면의 오른쪽 최상단에서 찾을 수 있고 모든 Mobx+ReactJS 애플리케이션 내에서 사용할 수 있는 개발자 도구를 제공합니다. 첫 번째 버튼을 클릭하면 각 다시 렌더링되는 @observer 컴포넌트가 표시됩니다. 두 번째 버튼을 클릭하고 미리보기에서 해당 컴포넌트 중 하나를 클릭하면 해당 컴포넌트의 종속성 트리가 표시되므로 주어진 순간에 관찰중인 데이터 조각을 정확하게 검사할 수 있습니다.



결론

끝났습니다! 관용구는 없습니다. 완전한 UI를 형성하는 간단하고 선언적인 컴포넌트들입니다. 그리고 상태로부터 완전하고 반응형으로 파생됩니다. 여러분의 애플리케이션에서 mobx와 mobx-react를 사용하기 시작할 준비가 되었습니다. 지금까지 배운 것들을 짧게 요약하였습니다:

1. MobX가 객체들을 관찰할 수 있도록 @observable 데코레이터 또는 observable(객체 혹은 배열)을 사용하세요.

2. @computed 데코레이터는 상태로부터 자동으로 파생되는 함수를 만들기 위해 사용될 수 있습니다.

3. 관찰 가능한 상태에 의존하는 함수들을 자동으로 실행하기 위해 autorun을 사용하세요. 로깅하거나 네트워크 요청하기에 유용합니다.

4. React 컴포넌트를 진짜 반응형으로 만들기 위해 mobx-react 패키지의 @observer 데코레이터를 사용하세요. 자동으로 효율적으로 업데이트합니다. 심지어 많은 양의 데이터가 있는 아주 복잡한 애플리케이션에서도 사용됩니다.


위의 수정 가능한 코드 블록을 사용하여 조금만 더 만져보면 MobX가 모든 변경 사항에 어떻게 반응하는지 기본적인 느낌을 얻을 수 있습니다. 예를 들어 언제 호출되는지 보기 위해 report 함수에 로그를 추가하거나 report를 출력하지 않고 이것이 TodoList 렌더링에 어떤 영향을 주는지 확인하세요. 아니면 특정 상황에서만 출력하세요...



MobX는 상태 컨테이너가 아닙니다

사람들은 종종 MobX를 Redux의 대안으로 사용합니다. MobX는 기술적인 문제를 해결하는 라이브러리일 뿐이며 아키텍처나 상태 컨테이너가 아닙니다. 그러한 의미에서 위의 예시들이 고안된 것으로 메서드에서 로직을 캡슐화하거나 store나 컨트롤러에서 구성하는 것과 같은 적절한 엔지니어링 기법을 사용하는 것이 좋습니다. 또는 HackerNesw의 누군가는 이렇게 말했습니다:

"MobX는 많은 곳에서 언급되었지만 나는 마냥 좋다고 말할 수 없습니다. MobX로 작성하는 것은 컨트롤러/디스패처/액션/슈퍼바이저 또는 다른 형태의 데이터 흐름을 관리하여 애플리케이션의 요구 사항을 패턴화할 수 있습니다."


브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari