Vue의 composable는 Vue 3의 Composition API에서 재사용 가능한 로직을 분리하고 관리하기 위한 함수입니다. 기본적인 아이디어는 컴포넌트의 상태와 관련된 로직을 함수로 추상화하여 코드의 재사용성과 유지 보수성을 높이는 것입니다.
// useCounter.js (컴포저블 함수)
import { ref } from 'vue';
export function useCounter() {
const count = ref(0);
const increment = () => {
count.value++;
};
const decrement = () => {
count.value--;
};
return {
count,
increment,
decrement
};
}
<template>
<div>
<p>{{ count }}</p>
<button @click="increment">Increment</button>
<button @click="decrement">Decrement</button>
</div>
</template>
<script>
import { useCounter } from './useCounter.js';
export default {
setup() {
const { count, increment, decrement } = useCounter();
return {
count,
increment,
decrement
};
}
}
</script>
useCounter가 각 컴포넌트에서 새로 호출되어 반응형 데이터인 count를 생성하므로, 각 컴포넌트는 개별적인 count를 소유하게 됩니다.
Vue에서 composable 함수를 관리하는 폴더 구조는 프로젝트의 규모와 팀의 요구에 따라 다를 수 있지만, 보편적으로 규모가 커질수록 컴포저블 함수들을 체계적으로 관리하는 것이 중요합니다. 다음은 업계에서 자주 사용되는 best practice와 그 이유를 설명한 구조입니다.
src/
├── components/
├── views/
├── composables/
│ ├── useCounter.js
│ ├── useFetch.js
│ └── useAuth.js
├── store/
└── router/
src/
├── components/
├── views/
├── composables/
│ ├── auth/
│ │ ├── useLogin.js
│ │ └── useLogout.js
│ ├── data/
│ │ ├── useFetch.js
│ │ └── useDataTransform.js
│ ├── ui/
│ │ └── useModal.js
│ └── useCounter.js
├── store/
└── router/
위와 같은 폴더 구조를 잡는 것이 일반적이며, index.js에서 한 번에 불러와 코드를 작성하는 것이 간편한 방식입니다.
export { useCounter } from './useCounter';
export { useFetch } from './data/useFetch';
export { useLogin, useLogout } from './auth';
import { useCounter, useFetch, useLogin } from '@/composables';