본문 바로가기

Vue.js

[Udemy Vue 완벽가이드 Section15] 217. 게터(Getters) 소개-데이터를 얻는 더 나은 방법

state에 있는 데이터를 store에서 변경하기 위해 mutations를 사용했다.

컴포넌트 내부에서 상태를 직접 변경해서는 안된다.

(전에 발행한 mutations에 관한 글↓)

 

[Udemy Vue 완벽가이드 Section15] 215. 변형(Mutation) 소개 - 데이터를 변경하는 더 나은 방법

예측 가능한 상태 관리에 관해 이야기를 했었다. 예측 가능한 flow는 데이터 flow를 명확하게 정의하고, 데이터를 업데이트하고 얻을 때 특정 방식을 따르게 하여 오류 발생을 줄여준다. # state 직

lion284.tistory.com

 

[Udemy Vue 완벽가이드 Section15] 216. payload를 사용하여 변형(Mutation)에 데이터 전달

어떤 변형(Mutation) 메서드는 인수를 요구하기도 한다. 'increment' mutation에서는 더하고자 하는 값인 2이 하드코딩 되어있다. // main.js mutations: { increment(state) { state.counter = state.counter + 2; }, }, 'increase' m

lion284.tistory.com

 

# state를 직접 읽어오는것의 문제 - 코드의 중복

직접 상태를 읽어오는 것도 이상적이지 않을 수 있다.

왜 이상적이지 않을까?

 

이 앱에서는 TheCounter.vue 컴포넌트에서 counter를 출력한다.

또 다른 컴포넌트인 FavoriteValue.vue를 추가해보자.

TheCounter.vue와 동일하되, 'We do more...'라는 글자를 추가해보자.

이 컴포넌트를 사용하기 위해 App.vue에서 FavoriteValue 컴포넌트를 불러오자.

 

counter가 두개가 있고, 둘다 업데이트가 잘 된다.

 

 

이제 이 counter에 2를 곱한 값을 출력해보자.

FavoriteValue.vue에 업데이트하고, TheCounter.vue에서도 업데이트하자.

computed: {
  counter() {
    return this.$store.state.counter * 2;
  },
},

 

 

자, 여기서 문제가 발견되었다.

→ 바로, 코드의 중복

 

규모가 더 큰 애플리케이션에서는 충분히 발생할 수 있는 상황이다.

다른 컴포넌트에 같은 종류의 데이터가 여러개 있는 경우,

데이터의 형식을 바꾸거나 계산값을 다르게 바꿔야 한다면 다른 모든 컴포넌트에서 해당 코드를 수정해야한다.

그렇기 때문에 상태와 직접 통신하지 않는 이유!

 

 

 

# 해결책 - Getters

이 때 게터(Getters)라는 개념을 사용할 수 있다.

이 개념은 computed 프로퍼티와 같이, 저장소에 직접 정의되어 우리가 원하는 컴포넌트 내부에서 사용할 수 있다.

 

 

## Getters 추가 방법

게터를 Vuex 저장소에 추가해보자.

mutations 옆에 (위치 중요x) getters를 추가해보자.

게터는 객체를 받는다. 이제 이 객체의 모든 게터는 메서드이다.

 

computed 프로퍼티가 컴포넌트의 computed옵션에 있는 메서드인것처럼,

여기서 finalCounter라는 게터를 가질 수 있다.

finalCounter 게터 메서드는 Vuex에 있는 모든 게터 메서드처럼 두 개의 인수를 받는다.

첫 번째 인수인 state에서는 현재 상태를 가져와야하고, 두 번째 인수는 getters이다.

여기서 계산하려는 값이 다른 게터의 결과에 따라 달라지는 경우 게터에 다른 게터를 넣는 것이 유용할 수 있다.

지금은 무시하고, state 인수만 작업하자.

값을 반환하자.

그 값은 state에서 관리되는 counter로, 2를 곱한 값이다.

getters: {
 finalCounter(state){
  return state.counter * 2;
 }
}



 

## 컴포넌트 내에서 Getters 사용방법

이제 원하는 어떤 컴포넌트에서도 이 게터를 사용할 수 있다.

 

