Vue에서 기본적으로 컴포저블이란, 상태 저장 로직들을 캡슐화하고 재사용하기 위해 만들어진 함수이다.
상태 저장 자체는 컴포저블의 목적이 아니다. 상태저장은 싱글톤으로 만들어진 전역 객체라면 다 가능하다. 물론 SSR에서는 좀 달라지지만…
상태 저장 로직을 이해하려면, 상태 비 저장 로직들을 먼저 이해하는게 편하다. 그쪽이 훨씬 종류가 다양하기 때문이다. 예를들면 lodash
나 date-fns
는 대표적인 상태 비저장 라이브러리들임. 어떤 날짜를 입력받고, 이를 조작해서 반환하기만 하는 함수가 있다면 이 함수는 상태 비 저장 로직이다. 어떠한 값도 함수 종료 이후 함수 내에 저장되지 않기 때문이다.
그러나 상태 저장 로직들은 시간에 따라 값이 변경될 수 있는 상태들을 저장하고 있다. 간단한 예로, 페이지에서 현재 마우스의 위치를 추적하는 함수이다.
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
const x = ref(0)
const y = ref(0)
function update(event) {
x.value = event.pageX
y.value = event.pageY
}
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
</script>
<template>마우스 위치: {{ x }}, {{ y }}</template>
이런 상태 저장 로직들이 여러 컴포넌트에서 동일하게, 재사용된다고 생각해보자. 이때 상태 저장 로직들을 컴포저블 함수로 재구성해 외부 파일로 추출할 수 있다.
쉽게 말해 재사용될 로직들을 캡슐화하는 것이 목적임.
// mouse.js
import { ref, onMounted, onUnmounted } from 'vue'
// 관례상, 컴포저블 함수 이름은 "use"로 시작합니다.
export function useMouse() {
// 컴포저블로 캡슐화된 내부에서 관리되는 상태
const x = ref(0)
const y = ref(0)
// 컴포저블은 시간이 지남에 따라 관리되는 상태를 업데이트할 수 있습니다.
function update(event) {
x.value = event.pageX
y.value = event.pageY
}
// 컴포저블은 또한 이것을 사용하는 컴포넌트의 생명주기에 연결되어
// 사이드 이펙트를 설정 및 해제할 수 있습니다.
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
// 관리 상태를 반환 값으로 노출
return { x, y }
}
💡 컴포저블 함수들은
useXXX
의 형태를 가지는 것이 관습이다.
그리고 위의 컴포저블 함수는 다음처럼 컴포넌트에서 사용된다.
<script setup>
import { useMouse } from './mouse.js'
const { x, y } = useMouse()
</script>
<template>마우스 위치: {{ x }}, {{ y }}</template>
위에서 알 수 있듯이, 컴포저블 함수들은 반복되는 로직들을 캡슐화하고 노출되어야 하는 상태만 반환한다.