11 Vuex - 소개

source: categories/study/vue-beginner-lv2/vue-beginner-lv2_9-02.md

11.1 Vuex 소개

Vuex - 상태 관리 라이브러리

개요

  • 복잡한 애플리케이션의 컴포넌트들을 효율적으로 관리하는 Vuex 라이브러리 소개
  • Vuex 라이브러리의 등장 배경인 Flux 패턴 소개

    Vuex를 쓰는 이유는 단순합니다.
    컴포넌트가 정말 많아졌을 때, 관리할 수 있는 방법이 무엇일까? 라고 Vue 코어팀에서 분명히 고민을 했을것이고
    특히 이제 리액트나 앵귤러의 장점들을 결합하는 과정에서..
    리액트에서 이미 Flux라는 패턴으로 그런 복잡한 애플리케이션의 문제점을.. 무수히 많은 컴포넌트들로부터 야기되는 관리의 문제점을 해결하고 있었고,
    그래서 그 Flux 패턴을 Vuex에 그대로 도입을 했고,
    나름대로 Vue의 Reactivity와 Flux가 같이 공존할 수 있는 방향으로 Vuex를 만들어냈습니다.

    리액트와 뷰는 서로 굉장히 닮아있습니다.

    그래서 Flux를 먼저 소개를 해드릴겁니다.
    그거를 아셔야지, 왜 MVC 패턴에서 Flux 패턴으로 넘어왔는지 그것도 아셔야돼고, 그리고 Flux 패턴이 어떤거였는지, 그리고 그것이 Vuex와 어떻게 다른지,
    이렇게 다 연결해서 학습하셔야된다고 생각합니다.

  • Vuex 라이브러리의 주요 속성인 state, getters, mutations, actions 학습

    Vuex에서 가장 어렵게 느껴지는 부분이 위 4가지입니다.
    상태관리, 어떤 상태라는 것에 대한 개념을 이해하기 전에.. 실제로 용어 자체도 낯설죠?
    솔직히 저는 아직도 왜 이렇게 명명을 했는지 잘 모르겠습니다.
    저희가 여태까지 배웠던 개념들을 생각하며 쉽게 지어보면

    • statedata 프로퍼티입니다.
    • getterscomputed입니다.
    • mutationsmethods입니다.
    • actions비동기 메소드입니다.
  • Vuex를 더 쉽게 코딩할 수 있는 방법인 Helper 기능 소개

    Helper 함수를 활용하면 Vuex를 좀 더 쉽게 활용할 수 있다.

  • Vuex로 프로젝트를 구조화하는 방법과 모듈 구조화 방법 소개

목차

  • Vuex 라이브러리 소개
  • Flux 패턴 소개
  • Vuex 컨셉과 구조
  • Vuex 설치 및 시작하기
  • Vuex 기술 요소 (state, getters, mutations, actions)
  • Vuex Helpers
  • Vuex로 프로젝트 구조화 및 모듈화하는 방법

Vuex란?

  • 무수히 많은 컴포넌트 데이터를 관리하기 위한 상태 관리 패턴이자 라이브러리
  • React의 Flux 패턴에서 기인함
  • Vue.js 중고급 개발자로 성장하기 위한 필수 관문

11.2 Flux와 MVC 패턴 소개 및 Flux 등장 배경

Vuex란?

  • 무수히 많은 컴포넌트 데이터를 관리하기 위한 상태 관리 패턴이자 라이브러리
  • React의 Flux 패턴에서 기인함
    리액트에서 Flux 패턴을 많이 쓰는데, 거기서 기인한 뷰만의 상태관리 라이브러리 또는 패턴이라고 보시면됩니다.
    그리고 앱이 커졌을 때 효율적으로 관리할 수 있는 가장 효과적인 방법입니다.
  • Vue.js 중고급 개발자로 성장하기 위한 필수 관문

Flux란?

Flux를 먼저 보시고 왜 이런 패턴이 생겨났는지에 대한 이야기를 해볼겁니다.
Flux를 간단하게 정의하면 다음과 같습니다.

Note

페이스북 개발자들이 MVC 패턴으로 계속 개발을하다가 리액트를 쓰고하다보니 MVC 패턴에서 야기되는 문제점이 되게 많더란말이죠.
예들들어서 페이스북을 생각하셨을 때, 채팅창이있고 맨 위에 상태관리바가 있고, 메인화면에 여러가지 뷰들이 많잖아요?
한개의 뷰가 바뀌었을 때 다른 뷰에서 데이터 추적하는게 굉장히 어렵습니다.
왜냐하면 페이스북처럼 거대한 앱들은 전체적인 앱의 흐름을 추적하기 어렵기 때문입니다.
그 이유가 MVC 패턴이었기 때문에.. (아 진짜 뭐라는거야.. 이해가 되게 설명을해.. 얘는 이론설명할 때는 완전 꽝인거같음..)
그래서 Flux를 만들었습니다.

  • MVC 패턴의 복잡한 데이터 흐름 문제를 해결하는 개발 패턴 - Unidirectional data flow