TheCounter.vue 컴포넌트 내에서 computed 프로퍼티에서 this.$store에 접근하여 state가 아닌, $store.getters에 접근한다.

그리고 게터 이름을 입력한다. 이 경우, finalCounter이다.

호출을 하거나 실행하는 것이 아니고, 그저 가리킬 뿐이다.

가리키면 Vuex가 getter메서드를 실행할 것이고, 현재 state를 게터에 전달한다.

<template>
  <h3>{{ counter }}</h3>
  <p>We do more...</p>
</template>
<script>
export default {
  computed: {
    counter() {
       return this.$store.getters.finalCounter;
    },
  },
};
</script>

 

이제 counter의 값을 3으로 곱하고 싶다면, 두 곳(TheCounter.vue, FavoriteValue.vue)이 아닌 한 곳(main.js의 getters객체)에서 코드를 수정하면 된다.

이렇게 저장하면 잘 작동하는 것을 확인할 수 있다.

 

 

## 여러 개의 getters

여러 개의 게터를 가질 수 있고, 게터는 서로에게 의존할 수 있다.

예를 들어 finalCounter 게터 외에 또다른 게터인 normalizedCounter를 추가해보자.

finalCounter값을 사용하여 이 값이 0보다 크고 100보다 작게 만들고 싶다.

이 범위를 벗어나면 0이나 100을 출력하게 하고싶다.

 

이를 구축할 하나의 방법으로는 counter * 3을 다시 계산하여 finalCounter라는 상수에 저장하고,

만약 finalCounter가 0보다 작으면 0을 출력하고, 100보다 크면 100을 출력한다.

이 두 가지 경우가 아닐때만 finalCounter를 출력한다.

getters: {
  finalCounter(state) {
    return state.counter * 3;
  },
  normalizedCounter(state) {
    const finalCounter = state.counter * 3;
    if (finalCounter < 0) {
      return 0;
    }
    if (finalCounter > 100) {
      return 100;
    }
    return finalCounter;
  },
},

참고로 게터에 두 줄 이상의 코드를 넣을 수 있다(게터의 또 다른 장점이기도 하다.).

 

이제 normalizedCounter가 있고, 이걸 FavoriteValue.vue 컴포넌트에 사용해보자.

<!--FavoriteValue.vue-->
<template>
  <h3>{{ counter }}</h3>
  <p>We do more...</p>
</template>
<script>
export default {
  computed: {
    counter() {
      return this.$store.getters.normalizedCounter;
    },
  },
};
</script>

 

이제 100을 초과하면 아래 counter는 100을 출력한다.

 

이렇게도 잘 작동하지만, 좋은 방법은 아니다.

왜냐하면, 다른 게터에서 계산한 것을 또 계산하고 있기 때문(const finalCounter = state.counter * 3;)

 

 

## getters의 두 번째 인수 - getters

이를 피하고자 getters라는 두 번째 인수를 추가한다.

이것으로 게터를 참조하여 finalCounter를 가져온다. getters.finalCounter를 호출하면 된다.

getters: {
  finalCounter(state) {
    return state.counter * 3;
  },
  normalizedCounter(_, getters) {
    const finalCounter = getters.finalCounter;
    if (finalCounter < 0) {
      return 0;
    }
    if (finalCounter > 100) {
      return 100;
    }
    return finalCounter;
  },
},

 

만약 finalCounter게터 안에 더 많은 코드가 있었다고 상상해보자.

getters 인수가 있다면 다른 게터에 있는 모든 코드를 복제할 필요가 없다.

따라서 getters인수로 finalCounter를 사용할 수 있다.

 

위 경우, 첫번째 인수인 state인수가 필요하지 않다.

따라서 여기서는 state인수는 밑줄(_)로 대체하자.

** 이 프로젝트 설정에서 사용하는 관행으로 두 번째 인수를 얻기 위해 getters인수는 사용하지만, state인수로는 작업하지 않는다는 뜻.

이렇게 해놓지 않으면 이 프로젝트의 설정은 사용하지 않는 인수에 대해 문제를 제기하기 때문에 관행을 사용해야한다.

 

 

** 출처: 모든 내용은 Udemy Vue-완벽가이드 강의를 기반으로 작성하였습니다.