티스토리 뷰

오늘은 Vuex의 세번째 이야기인 Getters에 대해서 이야기해보기 전에 잠깐 잡설을 풀어보려고 한다.

Vuex를 공부하면서 Vue에서 사용되는 Option들인 "el" 이라던가 "data"라던가 "computed" 같은 애들이 어떤 방식으로 동작을 하는지, 그리고 어떻게 코딩을 하면되는지 스스로 다시금 연구를 하게 되었다.

 

Javascript라는 언어 자체는 굉장히 유연한 언어라는 점에서 사고를 출발해야한다.

"객체"라는 것에 대한 것, 그리고 동기, 비동기방식의 오묘함에 대해서 제대로된 이해가 안된다면 사실 Javascript는 너무나도 난해한 언어밖에 되지 않는다는 것을 이해해야한다. 그래서 Javascript라는 언어가 처음에 시작하기에 쉽지만 어려운 언어라는 이야기를 하게되는 것인지도 모른다.

 

Vue.js를 며칠 만져보고 이것저것 가이드를 보면서 사용해본 결과 앞에서 말했던 "객체"를 굉장히 잘 다뤄야겠다는 생각을 했다. 그래서 처음에 가이드에 나온 문법들이 이해하기 어려웠던 이유가 아닐까 생각했다.

특정한 상태에서는 그냥 Object를 대입하면 괜찮았는데 어떤 환경에서는 Function을 대입해야하는 상황이라던지 혹은 어떤 옵션은 배열을 받던지 혹은 객체를 받는다던지 파라미터가 특정하지 않아서 햇깔린다던지 한다는 점들이 Vue.js를 공부하는 입장에서 굉장히 난해한 부분으로 다가왔다.

 

게다가 요즘의 Javascript는 격변기라서 (ES5, ES6, TypeScript...etc) 막 초급딱지 뗀 친구들은 뭐가 뭔지 알 수가 없는 요상함이 가득해져서 결국 뭘 어떻게 공부하라는건지 어느 장단에 춤을 춰야할 지 모르겠다는 생각이 든다.

어쩌라는거냐!

근데 사실 이런 문제들은 정답이 없어서 그저 열심히 이것저것 들여다보면서 남들 하는거 따라하고 책에 있는 예제들 따라하다보면 어느날 그 "장단"에 맞춰 춤을 추는게 아니라 "춤"에 맞춰서 장단을 고르는게 맞다는 걸 이해하게 된다.

그러니까 모르는 이야기에 좌절말고 그냥 배워고 따라해보자. 화이팅(뭔가 급하게 정리하고 "화이팅"하면서 썰을 마무리한 것 같다고 느꼈다면 느낌일 뿐이다. 그렇다. 엣헴.)

 

잡설은 이쯤하고 오늘 배워볼 Getters에 대해서 시작한다. 엣헴.

 

Getters는 말 그대로 Getter들이다. Getter는 다들 알겠지만 값을 가져오는 함수같은거라고 생각하면 된다.

예를 들어서 저번시간 사용한 소스에서 App.vue를 아래와 같이 수정해보자.

 

<template>
  <div id="app">
    <HelloWorld></HelloWorld>
  </div>
</template>

<script>
import Vue from 'vue'
import Vuex from 'vuex'
import HelloWorld from './components/hello'

Vue.use(Vuex)

const store = new Vuex.Store({
    state: {
        todos: [
            { id: 1, text: '출근하기', done: true },
            { id: 2, text: '아침밥 몰래 먹기', done: false },
            { id: 2, text: '점심시간까지 시간 보내기', done: false }
        ]
    },
    getters: {
        doneTodos: function( state ) {
            return state.todos.filter( function( todo ){
                return todo.done
            })
        }
    }
})

export default {
    name: 'app'
    , store
    , components: {
        HelloWorld
    }
}
</script>

코드를 보면 store에서 getters 를 통해 doneTodos라는 메서드를 제공한다. 이 메서드는 state의 todos 중에 done 속성이 true 인 녀석만 필터링하여 제공해준다는 것을 알 수 있다.

 

그럼 hello.vue 파일을 아래와 같이 수정하자

<template>
    <div>
        <h1>Todo List</h1>
        <ul>
            <li v-for="item in todoList" v-bind:key="item.id">
                {{item.text}}
            </li>
        </ul>
    </div>
</template>
<script>
import { mapState } from 'vuex';

export default {
    name: 'HelloWorld'
    , computed: mapState({
        todoList: function(state) {
            return state.todos
        }
    })
}
</script>

이렇게 만들어주면 아래와 같은 화면을 볼 수 있다.

자, 그럼 이렇게 나온 리스트에 getter를 이용해서 몇가지 기능을 추가해보도록 하자.

hello.vue 에 버튼과 조건문을 넣고 getters를 이용해서 기능을 추가하자.

 