아래를 보시면 방향이 한 방향입니다.
action 부터 view까지.

Note

즉, 이전에 컨테이너 컴포넌트, 프레젠테이셔널 컴포넌트로 구분하면서 했던 그 이유인가보네?
MVC 패턴은 데이터의 흐름이 복잡하다. 그래서 컨테이너, 프레젠테이셔널 컴포넌트로 구분해서 작업했다. 이런거네?
근데 MVC 패턴이 왜 데이터의 흐름이 그럴수밖에 없는지, 즉, 왜 복잡하게될수밖에 없는지에 대해서부터 설명해줘야하는거 아닌가…
여튼 강의에선 이런말 같네..
MVC는 여튼 그런 문제점을 가지고 있다고함.

여튼 Unidirectional data flow라고해서 무조건 모든 데이터의 흐름이 한 방향으로만 움직입니다.
요런것들이 이제 저희가 뷰를 학습했을 때, 항상 데이터가 상위에서 하위, 그러니까 부모에서 자식으로 내려갈 때는 부모에서 자식으로 props만 내리고,
자식이 부모에게 보낼 수 있는 것은 event뿐!이라는 거죠.
그런 것들이 데이터 흐름을 제한하면서, 좀 복잡해졌을 때 발생될 수 있는 문제들을 미리 방지하는거죠.
마찬가지로 Flux도 아래와 같이 단방향 통신을 하고있습니다.

Action -> Dispatcher -> Model -> View
  1. action: 화면에서 발생하는 이벤트 또는 사용자의 입력 (클릭 같은 거)
  2. dispatcher: 데이터를 변경하는 방법, 메서드 (모델을 바꾸기위한 역할. 즉, 이것이 데이터를 변경하는 방법, 메서드)
  3. model: 화면에 표시할 데이터
  4. view: 사용자에게 비춰지는 화면 (action은 이 화면에서 드러나겠죠? 이 view에서 action을 호출할겁니다. 단방향 루프)

이렇게 Flux라는 패턴은 이렇게 단방향 데이터 흐름을 가지고있습니다.
이것이 Flux의 핵심

MVC 패턴과 Flux 패턴 비교

  1. MVC 패턴
  Controller -> Model -> View
                      <-

MVC 패턴은 굉장히 오래전부터 사용되어왔던 개발 패턴입니다.
기본적으로 View, Model, Controller라는 3개의 주요 요소로 개발을합니다.
영역을 구분하는겁니다.
View는 저희가 보고있는 화면입니다.
화면에서 찍혀나오는 텍스트들.. 그걸 만약 DB에서 가지고왔으면 그건 Model입니다.
DB에서 가져왔다기보단 텍스트가됐건 이미지가됐건 그런 것들은 전부 다 Model에 담기는거죠.
그리고 ControllerModelView를 제어하는 역할을합니다.
데이터처리가 다양한 방향으로 일어납니다.

  1. Flux 패턴
  Action -> Dispatcher -> Model -> View

Flux 같은 경우는 Action부터 View까지 단방향으로 위와 같이 일어납니다.

다시 MVC 패턴으로 가시면 Model과 View가 서로 데이터를 주고받을 수 있습니다.
양방향으로 일어나고있습니다.
그럼 이러한 Model과 View가 많아지면 어떤 문제점이 일어날까요?

MVC 패턴의 문제점

  • 기능 추가 및 변경에 따라 생기는 문제점을 예측할 수가 없음. (예) 페이스북 채팅 화면
  • 앱이 복잡해지면서 생기는 업데이트 루프

MVC 패턴의 문제점이 위에서도 잠깐 말씀드렸지만 Controller가 하나가 있고, Model과 View가 엄청나게 많습니다.
그럼 위 이미지처럼 맨 위의 Model에서 View를 갱신했습니다.
그럼 그 View가 또 다른 Model을 갱신하고,
그 Model이 또 다른 View를 갱신하고,
또 그 View가 또 다른 Model을 갱신하고…

이렇게 왔다갔다하는데 이렇게되면 도저히 data의 흐름을 추적할 수가 없습니다.
이렇게되면 데이터의 흐름을 추적할 수가 없기 때문에 어떤 문제점, 버그가 생기는지 알 수가 없습니다.

Flux 패턴의 단방향 데이터 흐름

  • 데이터 흐름이 여러 갈래로 나뉘지 않고 단방향으로만 처리

