Computed vs Watch

uoayopยท2021๋…„ 10์›” 6์ผ
1

Vue

๋ชฉ๋ก ๋ณด๊ธฐ
3/4

๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ผ "computed๋ž‘ watch ๋‘˜ ๋‹ค ๋ฐ˜์‘ํ˜•์ด๋‹ˆ๊นŒ ๋˜‘๊ฐ™์€ ๊ฑฐ ์•„๋‹ˆ์•ผ?"
๐Ÿ‘ผ๐Ÿป "์•„๋‹˜"


Computed

  • ๋ฐ˜์‘ํ˜• getter

  • ํ…œํ”Œ๋ฆฟ์€ ๋‹จ์ˆœํ•˜๊ณ  ์„ ์–ธ์ ์ด์—ฌ์•ผ ํ•จ!

    ํ…œํ”Œ๋ฆฟ ๋‚ด์— ํ‘œํ˜„์‹์„ ๋„ฃ์œผ๋ฉด ํŽธ๋ฆฌํ•˜์ง€๋งŒ, ๋„ˆ๋ฌด ๋งŽ์€ ์—ฐ์‚ฐ์€ ํ…œํ”Œ๋ฆฟ์„ ๋ณต์žกํ•˜๊ณ  ์œ ์ง€ ๋ณด์ˆ˜๊ฐ€ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ฆ

  • ๋งŒ์•ฝ ์•„๋ž˜์™€ ๊ฐ™์€ ์ค‘์ฒฉ๋œ ๋ฐฐ์—ด์ด ์žˆ๋Š” ๊ฐ์ฒด์—์„œ, author ๊ฐ€ ์ฑ…์„ ๋ƒˆ๋Š”์ง€ ์•ˆ๋ƒˆ๋Š”์ง€์— ๋”ฐ๋ผ ์ฒดํฌ๋ฅผ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์Œ
<div id="computed-basics">
  <p>์ถœํŒ๋œ ์ฑ…:</p>
  <span>{{ author.books.length > 0 ? '์žˆ์Œ' : '์—†์Œ' }}</span>
</div>

Vue.createApp({
    data() {
        return {
          author: {
            name: '์กด ๋„์šฐ',
            books: [
              'Vue 2 - Advanced Guide',
              'Vue 3 - Basic Guide',
              'Vue 4 - The Mystery'
            ]
          }
        }
      }
})
  • <span> ํƒœ๊ทธ ๋‚ด์— ํ‘œํ˜„์‹์„ ๋„ฃ์œผ๋ฉด์„œ ์ง€์ €๋ถ„ํ•ด์ง
    • ๋งŒ์•ฝ author.books ์— ๋”ฐ๋ผ ํ•œ๋ฒˆ ๋” ๊ณ„์‚ฐ์„ ํ•ด์•ผํ•œ๋‹ค๋ฉด ๋” ์•…ํ™”๋จ
  • ๋ฐ˜์‘ํ˜• ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•˜๋Š” ๋กœ์ง์ธ ๊ฒฝ์šฐ, ์•„๋ž˜์™€ ๊ฐ™์ด computed ์†์„ฑ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•จ
<div id="computed-basics">
  <p>์ถœํŒ๋œ ์ฑ…:</p>
  <span>{{ publishedBooksMessage }}</span>
</div>

Vue.createApp({
  data() {
    return {
      author: {
        name: '์กด ๋„์šฐ',
        books: [
          'Vue 2 - Advanced Guide',
          'Vue 3 - Basic Guide',
          'Vue 4 - The Mystery'
        ]
      }
    }
  },
  computed: {
    publishedBooksMessage() {
      // ์—ฌ๊ธฐ์„œ์˜ `this` ๋Š” vm ์ธ์Šคํ„ด์Šค์ด๋‹ค.
      return this.author.books.length > 0 ? '์žˆ์Œ' : '์—†์Œ'
    }
  }
}).mount('#computed-basics')
  • computed ์†์„ฑ publishedBooksMessage ๋Š” author.books ์— ์˜์กดํ•จ.
    • books ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด publishedBooksMessage ์— ์˜์กดํ•˜๋Š” ๋ชจ๋“  ๋ฐ”์ธ๋”ฉ์„ ์—…๋ฐ์ดํŠธํ•จ

Computed์™€ ๋ฉ”์†Œ๋“œ ์ฐจ์ด

๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ผ "๊ทธ๋ƒฅ ๋ฉ”์†Œ๋“œ์— ๋˜‘๊ฐ™์ด publishedBooksMessage() ๋งŒ๋“ค๋ฉด ๋˜๋Š”๊ฑฐ ์•„๋…€?"
๐Ÿ‘ผ "๊ฒฐ๊ณผ๋Š” ๊ฐ™์ง€๋งŒ~~ ๋‚ด๋ถ€์ ์œผ๋ก  computed๊ฐ€ ๋” ์ข‹์Œ~~ "

  • author.books๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, computed ์†์„ฑ์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ๋ฒˆ ์ ‘๊ทผํ•˜๋”๋ผ๋„
    ํ•จ์ˆ˜๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•  ํ•„์š” ์—†์ด ์ด์ „์— ๊ณ„์‚ฐ๋œ ๊ฒฐ๊ณผ๋ฅผ ์ฆ‰์‹œ ๋ฐ˜ํ™˜ํ•จ!
  • ํ•˜์ง€๋งŒ ๋ฉ”์†Œ๋“œ์— ์„ ์–ธํ•œ ํ•จ์ˆ˜๋Š” ์žฌ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ํ•ญ์ƒ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๊ฒŒ ๋จ
  • Computed๋กœ Data๋ฅผ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜๋„ ์žˆ์Œ : set
    • this.fullName = "๋„์—ฐ ๊น€" ์„ ์‹คํ–‰ํ•˜๋ฉด, setter๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ 
      this.firstName๊ณผ this.lastName์ด ์•Œ์•„์„œ ์—…๋ฐ์ดํŠธ ๋จ!
