vue method와 computed의 차이

부루베릐·2022년 11월 6일
0

TIL

목록 보기
2/19

회사의 새 프로젝트에 답글 읽기 기능을 추가하면서 다음과 같은 요구 사항을 만족하는 코드를 작성해야 하는 경우가 생겼다.

  • 만약 해당 답글을 아직 읽지 않았다면, 해당 답글은 새 답글이다.
  • 새 답글을 읽음 처리 해 주기 위해서는 해당 답글을 클릭하면 된다.

따라서 각각의 답글 컴포넌트에 click 이벤트 핸들러가 바인딩되어야 하고, 클릭할 수 있다는 것을 사용자에게 알려주기 위해 cursor: pointer 스타일을 추가해야 한다.

따라서 이벤트 핸들러와 스타일 객체를 조건부로 바인딩하기 위해 다음과 같은 코드를 작성하였다.

<div
  v-for="comment in Comments"
  v-on="isNewComment(comment.is_dokyung_message, comment.read_at) 
        ? readableCommentClickEventHandler(comment.id) 
        : {}"
  :style="isNewComment(comment.is_dokyung_message, comment.read_at) 
          ? readableCommentStyle 
          : {}"
  :key="comment.id"
>

...

<script lang="ts">
export default defineComponent({
	setup(props) {
		const readableCommentStyle = reactive({
		  cursor: 'pointer'
		})
		const readableCommentClickEventHandler = (commentId: number) => ({
		  click: () => readComment(commentId)
		})
	
		return {
			...
		}
	}
})
</script>

이 때 조건부 바인딩의 조건이 되는 isNewCommentmethods로 작성하였는데, 이는 필요한 조건들을 인자로 받아서 이에 맞는 boolean 값을 리턴해주는 로직이 필요하기 때문이었다.

const isNewComment = (isDokyungMessage: string, readAt: Date | null) => {
  return isDokyungMessage === 'Y' && !readAt
}

나는 웬만한 조건문 안의 조건들은 computed로 작성을 해 왔었다. 그럼에도 불구하고 여기서 메서드를 사용했던 이유는 인자로 특정한 조건들을 받아야 했기 때문이다. 이렇게 놓고 보니, computed로 작성했던 기존의 코드들 역시 그냥 메서드로 대체하여 사용하면 되는 게 아닌가 하는 의문이 들었다. 즉, 메서드로도 작성할 수 있는 조건들을 굳이 computed로 사용하는 이유는 무엇인가?

vue의 공식 문서에는 다음과 같은 이야기가 있다.

Instead of a computed property, we can define the same function as a method. For the end result, the two approaches are indeed exactly the same. However, the difference is that computed properties are cached based on their reactive dependencies.

메서드와 computed 둘 다 같은 기능을 할 수 있지만, computed가 다른 점은 캐싱이 가능하다는 점. 밑의 코드를 보자.


methods: {
	isBookFromDokyung() {
		return this.book.owner === 'Dokyung' ? true : false
	}
}

위의 methods 코드와 밑의 computed 코드는 근본적으로는 같은 기능을 한다. 만약 두 속성 모두 컴포넌트에서 한 번씩만 호출되는 경우는 차이가 없을 수 있다.

computed: {
	isBookFromDokyung() {
		return this.book.owner === 'Dokyung' ? true : false
	}
}

하지만 이 둘이 여러 곳에서 접근된다고 가정해 보자.

<template>
	<div v-if="isBookFromDokyung" />
	...
	<div v-for="book in books" />
		<span v-if="isBookFromDokyung" />
	</div>
	... 
</template>

methods의 경우에는 접근이 일어날 때마다 메서드가 호출되어 계산이 이루어진다. 한 두번은 그러려니 할 수 있겠지만, 그 횟수가 수십 번, 수백 번이 일어나는 경우에는 성능 저하가 일어날 수 있다.

그러나 computed의 경우는 다르다. 만약 computed가 기대고 있는 reactive dependency들이 변하지 않는 이상, computed는 해당 계산을 하지 않고 이전에 계산되었던 값을 그대로 리턴한다.

다시 위의 코드로 돌아와서, 사실 저 코드는 computed를 사용하든 methods를 사용하든 큰 차이는 없을 것이다. 매 번 comment 데이터가 v-for를 통해 바뀌면서 새로 들어오기 때문에 계속해서 갈아치워지기 때문이다. 물론 computed의 경우 일부러 setter를 설정해 writable한 computed 속성을 만들 수도 있다. 하지만 캐싱에 대한 이점이 없다면 굳이 computed를 사용하지 않아도 될 것 같다.

예전에 팀원들이랑 computed를 사용하는 것이 성능상 떨어지지 않을까 고민했던 적이 있다. dependency가 변할 때마다 다시 계산을 수행하기 때문에, 불필요한 계산이 계속해서 일어나는 것이 아닐까 우려했던 것이다. 하지만 지금 돌이켜 보니 그 주장은 다시 생각해 볼 여지가 있는 듯 하다. 오히려 computed는 캐싱을 이용해 불필요한 계산을 줄임으로써 성능을 향상시키는 역할을 수행하고 있지 않을까 한다.


<참고 링크>
https://vuejs.org/guide/essentials/computed.html#computed-caching-vs-methods

<22.10.17 노션 글 아카이빙>

0개의 댓글