계산된 속성(Computed Properties)

계산된 속성(Computed Properties)

템플릿 안의 표현식은 간단한 연산을 위해 만들어졌어요. 로직이 많아지면 템플릿이 비대해지고 유지보수도 어려워져요. 이런 경우 계산된 속성(computed property) 을 쓰면, 반응형 의존성을 자동으로 추적하면서 파생 값을 선언적으로 계산할 수 있어요.

출처: https://vuejs.org/guide/essentials/computed.html

기본 예시

중첩 배열을 가진 객체가 있다고 해볼게요.

const author = reactive({
  name: 'John Doe',
  books: [
    'Vue 2 - Advanced Guide',
    'Vue 3 - Basic Guide',
    'Vue 4 - The Mystery'
  ]
})

author가 책을 이미 갖고 있는지에 따라 다른 메시지를 보여주고 싶어요. 이것을 매번 템플릿에 바로 쓰면 중복이 생기고 지저분해져요. 이럴 때 calculated 속성을 쓰면 깔끔해져요.

<script setup>
import { reactive, computed } from 'vue'

const author = reactive({
  name: 'John Doe',
  books: [...]
})

// 계산된 ref
const publishedBooksMessage = computed(() => {
  return author.books.length > 0 ? 'Yes' : 'No'
})
</script>

<template>
  <p>Has published books:</p>
  <span>{{ publishedBooksMessage }}</span>
</template>

computed() 함수는 getter 함수를 인자로 받고, 반환값은 computed ref예요. 일반 ref처럼 publishedBooksMessage.value로 접근하고, 템플릿에서는 자동 unwrap되므로 .value 없이 쓸 수 있어요. computedauthor.books에 의존함을 자동으로 추적해서, author.books가 바뀌면 의존하는 바인딩도 갱신돼요.

Computed vs Methods

메서드를 호출해도 같은 결과를 얻을 수 있지만, computed는 캐싱된다는 결정적 차이가 있어요. computed는 반응형 의존성이 바뀌기 전까지는 다시 계산하지 않고 캐시된 값을 재사용해요. 반면 메서드는 재렌더링마다 항상 함수를 다시 실행해요.

쓰기 가능한 Computed

computed는 기본적으로 읽기 전용이지만, getter와 setter를 모두 제공하면 쓰기 가능해져요.

const firstName = ref('John')
const lastName = ref('Doe')

const fullName = computed({
  // getter
  get() {
    return firstName.value + ' ' + lastName.value
  },
  // setter
  set(newValue) {
    [firstName.value, lastName.value] = newValue.split(' ')
  }
})

fullName = 'John Doe'처럼 할당하면 setter가 호출되고 firstName·lastName이 갱신돼요.

이전 값 가져오기 (3.4+)

computed getter의 첫 번째 인자로 이전 값을 얻을 수 있어요. 조건을 만족하지 않을 때 이전 값을 유지하고 싶은 경우에 유용해요.

const count = ref(2)
const alwaysSmall = computed((previous) => {
  if (count.value <= 3) {
    return count.value
  }
  return previous
})

모범 사례

getter는 부작용(side effect)이 없어야 해요. computed getter 안에서 다른 상태를 변형하거나, async 요청을 하거나, DOM을 변형하면 안 됩니다. computed 속성을 "다른 값에 기반해 값을 파생하는 방법을 선언적으로 기술하는 것"으로 생각하고, 그 책임은 값을 계산해서 반환하는 것으로 한정해야 해요.

더 알아보기