Browse Source

[docs:korean] Migrate git-book to vuepress (#1291)

* korean document change to vuepress

* docs: using vuepress

* docs: api reference is updated

* docs:kr: Promise translate

* docs:kr: Method-Style Access translate

* docs:kr module document is updated

* docs:kr plugins document is updated

* docs:kr testing document is updated

* update module document

* docs:ko fix hash link
usolkim 7 years ago
parent
commit
9548ee4a7b

+ 45 - 0
docs/.vuepress/config.js

@@ -19,6 +19,11 @@ module.exports = {
       lang: 'ru',
       title: 'Vuex',
       description: 'Централизованное управление состоянием для Vue.js'
+    },
+    '/kr/': {
+      lang: 'kr',
+      title: 'Vuex',
+      description: 'Vue.js의 중앙 상태 관리'
     }
   },
   serviceWorker: true,
@@ -189,6 +194,46 @@ module.exports = {
           '/ru/guide/testing',
           '/ru/guide/hot-reload'
         ]
+      },
+      '/kr/': {
+        label: '한국어',
+        selectText: '언어 변경',
+        editLinkText: 'GitHub에서 이 페이지 수정',
+        nav: [{
+            text: '가이드',
+            link: '/kr/guide/'
+          },
+          {
+            text: 'API 레퍼런스',
+            link: '/kr/api/'
+          },
+          {
+            text: '릴리즈 노트',
+            link: 'https://github.com/vuejs/vuex/releases'
+          }
+        ],
+        sidebar: [
+          '/kr/installation',
+          '/kr/',
+          '/kr/guide/',
+          {
+            title: '핵심 컨셉',
+            collapsable: false,
+            children: [
+              '/kr/guide/state',
+              '/kr/guide/getters',
+              '/kr/guide/mutations',
+              '/kr/guide/actions',
+              '/kr/guide/modules'
+            ]
+          },
+          '/kr/guide/structure',
+          '/kr/guide/plugins',
+          '/kr/guide/strict',
+          '/kr/guide/forms',
+          '/kr/guide/testing',
+          '/kr/guide/hot-reload'
+        ]
       }
     }
   }

+ 3 - 0
docs/.vuepress/public/_redirects