computed: {
  fullName: {
    get() {
      return this.firstName + ' ' + this.lastName
    },
    set(newValue) {
      const names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}

watch

  • ๋ฐ˜์‘ํ˜• ์ฝœ๋ฐฑ

  • ์ธ์Šคํ„ด์Šค์˜ ํŠน์ • ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ์ง€์ •ํ•œ ์ฝœ๋ฐฑํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋จ

  • ์ฃผ๋กœ computed ์†์„ฑ์ด ๋” ๋งŽ์ด ์‚ฌ์šฉ๋˜์ง€๋งŒ, watch๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Œ

    • ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ ๋น„๋™๊ธฐ ์ž‘์—… (API ์ ‘๊ทผ) or ๋น„์šฉ์ด ๋งŽ์ด ๋“œ๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ๋•Œ ์‚ฌ์šฉ
<div id="watch-example">
  <p>
    ์˜ˆ/์•„๋‹ˆ์˜ค ์งˆ๋ฌธ์„ ๋ฌผ์–ด๋ณด์„ธ์š”.
    <input v-model="question" />
  </p>
  <p>{{ answer }}</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script>
  const watchExampleVM = Vue.createApp({
    data() {
      return {
        question: '',
        answer: '์งˆ๋ฌธ์€ ๋ณดํ†ต ๋ฌผ์Œํ‘œ๋ฅผ ํฌํ•ฉํ•ฉ๋‹ˆ๋‹ค. ;-)'
      }
    },
    watch: {
      // question ์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค, ์ด ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋  ๊ฒƒ ์ž…๋‹ˆ๋‹ค.
      question(newQuestion, oldQuestion) {
        if (newQuestion.indexOf('?') > -1) {
          this.getAnswer()
        }
      }
    },
    methods: {
      getAnswer() {
        this.answer = '์ƒ๊ฐ์ค‘...'
        axios
          .get('https://yesno.wtf/api')
          .then(response => {
            this.answer = response.data.answer
          })
          .catch(error => {
            this.answer = '์—๋Ÿฌ! API์— ๋‹ฟ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ' + error
          })
      }
    }
  }).mount('#watch-example')
</script>
  • ์‚ฌ์šฉ์ž๊ฐ€ input ์ฐฝ์— ๊ฐ’์„ ์ž…๋ ฅํ•  ๋•Œ๋งˆ๋‹ค, ๊ทธ ๊ฐ’์€ question์— ๋ฐ”์ธ๋”ฉ ๋จ
    โ–ถ watch๋กœ question์„ ๊ฐ์‹œํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ’์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ์ฒดํฌํ•˜๊ฒŒ ๋จ
    โ–ถ question์ด ๋ฌผ์Œํ‘œ๋กœ ๋๋‚˜๋ฉด, methods์— ์ •์˜๋œ getAnswer ํ˜ธ์ถœ
    โ–ถ axios๋ฅผ ์‚ฌ์šฉํ•ด api๋ฅผ ํ˜ธ์ถœํ•˜๊ณ , ๋น„๋™๊ธฐ๋กœ ๊ฐ’์„ ๋ณ€๊ฒฝํ•จ

๐ŸฅŠ Computed vs Watch

  • data์— ํ• ๋‹น๋œ ๊ฐ’ ์‚ฌ์ด์— ์ข…์†๊ด€๊ณ„๋ฅผ ์ž๋™์œผ๋กœ ์„ธํŒ…ํ•˜๋ ค๋ฉด computed

    • a ๊ฐ’์— ๋”ฐ๋ผ b ๊ฐ’์ด ๊ฒฐ์ •๋œ๋‹ค๋ฉด computed
    • ์™œ? ๐Ÿค”
      • ์ข…์† ๊ด€๊ณ„๊ฐ€ ๋ณต์žกํ•ด์ง„๋‹ค๋ฉด watch๋กœ ๊ตฌํ˜„ํ•  ๊ฒฝ์šฐ ์ค‘๋ณต ๊ณ„์‚ฐ์ด๋‚˜ ์ฝ”๋“œ ๋ณต์žก๋„๊ฐ€ ๋†’์•„์ง
  • ํŠน์ • ๋ฐ์ดํ„ฐ์˜ ๋ณ€๊ฒฝ ์‹œ์ ์— ํŠน์ • ์•ก์…˜ (call api, push route ...) ์„ ์ทจํ•˜๊ณ ์ž ํ•  ๋• watch


์ฐธ๊ณ 

๐Ÿ”— Computed ์†์„ฑ vs Watch ์†์„ฑ
๐Ÿ”— watch์™€ computed ์˜ ์ฐจ์ด์™€ ์‚ฌ์šฉ๋ฒ•

profile
slow and steady wins the race ๐Ÿข

0๊ฐœ์˜ ๋Œ“๊ธ€