<template>
    <div>
        <h1>Todo List</h1>
        <button v-on:click="onBtnClick">{{getBtnText}}</button>
        <ul>
            <li v-for="item in todoList" v-bind:key="item.id">
                {{item.text}}
            </li>
        </ul>
    </div>
</template>
<script>
import { mapState } from 'vuex';

export default {
    name: 'HelloWorld'
    , data: function() {
        return {
            isFilter: false
        }
    }
    , computed: mapState({
        todoList: function(state, getters) {
            var list, self = this

            if( self.isFilter) {
                list = getters.doneTodos;
            } else {
                list = state.todos
            }

            return list;
        }, getBtnText: function() {
            var message, self = this
            message = self.isFilter ? "전체 목록 보기" : "완료된 목록만 보기"

            return message
        }
    }), methods: {
        onBtnClick: function(){
            this.isFilter = !this.isFilter;
        }
    }
}
</script>

이제 버튼을 누르면 버튼의 텍스트가 토글되고 리스트의 종류가 변경되는데 computed의 todoList를 살펴보자.

 

data의 isFilter 값을 true로 변경하게 되면 list 의 내용을 파라미터인 getters의 doneTodos를 가져오게 된다. doneTodos는 App.vue 에서 미리 정의한 getters의 함수로 실제로 사용할 때는 함수가 아닌 "속성 값" 처럼 사용하게 된다는 점이 특징이다. 이렇게 코딩을 하면 아래의 이미지처럼 동작하는 것을 확인할 수 있다.

그러면 함수의 함수를 호출함으로써 getters를 속성이 아닌 매서드로 접근하는 방법을 알아보자.

 

App.vue 의 getters에 함수 하나를 추가하자.

아참 이번에는 람다(Lambda) 식처럼 코드를 작성할테니 잘 적응하기 바란다.(MDN에서는 화살표함수라고 부르더라)

<template>
  <div id="app">
    <HelloWorld></HelloWorld>
  </div>
</template>

<script>
import Vue from 'vue'
import Vuex from 'vuex'
import HelloWorld from './components/hello'

Vue.use(Vuex)

const store = new Vuex.Store({
    state: {
        todos: [
            { id: 1, text: '출근하기', done: true },
            { id: 2, text: '아침밥 몰래 먹기', done: false },
            { id: 3, text: '점심시간까지 시간 보내기', done: false }
        ]
    },
    getters: {
        doneTodos: function( state ) {
            return state.todos.filter( function( todo ){
                return todo.done
            })
        }, findTodoById: (state) => (id) => state.todos.find(todo => todo.id === id) 
    }
})

export default {
    name: 'app'
    , store
    , components: {
        HelloWorld
    }
}
</script>

 

getters에 findTodoById 라는 메서드를 추가했다. 사실 풀어서 써도 괜찮지만 너무 복잡한 반환관계일 때는 이렇게 화살표 함수도 나쁜 방법은 아니다. 이해가 잘 안간다면 화살표 함수에 대해서 조금 공부하고 오자.

(https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/%EC%95%A0%EB%A1%9C%EC%9A%B0_%ED%8E%91%EC%85%98)

 

그리고 hello.vue 파일도 수정하자.

<template>
    <div>
        <h1>Todo List</h1>
        <div>
            <input type="text" v-model="todoId" />
            <button v-on:click="onBtnClick">{{getBtnText}}</button>
        </div>
        <hr />
        <ul>
            <li v-for="item in todoList" v-bind:key="item.id">
                {{item.text}}
            </li>
        </ul>
    </div>
</template>
<script>
import { mapState } from 'vuex';

export default {
    name: 'HelloWorld'
    , data: function() {
        return {
            isFilter: false
            , todoId: 1
        }
    }
    , computed: mapState({
        todoList: function(state, getters) {
            var list, self = this

            if( self.isFilter) {
                list = [getters.findTodoById( parseInt( self.todoId ))];
            } else {
                list = state.todos
            }

            return list;
        }, getBtnText: function() {
            var message, self = this
            message = self.isFilter ? "전체 목록 보기" : "검색된 목록만 보기"

            return message
        }
    }), methods: {
        onBtnClick: function(){
            this.isFilter = !this.isFilter;
        }
    }
}
</script>

이렇게 만들면 input 에 넣은 숫자대로 getters의 findTodoById에 파라미터로 전달하여 state의 todos 목록에서 항목을 찾아 반환하고 화면에 표시하는 코드가 된다.

오늘은 이상한 잔소리와 함께 Vuex의 getters 를 알아보는 시간을 가졌다. 지난번의 state와 getters를 활요하여 Vue안에 녹여 사용하는 방법과 컴포넌트간 상태값 공유와 이용방법에 대해서 조금씩 알아가는 시간이었던 것 같다.

 

다음 시간엔 Vuex의 네번째 이야기 Mutation(변이)에 대해서 알아보도록 하자.

 

그럼 안녕!

 

 

 

댓글
댓글쓰기 폼