본문 바로가기
FE/Vue.js

Vue.js Computed, Methods, Watch 비교

by Day0404 2021. 4. 9.
728x90
반응형

Vue.js Computed, Methods, Watch 비교

 

Nuxt.js로 개발을 하거나 공부를 할 때, Vue의 개념은 필수적입니다. 저는 Nuxt로 개발을 시작할 당시 Vue.js로 딱히 프로젝트를 진행해보지도 않았고, 개념정도만 알고 있는 그 정도였습니다. (약간 몸으로 부딪히며 배우는 스타일..)

그래서 Nuxt로 처음 프로젝트를 진행할 때, 중간 중간 Vue.js 개념도 다시 살펴보고 같이 공부하면서 진행했습니다.

물론 처음 Nuxt.js 기술검토할 때 Vue.js와 어떤 점이 다른지, 어떤 점이 편해졌는지 등은 공부했습니다.

(Nuxt.js는 자료가 너무 부족하여 굉장히 힘들었습니다...)

이번엔 Vue.js의 비슷하지만 다른 3가지 개념을 포스팅 하려고 합니다.

혹시나 알고 계신 것과 다른 점이 있다면 댓글로 꼭 말씀해주세요!

 

Methods VS Computed

computedmethods 와 다른 점

  • 인자를 전달할 수 없다
  • 반드시 return 값이 존재해야 한다.
  • template에서 함수 호출 형태인 ()를 사용할 수 없다.
  • 종속된 데이터 변경 시에만 계산된다.
  • 캐시 된다.

methodscomponent 가 관리하는 데이터가 변경될 때 마다 실행되며,

computed 는 종속된 데이터가 변경될 경우에만 실행이 됩니다.

데이터 변동이 없는 상태에서 computed는 이전의 계산된 값을 캐시해 두었다가 함수 호출시 다시 쓰게 됩니다.

반면 methods는 사용될 때마다 함수의 계산을 다시 하게 됩니다.

예제

 

<template>
  <div class="container">
    <h1>computed 포함</h1>
    <input type="button" class="btn btn-primary" @click="increaseComputedData()" :value="computedData">
    <br>
    <h1>computed 포함X</h1>
    <input type="button" class="btn btn-primary" @click="increaseMethodData()" :value="methodData">
    <br>
    <h1>아무 상관없는 methods</h1>
    <h2>{{noWorkFunction()}}</h2>
    <h1>computed data 가져오는 method</h1>
    <h2>{{getComputedData()}}</h2>
    <h1>computed data</h1>
    <h2>{{computedComputedData}}</h2>
  </div>
</template>

 

 

<script>

export default {
  data: function() {
    return {
      computedData: 0,
      methodData: 0,
    };
  },
  methods: {
    // button 클릭 시 data increase
    increaseComputedData() {
      this.computedData++;
    },
    increaseMethodData() {
      this.methodData++;
    },

    // 템플릿에서 사용되는 methods
    noWorkFunction() {
      console.log('computed data 와 상관없는 method 실행')
    },
    getComputedData() {
      console.log('computed data 가져오는 method 실행')
      return this.computedData;
    },
  },
  computed: {
    computedComputedData: function() {
      console.log('computed 실행')
      return this.computedData;
    }
  }
}
</script>

 

 

 

만약 데이터가 자주 변동되지 않는다면, 비용적인 면에서는 computed가 좋다고 할 수 있고,

데이터가 수시로 업데이트 된다면 계속해서 캐시를 저장하는 computed보다는 methods가 더 좋을 수 있습니다.

Computed VS Watch

computedwatch 모두 특정 데이터가 변경되었을 때 값을 조작할 수 있다는 공통점이 있지만

데이터를 가공해서 보여주는 역할은 computed, watch 는 아래와 같은 상황에서 사용합니다.

  • 서버와 통신
  • DOM 조작
  • local storage, audio playback 같은 browser API 사용 시

Vue.JS는 데이터가 변경 되었을 때 호출되는 콜백 함수를 정의하는 watch 속성을 제공합니다. watch는 감시할 데이터를 지정하고 그 데이터가 바뀌면 어떠한 함수를 실행하라는 방식의 명령형 프로그래밍(위키백과 명령형 프로그래밍) 방식입니다. 보통은 명령형 프로그래밍인 watch 보다는 선언형 프로그래밍인 computed를 사용하는 것이 더 좋다고 하네요.