@@ -11,3 +11,6 @@
 
 /ru/api.html  /ru/api/
 /ru/* /ru/guide/:splat
+
+/kr/api.html  /kr/api/
+/kr/* /kr/guide/:splat

+ 63 - 0
docs/kr/README.md

@@ -0,0 +1,63 @@
+# Vuex가 무엇인가요?
+
+Vuex는 Vue.js 애플리케이션에 대한 **상태 관리 패턴 + 라이브러리** 입니다. 애플리케이션의 모든 컴포넌트에 대한 중앙 집중식 저장소 역할을 하며 예측 가능한 방식으로 상태를 변경할 수 있습니다. 또한 Vue의 공식 [devtools 확장 프로그램](https://github.com/vuejs/vue-devtools)과 통합되어 설정 시간이 필요 없는 디버깅 및 상태 스냅 샷 내보내기/가져오기와 같은 고급 기능을 제공합니다.
+
+### "상태 관리 패턴"이란 무엇인가요?
+
+간단한 Vue 카운터 앱부터 시작 해보겠습니다.
+
+``` js
+new Vue({
+  // 상태
+  data () {
+    return {
+      count: 0
+    }
+  },
+  // 뷰
+  template: `
+    <div>{{ count }}</div>
+  `,
+  // 액션
+  methods: {
+    increment () {
+      this.count++
+    }
+  }
+})
+```
+
+다음과 같은 기능을 가진 앱입니다.
+
+- **상태** 는 앱을 작동하는 원본 소스 입니다.
+- **뷰** 는 **상태의** 선언적 매핑입니다.
+- **액션** 은 **뷰** 에서 사용자 입력에 대해 반응적으로 상태를 바꾸는 방법입니다.
+
+이것은 "단방향 데이터 흐름" 개념의 매우 단순한 도표입니다.
+
+<p style="text-align: center; margin: 2em">
+  <img style="width:100%;max-width:450px;" src="/flow.png">
+</p>
+
+그러나 **공통의 상태를 공유하는 여러 컴포넌트** 가 있는 경우 단순함이 빠르게 저하됩니다.
+
+- 여러 뷰는 같은 상태에 의존합니다.
+- 서로 다른 뷰의 작업은 동일한 상태를 반영해야 할 수 있습니다.
+
+첫번째 문제의 경우, 지나치게 중첩된 컴포넌트를 통과하는 prop는 장황할 수 있으며 형제 컴포넌트에서는 작동하지 않습니다. 두번째 문제의 경우 직접 부모/자식 인스턴스를 참조하거나 이벤트를 통해 상태의 여러 복사본을 변경 및 동기화 하려는 등의 해결 방법을 사용해야 합니다. 이러한 패턴은 모두 부서지기 쉽고 유지보수가 불가능한 코드로 빠르게 변경됩니다.
+
+그렇다면 컴포넌트에서 공유된 상태를 추출하고 이를 전역 싱글톤으로 관리해야 합니다. 이를 통해 우리의 컴포넌트 트리는 커다란 "뷰"가 되며 모든 컴포넌트는 트리에 상관없이 상태에 액세스하거나 동작을 트리거 할 수 있습니다!
+
+또한 상태 관리 및 특정 규칙 적용과 관련된 개념을 정의하고 분리함으로써 코드의 구조와 유지 관리 기능을 향상시킵니다.
+
+이는 [Flux](https://facebook.github.io/flux/docs/overview.html), [Redux](http://redux.js.org/), [The Elm Architecture](https://guide.elm-lang.org/architecture/)에서 영감을 받은 Vuex의 기본 아이디어 입니다. 다른 패턴과 달리 Vuex는 Vue.js가 효율적인 업데이트를 위해 세분화된 반응 시스템을 활용하도록 특별히 고안된 라이브러리입니다.
+
+![vuex](/vuex.png)
+
+### 언제 사용해야 하나요?
+
+Vuex는 공유된 상태 관리를 처리하는 데 유용하지만, 개념에 대한 이해와 시작하는 비용도 함께 듭니다. 그것은 단기간과 장기간 생산성 간의 기회비용이 있습니다.
+
+대규모 SPA를 구축하지 않고 Vuex로 바로 뛰어 들었다면, 시간이 오래 걸리고 힘든일일 것입니다. 이것은 일반 적인 일입니다. 앱이 단순하다면 Vuex없이는 괜찮을 것입니다. 간단한 [글로벌 이벤트 버스](https://kr.vuejs.org/v2/guide/components.html#비-부모-자식간-통신)만 있으면됩니다. 그러나 중대형 규모의 SPA를 구축하는 경우 Vue컴포넌트 외부의 상태를 보다 잘 처리할 수 있는 방법을 생각하게 될 가능성이 있으며 Vuex는 자연스럽게 선택할 수 있는 단계가 될 것입니다. Redux의 저자인 Dan Abramov의 좋은 인용이 있습니다.
+
+> Flux 라이브러리는 안경과 같습니다. 필요할 때 알아볼 수 있습니다.

+ 263 - 0
docs/kr/api/README.md

@@ -0,0 +1,263 @@
+---
+sidebar: auto
+---
+
+# API 레퍼런스
+
+## Vuex.Store
+
+``` js
+import Vuex from 'vuex'
+
+const store = new Vuex.Store({ ...options })
+```
+
+## Vuex.Store 생성자 옵션
+
+### state
+
+- 자료형: `Object | Function`
+
+  Vuex 저장소의 루트 상태 객체 입니다. [상세](../guide/state.md)
+
+  오브젝트를 반환하는 함수를 전달하면, 반환된 오브젝트가 로투 상태로 사용됩니다. 이것은 모듈 재사용을 위해 상태 객체를 재사용하고자 할 때 유용합니다. [상세](../guide/modules.md#모듈-재사용)
+
+### mutations
+
+- 자료형: `{ [type: string]: Function }`
+
+  저장소에 변이를 등록하십시오. 핸들러 함수는 항상 첫 번째 전달인자로 `state`를 받습니다 (모듈에 정의 된 경우 모듈 로컬 상태가됩니다). 두 번째 `payload` 전달인자가 있으면 처리합니다.
+
+  [상세](../guide/mutations.md)
+
+### actions
+
+- 자료형: `{ [type: string]: Function }`
+
+  저장소에 액션을 등록하십시오. 핸들러 함수는 다음 속성을 노출하는 `context` 객체를받습니다.
+
+    ``` js
+    {
+      state,      // store.state와 같습니다. 또는 모듈에 있는 경우 로컬 상태
+      rootState,  // store.state와 같습니다. 모듈 안에만 존재합니다
+      commit,     // store.commit와 같습니다.
+      dispatch,   // store.dispatch와 같습니다.
+      getters,    // store.getters와 같습니다. 또는 모듈에 있는 로컬 getters
+      rootGetters // store.getters와 같습니다. 모듈 안에만 존재합니다
+    }
+    ```
+
+  두 번째 `payload` 전달인자가 있으면 처리합니다.
+
+  [상세](../guide/actions.md)
+
+### getters
+
+- 자료형: `{ [key: string]: Function }`
+
+  저장소에 getter를 등록하십시오. getter 함수는 다음 전달인자를 받습니다.
+
+    ```
+    state,     // 모듈에 정의 된 경우 모듈 로컬 상태가됩니다.
+    getters   // store.getters와 같습니다.
+    ```
+
+  모듈 안에서 정의할 때의 사양입니다.
+
+    ```
+    state,       // 모듈에 정의 된 경우 모듈 로컬 상태가됩니다.
+    getters,     // store.getters와 같습니다.
+    rootState    // 글로벌 상태 입니다
+    rootGetters  // 모든 getters 입니다
+    ```
+
+  등록된 getter는 `store.getters`에 노출됩니다.
+
+  [상세](../guide/getters.md)
+
+### modules
+
+- 자료형: `Object`
+
+  저장소에 병합될 하위 모듈을 포함하는 객체 입니다.
+
+    ``` js
+    {
+      key: {
+        state,
+        namespaced?,
+        mutations?,
+        actions?,
+        getters?,
+        modules?
+      },
+      ...
+    }
+    ```
+
+  각 모듈은 루트 옵션과 비슷한 `state` 와 `mutations` 를 포함 할 수 있습니다. 모듈의 상태는 모듈의 키를 사용하여 저장소의 루트 상태에 연결됩니다. 모듈의 변이와 getter는 모듈의 로컬 상태를 루트 상태 대신 첫 번째 전달인자로 받으며 모듈 액션의 `context.state`도 로컬 상태를 가리 킵니다.
+
+  [상세](../guide/modules.md)
+
+### plugins
+
+- 자료형: `Array<Function>`
+
+  저장소에 적용 할 플러그인 함수의 배열입니다. 플러그인은 저장소를 유일한 전달인자로 받아들이고 아웃바운드 데이터 지속성, 로깅 또는 디버깅을 위한 변이를 감시하거나 (인바운드 데이터 (예: 웹 소켓 또는 관찰 가능 항목)의 디스패치 변이) 감시할 수 있습니다.
+
+  [상세](../guide/plugins.md)
+
+### strict
+
+- 자료형: `Boolean`
+- 기본값: `false`
+
+  Vuex 저장소를 strict 모드로 변경합니다. strict 모드에서 변이 핸들러 외부의 Vuex 상태에 대한 임의의 변이는 오류를 발생시킵니다.
+
+  [상세](../guide/strict.md)
+
+## Vuex.Store 인스턴스 속성
+
+### state
+
+- 자료형: `Object`
+
+  루트 상태. 읽기 전용
+
+### getters
+
+- 자료형: `Object`
+
+  등록된 getters 입니다. 읽기 전용.
+
+## Vuex.Store 인스턴스 메소드
+
+### commit
+
+- `commit(type: string, payload?: any, options?: Object)`
+- `commit(mutation: Object, options?: Object)`
+
+  변이를 커밋합니다. `options` 에 `root:true` 를 포함하면 [네임스페이스 모듈](../guide/modules.md#네임스페이스) 의 root 변이에 commit 을 허용합니다. [상세](../guide/mutations.md)
+
+### dispatch
+
+- `dispatch(type: string, payload?: any, options?: Object)`
+- `dispatch(action: Object, options?: Object)`
+
+  액션을 디스패치 합니다. `options` 에 `root:true` 를 포함하면 [네임스페이스 모듈](../guide/modules.md#네임스페이스) 의 root 액션에 디스패치를 허용합니다. 모든 트리거된 액션 핸들러를 처리하는 Promise를 반환합니다. [상세](../guide/actions.md)
+
+### replaceState
+
+- `replaceState(state: Object)`
+
+  저장소의 루트 상태를 바꿉니다. 상태에 대한 상호작용/시점 변경 목적으로 만 사용하십시오.
+
+### watch
+
+- `watch(fn: Function, callback: Function, options?: Object): Function`
+
+  `fn` 함수의 반환 값을 반응적으로 지켜보고 값이 변경되면 콜백을 호출합니다. `fn`는 저장소의 상태를 첫 번째 인수로 받고, getters를 두 번째 인수로 받습니다. Vue의 `vm.$watch` 메소드와 같은 옵션을 취하는 옵션 객체를 받아들입니다.
+
+  감시를 중단하려면 반환된 핸들 함수를 호출하십시오.
+
+### subscribe
+
+- `subscribe(handler: Function): Function`
+
+  저장소 변이를 구독합니다. `handler`는 모든 변이 이후 호출되고 변이 디스크립터와 변이 상태를 전달인자로 받습니다.
+
+  ``` js
+  store.subscribe((mutation, state) => {
+    console.log(mutation.type)
+    console.log(mutation.payload)
+  })
+  ```
+
+  구독을 중단하려면 반환된 구독 해제 함수를 호출하십시오.
+
+  플러그인에서 가장 일반적으로 사용됩니다. [상세](../guide/plugins.md)
+
+### subscribeAction
+
+-  `subscribeAction(handler: Function): Function`
+
+  > 2.5.0 에서 추가됨
+
+  저장소 액션을 구독합니다. `handler`는 모든 디스패치 액션 이후 호출되고 액션 디스크립터와 현재 저장소 상태를 전달인자로 받습니다.
+
+  ``` js
+  store.subscribeAction((action, state) => {
+    console.log(action.type)
+    console.log(action.payload)
+  })
+  ```
+
+  구독을 중단하려면 반환된 구독 해제 함수를 호출하십시오.
+
+  플러그인에서 가장 일반적으로 사용됩니다. [상세](../guide/plugins.md)
+
+### registerModule
+
+- `registerModule(path: string | Array<string>, module: Module, options?: Object)`
+
+  동적 모듈을 등록합니다. [상세](../guide/modules.md#동적-모듈-등록)
+  
+  `options`은 이전 속성을 보호하는 `preserveState: true`를 가질 수 있습니다. 이것은 서버사이드 렌더링에서 유용합니다.
+
+### unregisterModule
+
+- `unregisterModule(path: string | Array<string>)`
+
+  동적 모듈을 해제 합니다. [상세](../guide/modules.md#동적-모듈-등록)
+
+### hotUpdate
+
+- `hotUpdate(newOptions: Object)`
+
+  새 액션과 변이를 핫 스왑 합니다. [상세](../guide/hot-reload.md)
+
+## 컴포넌트 바인딩 헬퍼
+
+### mapState
+
+- `mapState(namespace?: string, map: Array<string> | Object<string | function>): Object`
+
+  Vuex 저장소의 하위 트리를 반환하는 컴포넌트 계산 옵션을 만듭니다. [상세](../guide/state.md#mapstate-헬퍼)
+  
+  처음 argument는 string 타입의 namespace가 될 수 있습니다. [상세](../guide/modules.md#헬퍼에서-네임스페이스-바인딩)
+
+  두번째 오브젝트 argument는 함수가 될 수 있습니다. `function(state: any)`
+
+### mapGetters
+
+- `mapGetters(namespace?: string, map: Array<string> | Object<String>): Object`
+
+  getter의 평가된 값을 반환하는 컴포넌트 계산 옵션을 만듭니다. [상세](../guide/getters.md#mapgetters-헬퍼)
+  
+  처음 argument는 string 타입의 namespace가 될 수 있습니다. [상세](../guide/modules.md#헬퍼에서-네임스페이스-바인딩)
+
+### mapActions
+
+- `mapActions(namespace?: string, map: Array<string> | Object<string | function>): Object`
+
+  액션을 전달하는 컴포넌트 메소드 옵션을 만듭니다. [상세](../guide/actions.md#컴포넌트-내부에서-디스패치-액션-사용하기)
+  
+  처음 argument는 string 타입의 namespace가 될 수 있습니다. [상세](../guide/modules.md#헬퍼에서-네임스페이스-바인딩)
+
+  두번째 오브젝트 argument는 함수가 될 수 있습니다. `function(dispatch: function, ...args: any[])`
+
+### mapMutations
+
+- `mapMutations(namespace?: string, map: Array<string> | Object<string | function>): Object`
+
+  변이를 커밋하는 컴포넌트 메소드 옵션을 만듭니다. [상세](../guide/mutations.md#컴포넌트-안에서-변이-커밋하기)
+  
+  처음 argument는 string 타입의 namespace가 될 수 있습니다. [상세](../guide/modules.md#헬퍼에서-네임스페이스-바인딩)
+
+  두번째 오브젝트 argument는 함수가 될 수 있습니다. `function(commit: function, ...args: any[])`
+  
+### createNamespacedHelpers
+
+- `createNamespacedHelpers(namespace: string): Object`
+
+  namespace가 적용된 컴포넌트 바인딩 helper를 만듭니다. 주어진 namespace가 적용된 `mapState`, `mapGetters`, `mapActions` `mapMutations`들을 가지고 있는 오브젝트를 반환합니다. [상세](../guide/modules.md#헬퍼에서-네임스페이스-바인딩)

+ 43 - 0
docs/kr/guide/README.md

@@ -0,0 +1,43 @@
+# 시작하기
+
+모든 Vuex 애플리케이션의 중심에는 **store** 가 있습니다. "저장소"는 기본적으로 애플리케이션 **상태** 를 보유하고있는 컨테이너입니다. Vuex 저장소가 일반 전역 개체와 두 가지 다른 점이 있습니다.
+
+1. Vuex store는 반응형 입니다. Vue 컴포넌트는 상태를 검색할 때 저장소의 상태가 변경되면 효율적으로 대응하고 업데이트합니다.
+2. 저장소의 상태를 직접 변경할 수 없습니다. 저장소의 상태를 변경하는 유일한 방법은 명시적인 **커밋을 이용한 변이** 입니다. 이렇게하면 모든 상태에 대한 추적이 가능한 기록이 남을 수 있으며 툴을 사용하여 앱을 더 잘 이해할 수 있습니다.
+
+### 가장 단순한 저장소
+
+> **참고:** 모든 예제는 ES2015 문법을 사용합니다. 사용하고 있지 않은 경우 [꼭 사용해야 합니다!](https://babeljs.io/docs/learn-es2015/)
+
+Vuex를 [설치](installation.md)한 후 저장소를 만들어 봅시다. 매우 간단합니다. 초기 상태 객체와 일부 변이를 제공하십시오.
+
+``` js
+// 모듈 시스템을 사용하는 경우 Vue.use(Vuex)를 먼저 호출해야합니다.
+
+const store = new Vuex.Store({
+  state: {
+    count: 0
+  },
+  mutations: {
+    increment (state) {
+      state.count++
+    }
+  }
+})
+```
+
+이제 state 객체에 `store.state`로 접근하여 `store.commit` 메소드로 상태 변경을 트리거 할 수 있습니다.
+
+``` js
+store.commit('increment')
+
+console.log(store.state.count) // -> 1
+```
+
+다시 말해, `store.state.count`를 직접 변경하는 대신 변이를 수행하는 이유는 명시적으로 추적을 하기 때문입니다. 이 간단한 규칙에 따라 의도를보다 명확하게 표현할 수 있으므로 코드를 읽을 때 상태 변화를 더 잘 지켜볼 수 있습니다. 또한 모든 변이를 기록하고 상태 스냅샷을 저장하거나 시간 흐름에 따라 디버깅을 할 수 있는 도구를 제공합니다.
+
+컴포넌트 안에서 저장소 상태를 사용하는 것은 단순히 계산된 속성 내에서 상태를 반환하는 것입니다. 변경을 트리거하는 것은 컴포넌트 메소드에서 변경을 커밋하는 것을 의미합니다.
+
+다음은 [가장 기본적인 Vuex 카운터 앱](https://jsfiddle.net/n9jmu5v7/1269/)의 예입니다.
+
+이제, 우리는 각 핵심 개념에 대해 더 자세히 설명 할 것입니다. [State](state.md)부터 시작해 보겠습니다.

+ 175 - 0
docs/kr/guide/actions.md

@@ -0,0 +1,175 @@
+# 액션
+
+액션은 변이와 유사합니다. 몇가지 다른 점은,
+
+- 상태를 변이시키는 대신 액션으로 변이에 대한 커밋을 합니다.
+- 작업에는 임의의 비동기 작업이 포함될 수 있습니다.
+
+간단한 액션을 등록합시다.
+
+``` js
+const store = new Vuex.Store({
+  state: {
+    count: 0
+  },
+  mutations: {
+    increment (state) {
+      state.count++
+    }
+  },
+  actions: {
+    increment (context) {
+      context.commit('increment')
+    }
+  }
+})
+```
+
+액션 핸들러는 저장소 인스턴스의 같은 메소드들/프로퍼티 세트를 드러내는 컨텍스트 객체를 받습니다. 그래서 `context.commit`을 호출하여 변이를 커밋하거나 `context.state`와 `context.getters`를 통해 상태와 getters에 접근 할 수 있습니다. 나중에 [모듈](modules.md)에서 이 컨텍스트 객체가 저장소 인스턴스 자체가 아닌 이유를 알 수 있습니다.
+
+실제로 (특히 `commit`를 여러 번 호출해야하는 경우)코드를 단순화하기 위해 ES2015 [전달인자 분해](https://github.com/lukehoban/es6features#destructuring)를 사용합니다.
+
+``` js
+actions: {
+  increment ({ commit }) {
+    commit('increment')
+  }
+}
+```
+
+### 디스패치 액션
+
+액션은 `store.dispatch` 메소드로 시작됩니다.
+
+``` js
+store.dispatch('increment')
+```
+
+처음 볼 때는 이상해 보일 수 있습니다. 카운트를 증가 시키려면 `store.commit('increment')`를 직접 호출하면 어떻습니까? 음, **상태변이는 동기적** 이어야 한다는 것을 기억하십니까? 액션은 그렇지 않습니다. 액션 내에서 **비동기** 작업을 수행 할 수 있습니다.
+
+``` js
+actions: {
+  incrementAsync ({ commit }) {
+    setTimeout(() => {
+      commit('increment')
+    }, 1000)
+  }
+}
+```
+
+액션은 동일한 페이로드 타입과 객체 스타일의 디스패치를 지원합니다.
+
+``` js
+// 페이로드와 함께 디스패치
+store.dispatch('incrementAsync', {
+  amount: 10
+})
+
+// 객체와 함께 디스패치
+store.dispatch({
+  type: 'incrementAsync',
+  amount: 10
+})
+```
+
+액션의 좀 더 실용적인 예는 **비동기 API 호출** 과 **여러 개의 변이를 커밋** 하는 장바구니 결제입니다.
+
+``` js
+actions: {
+  checkout ({ commit, state }, products) {
+    // 장바구니에 현재있는 항목을 저장하십시오.
+    const savedCartItems = [...state.cart.added]
+
+    // 결제 요청을 보낸 후 장바구니를 비웁니다.
+    commit(types.CHECKOUT_REQUEST)
+
+    // 상점 API는 성공 콜백 및 실패 콜백을 받습니다.
+    shop.buyProducts(
+      products,
+      // 요청 성공 핸들러
+      () => commit(types.CHECKOUT_SUCCESS),
+      // 요청 실패 핸들러
+      () => commit(types.CHECKOUT_FAILURE, savedCartItems)
+    )
+  }
+}
+```
+
+비동기 작업의 흐름을 수행하고 커밋하여 작업의 사이드이펙트(상태 변이)을 기록합니다.
+
+### 컴포넌트 내부에서 디스패치 액션 사용하기
+
+`this.$store.dispatch('xxx')`를 사용하여 컴포넌트에서 액션을 디스패치하거나 컴포넌트 메소드를 `store.dispatch` 호출에 매핑하는 `mapActions` 헬퍼를 사용할 수 있습니다 (루트 `store` 주입 필요) :
+
+``` js
+import { mapActions } from 'vuex'
+
+export default {
+  // ...
+  methods: {
+    ...mapActions([
+      'increment' // this.increment()을 this.$store.dispatch('increment')에 매핑
+    ]),
+    ...mapActions({
+      add: 'increment' // this.add()을 this.$store.dispatch('increment')에 매핑
+    })
+  }
+}
+```
+
+### 액션 구성하기
+
+액션은 종종 비동기적 입니다. 그러면 액션이 언제 완료되는지 어떻게 알 수 있습니까? 더 중요한 것은, 복잡한 비동기 흐름을 처리하기 위해 어떻게 여러 작업을 함께 구성 할 수 있습니까?
+
+가장 먼저 알아야 할 점은 `store.dispatch`가 트리거 된 액션 핸들러에 의해 반환된 Promise를 처리 할 수 있으며 Promise를 반환한다는 것입니다.
+
+``` js
+actions: {
+  actionA ({ commit }) {
+    return new Promise((resolve, reject) => {
+      setTimeout(() => {
+        commit('someMutation')
+        resolve()
+      }, 1000)
+    })
+  }
+}
+```
+
+이렇게 할 수 있습니다.
+
+``` js
+store.dispatch('actionA').then(() => {
+  // ...
+})
+```
+
+그리고 안에 또 다른 액션을 사용할 수 있습니다.
+
+``` js
+actions: {
+  // ...
+  actionB ({ dispatch, commit }) {
+    return dispatch('actionA').then(() => {
+      commit('someOtherMutation')
+    })
+  }
+}
+```
+
+마지막으로, JavaScript 기능인 [async/await](https://tc39.github.io/ecmascript-asyncawait/)를 사용하면 다음과 같은 작업을 구성 할 수 있습니다.
+
+``` js
+// getData() 및 getOtherData()가 Promise를 반환한다고 가정합니다.
+actions: {
+  async actionA ({ commit }) {
+    commit('gotData', await getData())
+  },
+  async actionB ({ dispatch, commit }) {
+    await dispatch('actionA') // actionA가 끝나기를 기다립니다.
+    commit('gotOtherData', await getOtherData())
+  }
+}
+```
+
+> `store.dispatch`가 다른 모듈에서 여러 액션 핸들러를 트리거하는 것이 가능합니다. 이 경우 반환 된 값은 모든 트리거 된 처리기가 완료 되었을 때 처리되는 Promise입니다.

+ 60 - 0
docs/kr/guide/forms.md

@@ -0,0 +1,60 @@
+# 폼 핸들링
+
+strict 모드로 Vuex를 사용하는 경우 Vuex에 포함된 부분에 `v-model`을 사용하는 것은 약간 까다로울 수 있습니다.
+
+``` html
+<input v-model="obj.message">
+```
+
+`obj`가 저장소에서 객체를 반환하는 계산된 속성이라면, 여기에있는 `v-model`은 사용자가 입력 할 때 `obj.message`를 직접 변경하려고 합니다. strict 모드에서는 Vuex 변이 처리기 내부에서 변이가 수행되지 않으므로 오류가 발생합니다.
+
+그것을 다루는 "Vuex 방식"은 `<input>`의 값을 바인딩하고 `input` 또는 `change` 이벤트에 대한 액션을 호출하는 것 입니다.
+
+``` html
+<input :value="message" @input="updateMessage">
+```
+``` js
+// ...
+computed: {
+  ...mapState({
+    message: state => state.obj.message
+  })
+},
+methods: {
+  updateMessage (e) {
+    this.$store.commit('updateMessage', e.target.value)
+  }
+}
+```
+
+변이에 대한 핸들러 입니다.
+
+``` js
+// ...
+mutations: {
+  updateMessage (state, message) {
+    state.obj.message = message
+  }
+}
+```
+
+### 양방향 계산된 속성
+
+틀림없이, 위의 내용은 `v-model` + 지역 상태보다 좀더 장황 해졌고, `v-model`의 유용한 기능 중 일부를 잃어 버렸습니다. 다른 방법은 setter를 사용하여 양방향 계산된 속성을 사용하는 것입니다.
+
+``` html
+<input v-model="message">
+```
+``` js
+// ...
+computed: {
+  message: {
+    get () {
+      return this.$store.state.obj.message
+    },
+    set (value) {
+      this.$store.commit('updateMessage', value)
+    }
+  }
+}
+```

+ 116 - 0
docs/kr/guide/getters.md

@@ -0,0 +1,116 @@
+# Getters
+
+때로는 저장소 상태를 기반하는 상태를 계산해야 할 수도 있습니다.(예: 아이템 리스트를 필터링하고 계산)
+
+``` js
+computed: {
+  doneTodosCount () {
+    return this.$store.state.todos.filter(todo => todo.done).length
+  }
+}
+```
+
+둘 이상의 컴포넌트가 이를 사용 해야하는 경우 함수를 복제하거나 공유된 헬퍼를 추출하여 여러 위치에서 가져와야합니다. 둘 다 이상적이지 않습니다.
+
+Vuex를 사용하면 저장소에서 "getters"를 정의 할 수 있습니다. 저장소의 계산된 속성으로 생각할 수 있습니다. 계산된 속성처럼 getter의 결과는 종속성에 따라 캐쉬되고, 일부 종속성이 변경된 경우에만 다시 재계산 됩니다.
+
+Getters는 첫 번째 전달인자로 상태를 받습니다.
+
+``` js
+const store = new Vuex.Store({
+  state: {
+    todos: [
+      { id: 1, text: '...', done: true },
+      { id: 2, text: '...', done: false }
+    ]
+  },
+  getters: {
+    doneTodos: state => {
+      return state.todos.filter(todo => todo.done)
+    }
+  }
+})
+```
+
+### 속성 유형 접근
+
+getters는 `store.getters` 객체에 노출되고, 속성으로 값에 접근할 수 있습니다:
+
+``` js
+store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
+```
+
+Getters는 두 번째 전달인자로 다른 getter도 받게됩니다.
+
+``` js
+getters: {
+  // ...
+  doneTodosCount: (state, getters) => {
+    return getters.doneTodos.length
+  }
+}
+```
+
+``` js
+store.getters.doneTodosCount // -> 1
+```
+
+이제 모든 컴포넌트에서 쉽게 사용할 수 있습니다.
+
+``` js
+computed: {
+  doneTodosCount () {
+    return this.$store.getters.doneTodosCount
+  }
+}
+```
+
+속성으로 접근하는 getter는 Vue의 반응성 시스템의 일부로 캐시된 것임을 유의해야 합니다.
+
+### 메소드 유형 접근
+
+함수를 반환하여 getter에 전달인자로 전달할 수도 있습니다. 이것은 저장소의 배열을 검색할 때 특히 유용합니다.
+
+```js
+getters: {
+  // ...
+  getTodoById: (state) => (id) => {
+    return state.todos.find(todo => todo.id === id)
+  }
+}
+```
+
+``` js
+store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
+```
+
+메서드를 통해 접근하는 getter는 호출 할 때마다 실행되며 결과가 캐시되지 않는다는 것을 유의해야 합니다.
+
+### `mapGetters` 헬퍼
+
+`mapGetters` 헬퍼는 저장소 getter를 로컬 계산된 속성에 매핑합니다.
+
+``` js
+import { mapGetters } from 'vuex'
+
+export default {
+  // ...
+  computed: {
+    // getter를 객체 전개 연산자(Object Spread Operator)로 계산하여 추가합니다.
+    ...mapGetters([
+      'doneTodosCount',
+      'anotherGetter',
+      // ...
+    ])
+  }
+}
+```
+
+getter를 다른 이름으로 매핑하려면 객체를 사용합니다.
+
+``` js
+...mapGetters({
+  // this.doneCount를 store.getters.doneTodosCount에 매핑하십시오.
+  doneCount: 'doneTodosCount'
+})
+```

+ 44 - 0
docs/kr/guide/hot-reload.md

@@ -0,0 +1,44 @@
+# 핫 리로딩
+
+Vuex는 webpack의 [핫 모듈 변경 API](https://webpack.js.org/guides/hot-module-replacement/)를 사용하여 개발 중에 핫 리로드 변이, 모듈, 액션 및 getter를 지원합니다. [browserify-hmr](https://github.com/AgentME/browserify-hmr/) 플러그인으로 Browserify에서 사용할 수도 있습니다.
+
+변이와 모듈의 경우, `store.hotUpdate()` API 메소드를 사용할 필요가 있습니다.
+
+``` js
+// store.js
+import Vue from 'vue'
+import Vuex from 'vuex'
+import mutations from './mutations'
+import moduleA from './modules/a'
+
+Vue.use(Vuex)
+
+const state = { ... }
+
+const store = new Vuex.Store({
+  state,
+  mutations,
+  modules: {
+    a: moduleA
+  }
+})
+
+if (module.hot) {
+  // 액션과 변이를 핫 모듈로 받아 들인다.
+  module.hot.accept(['./mutations', './modules/a'], () => {
+    // 업데이트 된 모듈은 babel 6 모듈 출력으로 인해
+    // .default를 여기에 추가해야합니다.
+    const newMutations = require('./mutations').default
+    const newModuleA = require('./modules/a').default
+    // 새로운 액션과 변이로 바꿉니다.
+    store.hotUpdate({
+      mutations: newMutations,
+      modules: {
+        a: newModuleA
+      }
+    })
+  })
+}
+```
+
+[counter-hot 예제](https://github.com/vuejs/vuex/tree/dev/examples/counter-hot)로 핫 리로드를 확인하십시오.

+ 319 - 0
docs/kr/guide/modules.md

@@ -0,0 +1,319 @@
+# 모듈
+
+단일 상태 트리를 사용하기 때문에 애플리케이션의 모든 상태가 하나의 큰 객체 안에 포함됩니다. 그러나 규모가 커짐에 따라 저장소는 매우 비대해질 수 있습니다.
+
+이를 위해 Vuex는 저장소를 **모듈** 로 나눌 수 있습니다. 각 모듈은 자체 상태, 변이, 액션, 게터 및 심지어 중첩된 모듈을 포함 할 수 있습니다.
+
+``` js
+const moduleA = {
+  state: { ... },
+  mutations: { ... },
+  actions: { ... },
+  getters: { ... }
+}
+
+const moduleB = {
+  state: { ... },
+  mutations: { ... },
+  actions: { ... }
+}
+
+const store = new Vuex.Store({
+  modules: {
+    a: moduleA,
+    b: moduleB
+  }
+})
+
+store.state.a // -> moduleA'의 상태
+store.state.b // -> moduleB'의 상태
+```
+
+### 지역 상태 모듈
+
+모듈의 변이와 getter 내부에서 첫 번째 전달인자는 **모듈의 지역 상태** 가됩니다.
+
+``` js
+const moduleA = {
+  state: { count: 0 },
+  mutations: {
+    increment (state) {
+      // state는 지역 모듈 상태 입니다
+      state.count++
+    }
+  },
+
+  getters: {
+    doubleCount (state) {
+      return state.count * 2
+    }
+  }
+}
+```
+
+유사하게 모듈 내부에서 `context.state`는 지역 상태를 노출시킬 것이고 루트 상태는 `context.rootState`로 노출 될 것입니다.
+
+``` js
+const moduleA = {
+  // ...
+  actions: {
+    incrementIfOddOnRootSum ({ state, commit, rootState }) {
+      if ((state.count + rootState.count) % 2 === 1) {
+        commit('increment')
+      }
+    }
+  }
+}
+```
+
+또한, 모듈 getters 내부, 루트 상태는 그들의 세 번째 전달인자로 노출됩니다.
+
+``` js
+const moduleA = {
+  // ...
+  getters: {
+    sumWithRootCount (state, getters, rootState) {
+      return state.count + rootState.count
+    }
+  }
+}
+```
+
+### 네임스페이스
+
+기본적으로 모듈 내의 액션, 변이 및 getter는 여전히 **전역 네임 스페이스** 아래에 등록됩니다. 여러 모듈이 동일한 변이/액션 유형에 반응 할 수 있습니다.
+
+만약 모듈이 독립적이거나 재사용되기를 원한다면, `namespaced: true`라고 네임스페이스에 명시하면 됩니다. 모듈이 등록될 때, 해당 모듈의 모든 getter, 액션/변이는 자동으로 등록된 모듈의 경로를 기반으로 네임스페이스가 지정됩니다. 아래는 예시입니다:
+
+``` js
+const store = new Vuex.Store({
+  modules: {
+    account: {
+      namespaced: true,
+
+      // 모듈 자산
+      state: { ... }, // 모듈 상태는 이미 중첩되어 있고, 네임스페이스 옵션의 영향을 받지 않음
+      getters: {
+        isAdmin () { ... } // -> getters['account/isAdmin']
+      },
+      actions: {
+        login () { ... } // -> dispatch('account/login')
+      },
+      mutations: {
+        login () { ... } // -> commit('account/login')
+      },
+
+      // 중첩 모듈
+      modules: {
+        // 부모 모듈로부터 네임스페이스를 상속받음
+        myPage: {
+          state: { ... },
+          getters: {
+            profile () { ... } // -> getters['account/profile']
+          }
+        },
+
+        // 네임스페이스를 더 중첩
+        posts: {
+          namespaced: true,
+
+          state: { ... },
+          getters: {
+            popular () { ... } // -> getters['account/posts/popular']
+          }
+        }
+      }
+    }
+  }
+})
+```
+
+네임스페이스의 getter와 액션은 지역화된  `getters`, `dispatch` 그리고 `commit`을 받습니다. 즉, 동일한 모듈 안에서 접두어 없이 모듈 자산을 사용할 수 있습니다. 네임스페이스 옵션 값을 바꾸어도 모듈 내부의 코드에는 영향을 미치지 않습니다.
+
+#### 네임스페이스 모듈 내부에서 전역 자산 접근
+
+전역 상태나 getter를 사용하고자 한다면, `rootState`와 `rootGetters`가 getter 함수의 3번째와 4번째 인자로 전달되고, 또한 action 함수에 전달된 'context' 객체의 속성으로도 노출됩니다.
+
+전역 네임스페이스의 액션을 디스패치하거나 변이를 커밋하려면 `dispatch`와 `commit`에 3번째 인자로 `{ root: true }`를 전달하면 됩니다.
+
+``` js
+modules: {
+  foo: {
+    namespaced: true,
+
+    getters: {
+      // `getters`는 해당 모듈의 지역화된 getters
+      // getters의 4번째 인자를 통해서 rootGetters 사용 가능
+      someGetter (state, getters, rootState, rootGetters) {
+        getters.someOtherGetter // -> 'foo/someOtherGetter'
+        rootGetters.someOtherGetter // -> 'someOtherGetter'
+      },
+      someOtherGetter: state => { ... }
+    },
+
+    actions: {
+      // 디스패치와 커밋도 해당 모듈의 지역화된 것
+      // 전역 디스패치/커밋을 위한 `root` 옵션 설정 가능
+      someAction ({ dispatch, commit, getters, rootGetters }) {
+        getters.someGetter // -> 'foo/someGetter'
+        rootGetters.someGetter // -> 'someGetter'
+
+        dispatch('someOtherAction') // -> 'foo/someOtherAction'
+        dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'
+
+        commit('someMutation') // -> 'foo/someMutation'
+        commit('someMutation', null, { root: true }) // -> 'someMutation'
+      },
+      someOtherAction (ctx, payload) { ... }
+    }
+  }
+}
+```
+
+#### 네임스페이스 모듈에서 전역 액션 등록
+
+네임스페이스 모듈에서 전역 액션을 등록하려면, `root: true`를 표시하고 `handler` 함수에 액션을 정의하면 됩니다. 아래는 예시입니다:
+
+``` js
+{
+  actions: {
+    someOtherAction ({dispatch}) {
+      dispatch('someAction')
+    }
+  },
+  modules: {
+    foo: {
+      namespaced: true,
+
+      actions: {
+        someAction: {
+          root: true,
+          handler (namespacedContext, payload) { ... } // -> 'someAction'
+        }
+      }
+    }
+  }
+}
+```
+
+#### 헬퍼에서 네임스페이스 바인딩
+
+`mapState`, `mapGetters`, `mapActions` 그리고 `mapMutations` 헬퍼에서 네임스페이스 모듈을 컴포넌트에 바인딩 할 때 조금 장황하게 됩니다.
+
+``` js
+computed: {
+  ...mapState({
+    a: state => state.some.nested.module.a,
+    b: state => state.some.nested.module.b
+  })
+},
+methods: {
+  ...mapActions([
+    'some/nested/module/foo',
+    'some/nested/module/bar'
+  ])
+}
+```
+
+이러한 경우에는 모듈의 네임스페이스 문자열을 헬퍼의 첫 번째 인수로 전달하여 해당 모듈을 컨텍스트로 사용하여 모든 바인딩을 할 수 있습니다. 위의 예시는 아래와 같이 단순화 할 수 있습니다.
+
+``` js
+computed: {
+  ...mapState('some/nested/module', {
+    a: state => state.a,
+    b: state => state.b
+  })
+},
+methods: {
+  ...mapActions('some/nested/module', [
+    'foo',
+    'bar'
+  ])
+}
+```
+
+또한 `createNamespacedHelpers`를 사용하여 네임스페이스 헬퍼를 생성할 수 있습니다. 전달된 네임스페이스 값으로 바인딩된 새로운 컴포넌트 바인딩 헬퍼를 가진 객체를 반환합니다.
+
+``` js
+import { createNamespacedHelpers } from 'vuex'
+
+const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
+
+export default {
+  computed: {
+    // `some/nested/module`에서 찾음
+    ...mapState({
+      a: state => state.a,
+      b: state => state.b
+    })
+  },
+  methods: {
+    // `some/nested/module`에서 찾음
+    ...mapActions([
+      'foo',
+      'bar'
+    ])
+  }
+}
+```
+
+#### 플러그인 개발자를 위한 주의 사항
+
+개발자가 개발한 특정 모듈을 위해서 만든 [플러그인](plugins.md)을 사용자가 Vuex 저장소에 등록할 때 예측할 수 없는 네임스페이스 오류를 주의해야 합니다. 플러그인 사용자가 특정 모듈을 네임스페이스 모듈 하위에 추가하면 해당 모듈도 동일한 네임스페이스로 등록됩니다. 이러한 상황을 피하기 위해서 플러그인 옵션을 통해 네임스페이스 값을 전달받을 수 있어야 합니다.
+
+``` js
+// 플러그인 옵션을 통해 네임스페이스 값 전달
+// 그리고 Vuex 플러그인 함수를 반환
+export function createPlugin (options = {}) {
+  return function (store) {
+    // add namespace to plugin module's types
+    const namespace = options.namespace || ''
+    store.dispatch(namespace + 'pluginAction')
+  }
+}
+```
+
+### 동적 모듈 등록
+
+`store.registerModule` 메소드로 저장소가 생성 된 **후에** 모듈을 등록 할 수 있습니다.
+
+``` js
+store.registerModule('myModule', {
+  // ...
+})
+
+// `nested/myModule` 중첩 모듈 등록
+store.registerModule(['nested', 'myModule'], {
+  // ...
+})
+```
+
+모듈의 상태는`store.state.myModule`와 `store.state.nested.myModule`로 노출 됩니다.
+
+동적 모듈 등록을 사용하면 다른 Vue 플러그인도 애플리케이션의 저장소에 모듈을 연결하여 상태 관리에 Vuex를 활용할 수 있습니다. 예를 들어 [`vuex-router-sync`](https://github.com/vuejs/vuex-router-sync) 라이브러리는 동적으로 연결된 모듈에서 애플리케이션의 라우트 상태를 관리하여 vue-router와 vuex를 통합합니다.
+
+`store.unregisterModule(moduleName)`을 사용하여 동적으로 등록 된 모듈을 제거할 수도 있습니다. 이 방법으로는 정적 모듈(저장소 생성시 선언 됨)을 제거 할 수 없습니다.
+
+Server Side Rendered 앱에서 상태를 유지하는 것처럼 새 모듈을 등록할 때 이전 상태를 유지하고자 할 수 있습니다. `preserveState` 옵션을 사용하면 그렇게 할 수 있습니다: `store.registerModule('a', module, { preserveState: true })`
+
+### 모듈 재사용
+
+때로는 한 모듈에서 여러 인스턴스를 생성해야 할 수도 있습니다. 예를 들자면 다음과 같습니다:
+
+- 동일 모듈을 사용하는 여러 저장소 생성 (예. [SSR 에서 싱글톤 상태 피하기](https://ssr.vuejs.org/en/structure.html#avoid-stateful-singletons) 에서 `runInNewContext` 옵션이 `false`나 `once`일 때)
+- 동일 모듈을 동일 저장소에 여러 번 등록
+
+일반 객체를 사용하여 모듈의 상태를 선언하면 상태 객체가 참조에 의해 공유되고 변이 될 때 교차 저장소/모듈의 상태 오염을 일으킵니다.
+
+이것은 실제로 Vue 컴포넌트 내부의 `data`와 완전히 동일한 문제입니다. 그래서 해결책도 역시 동일합니다. 함수를 사용하여 모듈 상태를 선언합니다. (2.3.0 부터 지원함)
+
+``` js
+const MyReusableModule = {
+  state () {
+    return {
+      foo: 'bar'
+    }
+  },
+  // 변이, 액션, getters...
+}
+```

+ 167 - 0
docs/kr/guide/mutations.md

@@ -0,0 +1,167 @@
+# 변이
+
+Vuex 저장소에서 실제로 상태를 변경하는 유일한 방법은 변이하는 것입니다. Vuex 변이는 이벤트와 매우 유사합니다. 각 변이에는 **타입** 문자열 **핸들러** 가 있습니다. 핸들러 함수는 실제 상태 수정을 하는 곳이며, 첫 번째 전달인자로 상태를받습니다.
+
+``` js
+const store = new Vuex.Store({
+  state: {
+    count: 1
+  },
+  mutations: {
+    increment (state) {
+      // 상태 변이
+      state.count++
+    }
+  }
+})
+```
+
+변이 핸들러를 직접 호출 할 수는 없습니다. 이 옵션은 이벤트 등록과 비슷합니다. "타입이 `increment`인 변이가 발생하면이 핸들러를 호출합니다." 변이 핸들러를 호출하려면 해당 타입과 함께 **store.commit** 을 호출해야합니다.
+
+``` js
+store.commit('increment')
+```
+
+### 페이로드를 가진 커밋
+
+변이에 대해 **payload** 라고하는 `store.commit`에 추가 전달인자를 사용 할 수 있습니다.
+
+``` js
+// ...
+mutations: {
+  increment (state, n) {
+    state.count += n
+  }
+}
+```
+``` js
+store.commit('increment', 10)
+```
+
+대부분의 경우 페이로드는 여러 필드를 포함할 수 있는 객체여야하며 기록 된 변이는 더 이해하기 쉽습니다.
+
+``` js
+// ...
+mutations: {
+  increment (state, payload) {
+    state.count += payload.amount
+  }
+}
+```
+``` js
+store.commit('increment', {
+  amount: 10
+})
+```
+
+### 객체 스타일 커밋
+
+변이를 커밋하는 또 다른 방법은 `type` 속성을 가진 객체를 직접 사용하는 것입니다.
+
+``` js
+store.commit({
+  type: 'increment',
+  amount: 10
+})
+```
+
+객체 스타일 커밋을 사용할 때 전체 객체는 변이 핸들러에 페이로드로 전달되므로 핸들러는 동일하게 유지됩니다.
+
+``` js
+mutations: {
+  increment (state, payload) {
+    state.count += payload.amount
+  }
+}
+```
+
+### Vue의 반응성 규칙을 따르는 변이
+
+Vuex 저장소의 상태는 Vue에 의해 반응하므로, 상태를 변경하면 상태를 관찰하는 Vue 컴포넌트가 자동으로 업데이트됩니다. 이것은 또한 Vuex 변이가 일반 Vue로 작업 할 때 동일한 반응성에 대한 경고를 받을 수 있음을 의미합니다.
+
+1. 원하는 모든 필드에 앞서 저장소를 초기화하는 것이 좋습니다.
+
+2. 객체에 새 속성을 추가할 때 다음 중 하나를 수행해야합니다.
+
+  - `Vue.set(obj, 'newProp', 123)`을 사용하거나,
+
+  - 객체를 새로운 것으로 교체하십시오. 예를 들어, 3 단계 [객체 확산 문법](https://github.com/sebmarkbage/ecmascript-rest-spread)을 사용하면 다음과 같이 작성할 수 있습니다.
+
+    ``` js
+    state.obj = { ...state.obj, newProp: 123 }
+    ```
+
+### 변이 타입에 상수 사용
+
+다양한 Flux 구현에서 변이 유형에 상수를 사용하는 것은 일반인 패턴입니다. 이를 통해 코드는 linter와 같은 툴링을 활용할 수 있으며 모든 상수를 단일 파일에 저장하면 공동 작업자가 전체 애플리케이션에서 어떤 변이가 가능한지 한눈에 파악할 수 있습니다.
+
+``` js
+// mutation-types.js
+export const SOME_MUTATION = 'SOME_MUTATION'
+```
+
+``` js
+// store.js
+import Vuex from 'vuex'
+import { SOME_MUTATION } from './mutation-types'
+
+const store = new Vuex.Store({
+  state: { ... },
+  mutations: {
+    // ES2015에서 계산 된 프로퍼티 이름 기능을 사용하여
+    // 상수를 함수 이름으로 사용할 수 있습니다
+    [SOME_MUTATION] (state) {
+      // 변이 상태
+    }
+  }
+})
+```
+
+상수를 사용할지 여부는 대부분 환경 설정입니다. 개발자가 많은 대규모 프로젝트에서 유용할 수 있지만, 이는 완전히 선택 사항입니다.
+
+### 변이는 무조건 동기적이어야 합니다.
+
+기억 해야할 한 가지 중요한 규칙은 **변이 핸들러 함수는 동기적** 이어야 한다는 것입니다. 왜 그럴까요? 다음 예제를 확인해보십시오.
+
+``` js
+mutations: {
+  someMutation (state) {
+    api.callAsyncMethod(() => {
+      state.count++
+    })
+  }
+}
+```
+
+이제 우리가 앱을 디버깅하고 devtool의 돌연변이 로그를 보고 있다고 상상해보십시오. 기록 된 모든 변이에 대해 devtool은 상태의 "이전" 및 "이후" 스냅 샷을 캡처 해야 합니다. 그러나 위의 예제 변이 내의 비동기 콜백은 불가능합니다. 변이가 커밋 되었을 때 콜백은 아직 호출되지 않으며, 콜백이 실제로 호출 될 시기를 devtool이 알 수 있는 방법이 없습니다. 콜백에서 수행 된 모든 상태 변이는 본질적으로 추적 할 수 없습니다!
+
+### 컴포넌트 안에서 변이 커밋하기
+
+`this.$store.commit('xxx')`를 사용하여 컴포넌트에서 변이를 수행하거나 컴포넌트 메소드를 `store.commit` 호출에 매핑하는 `mapMutations` 헬퍼를 사용할 수 있습니다 (루트 `store` 주입 필요)
+
+``` js
+import { mapMutations } from 'vuex'
+
+export default {
+  // ...
+  methods: {
+    ...mapMutations([
+      'increment' // this.increment()를 this.$store.commit('increment')에 매핑합니다.
+    ]),
+    ...mapMutations({
+      add: 'increment' // this.add()를 this.$store.commit('increment')에 매핑합니다.
+    })
+  }
+}
+```
+
+### 액션에서 사용
+
+비동기성이 상태의 변이와 결합하면 프로그램을 파악하기가 매우 어려워 질 수 있습니다. 예를 들어 상태를 변경하는 두 가지 비동기 콜백 메소드를 호출할 때 호출되는 시점과 먼저 호출 된 콜백을 어떻게 알 수 있습니까? 이것이 우리가 두 개념을 분리하려는 이유입니다. Vuex에서 **변이는 동기적으로 트랜잭션합니다.**
+
+``` js
+store.commit('increment')
+// "increment" 변이가 일으킬 수 있는 모든 상태 변화는 이 순간에 이루어져야합니다.
+```
+
+비동기 작업을 처리하기 위한 [액션](actions.md)를 소개합시다.

+ 127 - 0
docs/kr/guide/plugins.md

@@ -0,0 +1,127 @@
+# 플러그인
+
+Vuex 저장소는 각 변이에 대한 훅을 노출하는 `plugins` 옵션을 허용합니다. Vuex 플러그인은 저장소를 유일한 전달인자로 받는 함수입니다.
+
+``` js
+const myPlugin = store => {
+  // 저장소가 초기화 될 때 불립니다.
+  store.subscribe((mutation, state) => {
+    // 매 변이시마다 불립니다.
+    // 변이는 { type, payload } 포맷으로 제공됩니다.
+  })
+}
+```
+
+그리고 다음과 같이 사용할 수 있습니다.
+
+``` js
+const store = new Vuex.Store({
+  // ...
+  plugins: [myPlugin]
+})
+```
+
+### 플러그인 내부에서 변이 커밋하기
+
+플러그인은 상태를 직접 변이할 수 없습니다. 컴포넌트와 마찬가지로 변이를 커밋하여 변경을 트리거 할 수 있습니다.
+
+변이을 커밋함으로써 플러그인을 사용하여 데이터 소스를 저장소에 동기화 할 수 있습니다. 예를 들어, websocket 데이터 소스를 저장소에 동기화하려면 (이는 사실 인위적인 예제입니다. 실제로 `createPlugin` 함수는 더 복잡한 작업을 위해 몇 가지 추가 옵션을 필요로 할 수 있습니다)
+
+``` js
+export default function createWebSocketPlugin (socket) {
+  return store => {
+    socket.on('data', data => {
+      store.commit('receiveData', data)
+    })
+    store.subscribe(mutation => {
+      if (mutation.type === 'UPDATE_DATA') {
+        socket.emit('update', mutation.payload)
+      }
+    })
+  }
+}
+```
+
+``` js
+const plugin = createWebSocketPlugin(socket)
+
+const store = new Vuex.Store({
+  state,
+  mutations,
+  plugins: [plugin]
+})
+```
+
+### 상태 스냅샷 가져오기
+
+때로는 플러그인이 상태의 "스냅샷"을 얻고자 할 수 있으며, 또한 변이 이후 상태와 변이 이전 상태를 비교할 수 있습니다. 이를 달성하기 위해서는 상태 객체에 대한 깊은 복사를 수행해야합니다 :
+
+``` js
+const myPluginWithSnapshot = store => {
+  let prevState = _.cloneDeep(store.state)
+  store.subscribe((mutation, state) => {
+    let nextState = _.cloneDeep(state)
+
+    // prevState와 nextState를 비교하십시오.
+
+    // 다음 변이를 위한 상태 저장
+    prevState = nextState
+  })
+}
+```
+
+**상태 스냅 샷을 사용하는 플러그인은 개발 중에 만 사용해야합니다.** webpack 또는 Browserify를 사용하는 경우 빌드 도구가 이를 처리 할 수 있습니다.
+
+``` js
+const store = new Vuex.Store({
+  // ...
+  plugins: process.env.NODE_ENV !== 'production'
+    ? [myPluginWithSnapshot]
+    : []
+})
+```
+
+플러그인은 기본적으로 사용됩니다. 배포를 위해서는 webpack의 [DefinePlugin](https://webpack.js.org/plugins/define-plugin/) 또는 [envify](https://github.com/hughsk/envify)가 필요합니다. Browserify가 `process.env.NODE_ENV !== 'production'`의 값을 최종 빌드를 위해 `false`로 변환합니다.
+
+
+### 내장 로거 플러그인
+
+> [vue-devtools](https://github.com/vuejs/vue-devtools)를 사용하고 있으면 필요 없을 수 있습니다.
+
+Vuex에는 일반적인 디버깅을 위한 로거 플러그인이 함께 제공됩니다.
+
+``` js
+import createLogger from 'vuex/dist/logger'
+
+const store = new Vuex.Store({
+  plugins: [createLogger()]
+})
+```
+
+`createLogger` 함수는 몇 가지 옵션을 가질 수 있습니다.
+
+``` js
+const logger = createLogger({
+  collapsed: false, // 로그를 가지는 변이 자동 확장
+  filter (mutation, stateBefore, stateAfter) {
+    // 변이시 항상 로깅해야 한다면 true 를 반환하십시오.
+    // 변이는 { type, payload }의 포맷입니다.
+    return mutation.type !== "aBlacklistedMutation"
+  },
+  transformer (state) {
+    // 로깅하기전 상태를 변이 하십시오.
+    // 예를 들어 특정 하위 트리만 반환합니다.
+    return state.subTree
+  },
+  mutationTransformer (mutation) {
+    // 변이는 { type, payload }의 포맷으로 기록됩니다.
+    // 원하는 포맷으로 변경할 수 있습니다.
+    return mutation.type
+  },
+  logger: console, // `console` API의 구현체, default `console`
+})
+```
+
+로거 파일은`<script>`태그를 통해 직접 포함될 수 있으며 `createVuexLogger` 함수를 전역적으로 노출합니다.
+
+로거 플러그인은 상태 스냅샷을 사용하므로 개발용으로만 사용하십시오.

+ 109 - 0
docs/kr/guide/state.md

@@ -0,0 +1,109 @@
+# 상태
+
+### 단일 상태 트리
+
+Vuex는 **단일 상태 트리** 를 사용합니다. 즉, 이 단일 객체는 모든 애플리케이션 수준의 상태를 포함하며 "원본 소스" 역할을 합니다. 이는 각 애플리케이션마다 하나의 저장소만 갖게 된다는 것을 의미합니다. 단일 상태 트리를 사용하면 특정 상태를 쉽게 찾을 수 있으므로 디버깅을 위해 현재 앱 상태의 스냅 샷을 쉽게 가져올 수 있습니다.
+
+단일 상태 트리는 모듈성과 충돌하지 않습니다. 나중에 상태와 변이를 하위 모듈로 분할하는 방법에 대해 설명합니다.
+
+### Vuex 상태를 Vue 컴포넌트에서 가져오기
+
+그러면 Vue 컴포넌트에서 저장소 내부의 상태를 어떻게 표시하나요? Vuex 저장소는 반응적이기 때문에 저장소에서 상태를 "검색"하는 가장 간단한 방법은 [계산된 속성](http://kr.vuejs.org/guide/computed.html)내에서 일부 저장소 상태를 가져오는 것입니다.
+
+``` js
+// Counter 컴포넌트를 만듭니다
+const Counter = {
+  template: `<div>{{ count }}</div>`,
+  computed: {
+    count () {
+      return store.state.count
+    }
+  }
+}
+```
+
+`store.state.count`가 변경되면 계산된 속성이 다시 변경되고 관련 DOM 업데이트가 트리거됩니다.
+
+그러나 이 패턴은 컴포넌트가 전역 저장소 단독 항목에 의존하게합니다. 모듈 시스템을 사용할 때는 저장소 상태를 사용하는 모든 컴포넌트에서 저장소를 가져와야하며 컴포넌트를 테스트 할 때는 가짜데이터가 필요합니다.
+
+Vuex는 `store` 옵션(`Vue.use(Vuex)`에 의해 가능)으로 루트 컴포넌트의 모든 자식 컴포넌트에 저장소를 "주입"하는 메커니즘을 제공합니다.
+
+``` js
+const app = new Vue({
+  el: '#app',
+  // "store" 옵션을 사용하여 저장소를 제공하십시오.
+  // 그러면 모든 하위 컴포넌트에 저장소 인스턴스가 삽입됩니다.
+  store,
+  components: { Counter },
+  template: `
+    <div class="app">
+      <counter></counter>
+    </div>
+  `
+})
+```
+
+루트 인스턴스에 `store` 옵션을 제공함으로써 저장소는 루트의 모든 하위 컴포넌트에 주입되고 `this.$store`로 사용할 수 있습니다. `Counter` 구현을 수정해야 합니다.
+
+``` js
+const Counter = {
+  template: `<div>{{ count }}</div>`,
+  computed: {
+    count () {
+      return this.$store.state.count
+    }
+  }
+}
+```
+
+### `mapState` 헬퍼
+
+컴포넌트가 여러 저장소 상태 속성이나 getter를 사용해야하는 경우 계산된 속성을 모두 선언하면 반복적이고 장황해집니다. 이를 처리하기 위해 우리는 계산된 getter 함수를 생성하는 `mapState` 헬퍼를 사용하여 키 입력을 줄일 수 있습니다.
+
+``` js
+// 독립 실행 형 빌드에서 헬퍼가 Vuex.mapState로 노출됩니다.
+import { mapState } from 'vuex'
+
+export default {
+  // ...
+  computed: mapState({
+    // 화살표 함수는 코드를 매우 간결하게 만들어 줍니다!
+    count: state => state.count,
+
+    // 문자열 값 'count'를 전달하는 것은 `state => state.count`와 같습니다.
+    countAlias: 'count',
+
+    // `this`를 사용하여 로컬 상태에 액세스하려면 일반적인 함수를 사용해야합니다
+    countPlusLocalState (state) {
+      return state.count + this.localCount
+    }
+  })
+}
+```
+
+또한 매핑 된 계산된 속성의 이름이 상태 하위 트리 이름과 같을 때 문자열 배열을 `mapState`에 전달할 수 있습니다.
+
+``` js
+computed: mapState([
+  // this.count를 store.state.count에 매핑 합니다.
+  'count'
+])
+```
+
+### 객체 전개 연산자 (Object Spread Operator)
+
+`mapState`는 객체를 반환합니다. 다른 로컬 영역의 계산된 속성과 함께 사용하려면 어떻게 해야 하나요? 일반적으로, 최종 객체를 `computed`에 전달할 수 있도록 여러 객체를 하나로 병합하는 유틸리티를 사용해야합니다. 그러나 (3 단계 ECMAScript 스펙) [객체 전개 연산자 (Object Spread Operator)](https://github.com/sebmarkbage/ecmascript-rest-spread)을 사용하면 문법을 매우 단순화 할 수 있습니다.
+
+``` js
+computed: {
+  localComputed () { /* ... */ },
+  // 이것을 객체 전개 연산자(Object Spread Operator)를 사용하여 외부 객체에 추가 하십시오.
+  ...mapState({
+    // ...
+  })
+}
+```
+
+### 컴포넌트에는 여전히 로컬 상태가 있을 수 있습니다.
+
+Vuex를 사용한다고해서 Vuex에 **모든** 상태를 넣어야하는 것은 아닙니다. Vuex에 더 많은 상태를 넣으면 상태 변이가 더 명확하고 디버그 가능하지만, 때로는 코드를 보다 장황하고 간접적으로 만들 수 있습니다. 상태 조각이 단일 컴포넌트에 엄격하게 속한 경우 로컬 상태로 남겨 둘 수 있습니다. 기회비용을 판단하고 앱의 개발 요구에 맞는 결정을 내려야 합니다.

+ 25 - 0
docs/kr/guide/strict.md

@@ -0,0 +1,25 @@
+# Strict 모드
+
+strict 모드를 사용하기 위해, `strict: true`를 Vuex 저장소를 만들 때 추가하면 됩니다.
+
+``` js
+const store = new Vuex.Store({
+  // ...
+  strict: true
+})
+```
+
+엄격 모드에서는 Vuex 상태가 변이 핸들러 외부에서 변이 될 때 마다 오류가 발생합니다. 이렇게하면 디버깅 도구로 모든 상태 변이를 명시적으로 추적 할 수 있습니다.
+
+### 개발 vs. 배포
+
+**배포시 strict 모드를 켜지 마십시오!**  Strict 모드는 부적절한 변이를 감지하기 위해 상태 트리를 자세히 관찰합니다. 성능 이슈를 피하기 위해 배포 환경에서 이를 해제 하십시오.
+
+플러그인과 마찬가지로 빌드 도구가 다음을 처리하도록 할 수 있습니다.
+
+``` js
+const store = new Vuex.Store({
+  // ...
+  strict: process.env.NODE_ENV !== 'production'
+})
+```

+ 33 - 0
docs/kr/guide/structure.md

@@ -0,0 +1,33 @@
+# 애플리케이션 구조
+
+실제로 Vuex는 코드 구조를 제한하지는 않습니다. 이보다 아래에 있는 상위 수준 원칙을 강요합니다.
+
+1. 애플리케이션 레벨의 상태는 중앙 집중된 저장소 입니다.
+
+2. 상태를 변경시키는 유일한 방법은 동기 트랜잭션인 **변이** 를 커밋하는 것입니다.
+
+3. 비동기식 로직은 캡슐화되어야하며 **액션** 으로 구성 됩니다.
+
+
+이 규칙을 따른다면 프로젝트를 구조화하는 것은 사용자에게 달려 있습니다. 저장소 파일이 너무 커지면 액션, 돌연변이 및 getter를 개별 파일로 분할하기만 하면됩니다.
+
+중요한 앱의 경우 모듈을 활용해야 할 가능성이 높습니다. 다음은 프로젝트 구조의 예입니다.
+
+``` bash
+├── index.html
+├── main.js
+├── api
+│   └── ... # API 요청을 위한 추상화를 포함합니다.
+├── components
+│   ├── App.vue
+│   └── ...
+└── store
+    ├── index.js          # 모듈을 조합하고 저장소를 내보내는 곳 입니다.
+    ├── actions.js        # 루트 액션
+    ├── mutations.js      # 루트 변이
+    └── modules
+        ├── cart.js       # cart 모듈
+        └── products.js   # products 모듈
+```
+
+참고 사항으로, [장바구니 예](https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart)를 확인하십시오.

+ 241 - 0
docs/kr/guide/testing.md

@@ -0,0 +1,241 @@
+# 테스팅
+
+Vuex에서 단위 테스트를 하고자 하는 주요 부분은 변이와 액션입니다.
+
+### 변이 테스팅
+
+변이는 테스트하기 매우 간단합니다. 왜냐하면 변이는 전달인자에 완전히 의존하는 함수이기 때문입니다. 한 가지 트릭은 ES2015 모듈을 사용하고 `store.js` 파일에 변이를 넣는다면 기본 내보내기와 함께 변이를 명명된 내보내기로 내보낼 수 있다는 것입니다.
+
+``` js
+const state = { ... }
+
+// 변이를 이름을 가지는 내보내기를 이용하여 내보냅니다.
+export const mutations = { ... }
+
+export default new Vuex.Store({
+  state,
+  mutations
+})
+```
+
+Mocha + Chai를 사용하여 변이를 테스팅 하는 예(원하는 프레임워크/assertion 라이브러리를 사용할 수 있습니다.)
+
+``` js
+// mutations.js
+export const mutations = {
+  increment: state => state.count++
+}
+```
+
+``` js
+// mutations.spec.js
+import { expect } from 'chai'
+import { mutations } from './store'
+
+// 변이 가져오기
+const { increment } = mutations
+
+describe('mutations', () => {
+  it('INCREMENT', () => {
+    // mock 상태
+    const state = { count: 0 }
+    // 변이 적용
+    increment(state)
+    // 결과 확인
+    expect(state.count).to.equal(1)
+  })
+})
+```
+
+### 액션 테스팅
+
+액션은 외부 API를 호출 할 수 있기 때문에 좀 더 까다로울 수 있습니다. 액션을 테스트 할 때 우리는 일반적으로 조작을 어느 정도 해야합니다. 예를 들어 API 호출을 서비스로 추상화하고 테스트 내에서 해당 서비스를 조작 할 수 있습니다. 의존성을 쉽게 모방하기 위해 webpack과 [inject-loader](https://github.com/plasticine/inject-loader)를 사용하여 테스트 파일을 묶을 수 있습니다.
+
+비동기 액션 테스트 예제:
+
+``` js
+// actions.js
+import shop from '../api/shop'
+
+export const getAllProducts = ({ commit }) => {
+  commit('REQUEST_PRODUCTS')
+  shop.getProducts(products => {
+    commit('RECEIVE_PRODUCTS', products)
+  })
+}
+```
+
+``` js
+// actions.spec.js
+
+// 인라인 로더에는 require 구문을 사용하십시오.
+// inject-loader를 사용하면 조작된 의존성을
+// 주입 할 수있는 모듈 팩토리가 반환됩니다.
+import { expect } from 'chai'
+const actionsInjector = require('inject-loader!./actions')
+
+// 조작된 모의 응답과 함께 모듈 생성
+const actions = actionsInjector({
+  '../api/shop': {
+    getProducts (cb) {
+      setTimeout(() => {
+        cb([ /* 모의 응답 */ ])
+      }, 100)
+    }
+  }
+})
+
+// 예상되는 변이와 함께 테스팅 액션을 도와주는 헬퍼
+const testAction = (action, payload, state, expectedMutations, done) => {
+  let count = 0
+
+  // 모의 커밋
+  const commit = (type, payload) => {
+    const mutation = expectedMutations[count]
+
+    try {
+      expect(type).to.equal(mutation.type)
+      if (payload) {
+        expect(payload).to.deep.equal(mutation.payload)
+      }
+    } catch (error) {
+      done(error)
+    }
+
+    count++
+    if (count >= expectedMutations.length) {
+      done()
+    }
+  }
+
+  // 모의 저장소와 전달인자로 액션을 부릅니다.
+  action({ commit, state }, payload)
+
+  // 디스패치된 변이가 없는지 확인
+  if (expectedMutations.length === 0) {
+    expect(count).to.equal(0)
+    done()
+  }
+}
+
+describe('actions', () => {
+  it('getAllProducts', done => {
+    testAction(actions.getAllProducts, null, {}, [
+      { type: 'REQUEST_PRODUCTS' },
+      { type: 'RECEIVE_PRODUCTS', payload: { /* 모의 응답 */ } }
+    ], done)
+  })
+})
+```
+
+사용하는 테스팅 환경에서 스파이를 사용할 수 있다면 (예를 들어 [Sinon.JS](http://sinonjs.org/)같은) `testAction` 헬퍼 대신에 스파이를 사용할 수 있습니다.
+
+``` js
+describe('actions', () => {
+  it('getAllProducts', () => {
+    const commit = sinon.spy()
+    const state = {}
+    
+    actions.getAllProducts({ commit, state })
+    
+    expect(commit.args).to.deep.equal([
+      ['REQUEST_PRODUCTS'],
+      ['RECEIVE_PRODUCTS', { /* 모의 응답 */ }]
+    ])
+  })
+})
+```
+
+
+### Getters 테스팅
+
+Getter에 복잡한 연산이 있는 경우 테스트하는 것이 좋습니다. Getter는 변이와 같은 이유로 테스트하는 것이 매우 간단합니다.
+
+getter 테스팅 예제:
+
+``` js
+// getters.js
+export const getters = {
+  filteredProducts (state, { filterCategory }) {
+    return state.products.filter(product => {
+      return product.category === filterCategory
+    })
+  }
+}
+```
+
+``` js
+// getters.spec.js
+import { expect } from 'chai'
+import { getters } from './getters'
+
+describe('getters', () => {
+  it('filteredProducts', () => {
+    // mock state
+    const state = {
+      products: [
+        { id: 1, title: 'Apple', category: 'fruit' },
+        { id: 2, title: 'Orange', category: 'fruit' },
+        { id: 3, title: 'Carrot', category: 'vegetable' }
+      ]
+    }
+    // 모의 getter
+    const filterCategory = 'fruit'
+
+    // getter로 부터 결과를 받습니다
+    const result = getters.filteredProducts(state, { filterCategory })
+
+    // 결과 테스트
+    expect(result).to.deep.equal([
+      { id: 1, title: 'Apple', category: 'fruit' },
+      { id: 2, title: 'Orange', category: 'fruit' }
+    ])
+  })
+})
+```
+
+### 테스트 실행
+
+변이와 액션이 제대로 작성되면 적절한 모의 조작을 한 후 브라우저 API에 직접적인 의존성이 없어야합니다. 따라서 webpack을 사용하여 테스트를 번들로 묶어 Node를 이용해 직접 실행할 수 있습니다. 또는, `mocha-loader` 나 Karma + `karma-webpack`을 사용하여 실제 브라우저에서 테스트를 실행할 수 있습니다.
+
+#### Node를 이용한 실행
+
+다음과 같이 webpack 설정을 하십시오 ([`.babelrc`](https://babeljs.io/docs/usage/babelrc/)도 함께 필요 합니다.)
+
+``` js
+// webpack.config.js
+module.exports = {
+  entry: './test.js',
+  output: {
+    path: __dirname,
+    filename: 'test-bundle.js'
+  },
+  module: {
+    loaders: [
+      {
+        test: /\.js$/,
+        loader: 'babel-loader',
+        exclude: /node_modules/
+      }
+    ]
+  }
+}
+```
+
+이제,
+
+``` bash
+webpack
+mocha test-bundle.js
+```
+
+#### 브라우저에서 테스팅
+
+1. `mocha-loader`를 설치하세요.
+2. webpack 설정에서 `entry`를 `'mocha!babel!./test.js'`로 변경하세요.
+3. 설정을 이용하여 `webpack-dev-server`를 실행하세요.
+4. `localhost:8080/webpack-dev-server/test-bundle`로 가세요.
+
+#### 브라우저와 Karma + karma-webpack을 이용한 테스팅
+
+[vue-loader 문서](http://vue-loader.vuejs.org/en/workflow/testing.html)를 확인하세요.

+ 77 - 0
docs/kr/installation.md

@@ -0,0 +1,77 @@
+# 설치
+
+### 직접 다운로드 / CDN
+
+[https://unpkg.com/vuex](https://unpkg.com/vuex)
+
+<!--email_off-->
+[Unpkg.com](https://unpkg.com)은 NPM 기반 CDN 링크를 제공합니다. 위의 링크는 항상 NPM의 최신 릴리스를 가리킵니다. `https://unpkg.com/vuex@2.0.0`과 같은 URL을 통해 특정 버전/태그를 사용할 수도 있습니다.
+<!--/email_off-->
+
+Vue 뒤에 `vuex`를 추가하면 자동으로 설치됩니다:
+
+``` html
+<script src="/path/to/vue.js"></script>
+<script src="/path/to/vuex.js"></script>
+```
+
+### NPM
+
+``` bash
+npm install vuex --save
+```
+
+### Yarn
+
+``` bash
+yarn add vuex
+```
+
+모듈 시스템과 함께 사용하면 `Vue.use()`를 통해 Vuex를 명시적으로 추가해야 합니다.
+
+``` js
+import Vue from 'vue'
+import Vuex from 'vuex'
+
+Vue.use(Vuex)
+```
+
+전역 스크립트 태그를 사용할 때는 이 작업을 할 필요가 없습니다.
+
+### Promise
+
+Vuex는 [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises)를 필요로 합니다. 만약 지원 대상 브라우저가 아직 Promise를 구현하지 않았다면(예를 들어 IE), [es6-promise](https://github.com/stefanpenner/es6-promise)와 같은 polyfill 라이브러리를 사용할 수 있습니다.
+
+CDN을 통해서 포함할 수 있습니다:
+
+``` html
+<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.js"></script>
+```
+
+그러면 자동으로 `window.Promise`를 사용할 수 있습니다.
+
+NPM 이나 Yarn 같은 패키지 매니저를 사용한다면, 아래 명령어로 설치할 수 있습니다:
+
+``` bash
+npm install es6-promise --save # NPM
+yarn add es6-promise # Yarn
+```
+
+또한 Vuex를 사용하기 전에 아래 코드를 아무 곳에나 추가하십시오.
+
+``` js
+import 'es6-promise/auto'
+```
+
+
+### 개발용 빌드
+
+최신 dev 빌드를 사용하고 싶은 경우 직접 GitHub에서 클론하고 `vuex`를 직접 빌드 해야합니다.
+
+
+``` bash
+git clone https://github.com/vuejs/vuex.git node_modules/vuex
+cd node_modules/vuex
+npm install
+npm run build
+```