아까 말씀드린 것처럼 데이터 흐름이 단방향이기 때문에 데이터 흐름에 대한 예측이 가능합니다.
저희 Vue 컴포넌트만봐도 그렇죠?
상위 컴포넌트가 하위 컴포넌트로 props 내리겠는데?
하위 컴포넌트는 상위 컴포넌트로 event를 올리겠네?
이런식으로 예측이 가능하잖아요?

그런식으로 프레임워크 자체, 어떤 패턴 자체에서 데이터의 흐름을 정형화시켜서.. 향후에 발생할 수 있는 문제점들을 미리 방지하는 것들..
좀 더 safe한 코딩이라고 표현을 많이 하는데,
그런식으로 안전성있게 코딩할 수 있는 것 같습니다.

Note
  1. action: 화면에서 발생하는 이벤트 또는 사용자의 입력 (클릭 같은 거)
  2. dispatcher: 데이터를 변경하는 방법, 메서드 (모델을 바꾸기위한 역할. 즉, 이것이 데이터를 변경하는 방법, 메서드)
  3. model: 화면에 표시할 데이터
  4. view: 사용자에게 비춰지는 화면 (action은 이 화면에서 드러나겠죠? 이 view에서 action을 호출할겁니다. 단방향 루프)

action이 발생해서 dispatcher가 동작을 하는거고, dispatcher가 하는 역할은 store(model, data)를 바꾸고 store가 바뀌면 store에 의해서 view 즉, 화면이 갱신이됩니다.
또 view 즉, 화면단에서 사용자가 입력을하면 action이 발생하겠죠?
action이 발생해서 다시 dispatcher가 동작하고..
위 사이클이 반복되는겁니다.

데이터 단방향 흐름.

11.3 Vuex가 필요한 이유, Vuex 컨셉, Vuex 구조

Vuex가 왜 필요할까?

  • 복잡한 애플리케이션에서 컴포넌트의 개수가 많아지면 컴포넌트간에 데이터 전달이 어려워진다.

애플리케이션이 커지고 복잡해질수록 컴포넌트의 갯수도 많아지고 복잡해진다.
위를 보면 루트 컴포넌트 아래에 몇개의 하위 컴포넌트가 있는지 제대로 파악하는 것도 힘들어진다.
그리고 위와 같이 하위 컴포넌트의 하위 컴포넌트의 하위 컴포넌트의 하위 컴포넌트의…
이런식의 구조가 될수밖에 없다. 어플리케이션이 커지면.

저희가 일반적으로 알고있는 props 또는 event 전달방식을 사용하면, props는 일단 중간 컴포넌트마다 다 props를 전달해서 거쳐가도록 해야되잖아요?
그러면 굉~장히 불편해집니다.
즉, 위와 같이 컴포넌트의 갯수가 많아지면 많아질수록 데이터 전달이 번거로워지고 복잡해지는데,
이런 것들을 이벤트 버스로 해결할 수도 있겠죠?

이벤트 버스로 해결?

  • 어디서 이벤트를 보냈는지 혹은 어디서 이벤트를 받았는지 알기 어려움
// Login.vue
eventBus.$emit('fetch', loginInfo);

// List.vue
eventBus.$on('display', data => this.displayOnScreen(data));

// Chart.vue
eventBus.$emit('refreshData', chartData);

컴포넌트 간 데이터 전달이 명시적이지 않음

Note

v-on, v-bind를 안쓰고 Vuex도 안쓰고 난 eventBus를 사용할거야! 라고 하실 수 있습니다.
그래서 eventBus로 하시게되면 위와 같은 식으로
Login.vue에선 이벤트를 발생시키고
List.vue에선 이벤트를 받고
Chart.vue에선 이벤트를 발생시키고

이런식으로 해결하실 수 있습니다.
그런데 이건 또 문제점이뭐냐면, 위와 같이 딱 봐도 컴포넌트가 3개고 각각의 이벤트명도 다릅니다.
그럼 이걸 어디서 받는지 잘 추적도 안될겁니다.
특히 지금 예시는 컴포넌트가 3개뿐인데, 보통 vue로 개발하다보면 컴포넌트를 10개 이상은 만들게됩니다.

그랬을때 컴포넌트간 데이터 전달이 어떤식으로되는지 외우기는 거의 불가능해집니다.
그런부분들이 컴포넌트간 데이터전달이 명시적이지 않게되는 것이죠.

결국 이렇게 중간에 거쳐야될 컴포넌트들이 많을 때 props 전달이 번거롭다는 점과
eventBus로 데이터를 전달했을 때 명시적이지 않다는 문제점을 바로 Vuex가 해결해줍니다.