따라서 computed 는 데이터의 변경에 반응하여, 특정 값을 반환해주는 일종의 getter 함수이며

watchcomputed 와 비슷하지만 특정 데이터가 변경되었을 때 지정한 callback 함수를 실행하는,

즉 사용 목적이 다른 속성이다.

 

computed 예제

<template>
  <div id="example">
    <p>원본 메시지: "{{ message }}"</p>
    <p>역순으로 표시한 메시지: "{{ reversedMessage }}"</p>
  </div>
</template>

<script>
export default {
  name: 'vue-computed-example',
  data(){
    return {
      message: 'Hello World!'
    }
  },
  computed: {
    // 계산된 getter
    reversedMessage: function () {
      return this.message.split('').reverse().join('')
    }
  }
}
</script>

 

위 예제 실행 시 message 의 값에 따라 reversedMessage 가 반환하는 값이 변경됩니다.

reversedMessage 라는 getter 함수가 message 에 의존성을 가지고 있기 때문이죠.

computed vs methods 의 내용에서 이미 설명했지만 computed 의 장점중 하나는

의존성을 가진 데이터가 변경되지 않으면 getter 호출 시 내부 로직 연산을 다시 하지 않고, 이미 계산되어 있는 결과를 즉시 반환한다는 점입니다.

이는 Vue가 데이터를 추적하기 위해 사용하는 방식 덕분인데, 연산이 부담스러운 데이터 같은 경우 이러한 특성을 잘 활용하면 불필요한 연산을 줄일 수 있습니다. 매번 연산이 필요할 경우엔 method를 활용하면 됩니다.

 

watch 예제

<template>
  <div>
    <div id="watch-example">
      <p>
        yes/no 질문해보세요:
        <input v-model="question">
      </p>
      <p>
        {{ answer }}
      </p>
    </div>
  </div>
</template>

<script>
export default {
  auth : false,
  data() {
    return {
      question: '',
      answer : '질문을 하기 전까지는 대답할 수 없습니다.',
    }
  },
  watch: {
    // 질문이 변경될 때 마다 이 기능이 실행됩니다.
    question : function (newQuestion) {
      this.answer = '입력을 기다리는 중...'
      this.debouncedGetAnswer()
    }
  },
  created() {
    // _.debounce는 lodash가 제공하는 기능으로
    // 특히 시간이 많이 소요되는 작업을 실행할 수 있는 빈도를 제한합니다.
    // 이 경우, 우리는 yesno.wtf/api 에 액세스 하는 빈도를 제한하고,
    // 사용자가 ajax요청을 하기 전에 타이핑을 완전히 마칠 때까지 기다리길 바랍니다.
    // _.debounce 함수(또는 이와 유사한 _.throttle)에 대한
    // 자세한 내용을 보려면 https://lodash.com/docs#debounce 를 방문하세요.
    this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
  },
  methods: {
    getAnswer: function () {
      if (this.question.indexOf('?') === -1) {
        this.answer = '질문에는 일반적으로 물음표가 포함 됩니다. ;-)'
        return
      }
      this.answer = '생각중...'
      var vm = this
      this.$axios.get('https://yesno.wtf/api')
        .then(function (response) {
          vm.answer = _.capitalize(response.data.answer)
        })
        .catch(function (error) {
          vm.answer = '에러! API 요청에 오류가 있습니다. ' + error
        })
    }
  }
}
</script>

<style scoped>

</style>

 

대부분의 경우 computed 속성이 더 적합하지만 사용자가 만든 감시자가 필요한 경우가 있습니다. 그래서 Vue는 watch 옵션을 통해 데이터 변경에 반응하는 보다 일반적인 방법을 제공합니다. 이는 데이터 변경에 대한 응답으로 비동기식 또는 시간이 많이 소요되는 조작을 수행하려는 경우에 가장 유용하다고 합니다.

위 예제의 경우 watch 옵션을 사용하면 비동기 연산 (API 엑세스)를 수행하고, 우리가 그 연산을 얼마나 자주 수행하는지 제한하고, 최종 응답을 얻을 때까지 중간 상태를 설정할 수 있습니다. computed 속성은 이러한 기능을 수행할 수 없습니다.

반응형

댓글