Vuex로 해결할 수 있는 문제

  1. MVC 패턴에서 발생하는 구조적 오류
  2. 컴포넌트간 데이터 전달 명시
    특히 이번 강의에서 저희가 어떤 요소들을 배우고 리팩토링하는 과정에서 저희가 vue 개발자도구로 계속 디버깅을 할텐데,
    디버깅에서 얼마나 데이터전달이 명시적으로되는지,
    그리고 그 데이터의 구체적인 내용들,
    모두 뷰 개발자도구로 확인할 수 있거든요. 그런 부분들에 대해 살펴볼 예정입니다.
  3. 여러 개의 컴포넌트에서 같은 데이터를 업데이트할 때 동기화 문제
    이를 위해 mutation이 있고 actions가 있었습니다.
    그런 것들을 이용해서 동기화 문제들도 다 해결할 수 있습니다.
Note
  • statedata 프로퍼티입니다.
  • getterscomputed입니다.
  • mutationsmethods입니다.
  • actions비동기 메소드입니다.

Vuex 컨셉

  • State: 컴포넌트 간에 공유하는 데이터 data()
    보통 ‘상태'라고 말을 많이합니다.
    영어 단어 뜻 자체도 ‘상태'라는 뜻인데, State는 컴포넌트 간에 공유하는 데이터를 뜻합니다. 그냥 State라고 하면 안와닿는데, 이런식으로 비유를 하면 이해하기 쉽거든요?
    저희가 TodoApp을 만들 때도 data 프로퍼티를 많이 생성하셨었잖아요?
    그게 State입니다. State는 결국 data 프로퍼티입니다.
    ‘State는 여러 컴포넌트에서 사용하는 data 프로퍼티'이다.

  • View: 데이터를 표시하는 화면 template

  • Action: 사용자의 입력에 따라 데이터를 변경하는 methods

단방향 데이터 흐름 처리를 단순하게 도식화한 그림

위 그림은 정말 단순한 그림입니다.
아까 제가 알려드렸던 Flux를 생각해보면.. Flux도 단방향이었죠?
Vuex도 마찬가지로 단방향입니다.
그게 일단 공통점이고, 위 그림은 Vuex 기술 요소를 다 나열해놓지않고 간단한 컨셉을 보여주는 그림인데, 먼저 보실거는 state, view, action입니다.

Note

State, View, Action을 각각 보면 어려운데 위와 같이 비유를 통해보면 어렵지 않습니다.
저희가 이미 vue 실습하면서 다 다뤘던 것들입니다.

View(= template) 화면에서 버튼을 클릭하면 v-on:click="addTodo"를 통해서 메소드가 실행된다.
이것이 Action(= methods)이다.
그럼 Action이 this.todoItems.push() 이런걸 통해서 State(= data)를 변경했다.

이런식으로 Vuex 컨셉이 돌아가고 중요한 것은 단방향 데이터 흐름이라는거.
그것이 가장 중요한 핵심입니다.

Vuex 구조

위 그림을 단순화해서 적어놓은게 바로

컴포넌트 -> 비동기 로직 -> 동기 로직 -> 상태

위 흐름입니다.
컴포넌트에서 비동기로직, 동기로직, 상태 순으로 흐릅니다.

Vue Components에서 Actions, 즉 비동기로직(= Actions), 비동기 메서드라고 보시면됩니다.
저희가 메서드를 많이 선언을 했었는데, 한번도 setTimeout이라던지 아니면 서버로 데이터를 주고받는 API call 같은건 하진 않았습니다.
그런데 보통 그런 것들을 Actions에서 처리를 합니다.
Actions는 그런 비동기로직만을 처리하는거고 데이터를 바꾸진않습니다.
Actions에서 data를 바꿀 수 있는 Mutations를 콜하고 Mutations에서만 data(=state)를 바꿀 수 있습니다.
Mutations 역시 메소드입니다.
Mutations는 동기 메서드입니다.

위 그림을보시면 Backend API, Dispatch, Commit, Devtools, Mutate, Render.. 별개 다있죠?
이것들은 지금 다 모르셔도됩니다.
중요한 것은 위와 같은 흐름으로 돈다는 것만 이해하시면됩니다.

이번 강의에서 저희가 집중적으로 다룰 부분은 MutationsDevtools 부분입니다.
그리고 나중에 이 강의를 다 들으시고나면 실무에서 충분히 ActionsBackend API를 연동해서 사용하실 수 있을겁니다.
제 초급 강의에선 axios를 많이 다루고있는데, ActionsBackend API를 연동하는 부분이 axios를 통해 연동하기만하면 되는거거든요.

결론적으로는 위 그림에대해 이해 못하시더라도 이 강의를 다 듣고나시면 이해를 하실 수 있으실거라고 생각합니다.