Vue 3의 Composition API를 이용하면 재사용 가능한 로직을 훅(hook) 형태로 만들어 컴포넌트 간에 공유할 수 있습니다. 이는 코드 재사용성을 높이고, 컴포넌트를 더욱 모듈화하여 관리하기 쉽게 만듭니다.
왜 사용자 훅을 만들어야 할까요?
- 코드 재사용성 증가: 여러 컴포넌트에서 공통적으로 사용되는 로직을 한 번만 작성하여 재사용할 수 있습니다.
- 컴포넌트 복잡도 감소: 컴포넌트 내 로직을 작은 단위의 훅으로 분리하여 관리하기 쉬워집니다.
- 테스트 용이성 향상: 각 훅을 독립적으로 테스트할 수 있어 컴포넌트 전체를 테스트하는 것보다 효율적입니다.
- 더 나은 코드 가독성: 복잡한 로직을 작은 단위의 함수로 분리하여 코드를 더 명확하게 작성할 수 있습니다.
사용자 훅 만드는 방법
- 새로운 파일 생성: hooks 폴어를 만들고, 그 안에 훅 파일을 생성합니다. (예: useFetchData.js)
- 함수 정의: use로 시작하는 이름으로 함수를 정의합니다.
- 반응형 데이터 관리: ref, reactive, computed 등을 사용하여 반응형 데이터를 관리합니다.
- 로직 구현: 필요한 로직을 구현하고, 반환값으로 필요한 데이터를 제공합니다.
예시: 데이터 Fetching 훅
import { ref, onMounted } from 'vue';
export function useFetchData(url) {
const data = ref(null);
const error = ref(null);
const loading = ref(false);
onMounted(async () => {
loading.value = true;
try {
const response = await fetch(url);
data.value = await response.json();
} catch (error) {
console.error(error);
error.value = error;
} finally {
loading.value = false;
}
});
return { data, error, loading };
}
사용자 훅 사용 방법
<template>
<div v-if="loading">Loading...</div>
<div v-else-if="error">Error: {{ error }}</div>
<div v-else>
</div>
</template>
<script setup>
import { useFetchData } from '@/hooks/useFetchData';
const { data, error, loading } = useFetchData('https://api.example.com/data');
</script>
추가적인 팁
- 훅의 목적을 명확히 하기: 훅 하나에 하나의 기능만 담는 것이 좋습니다.
- 타입 선언: TypeScript를 사용한다면, 훅의 인자와 반환값에 타입을 명확히 선언하여 코드의 안정성을 높일 수 있습니다.
- 커스텀 훅 라이브러리 활용: VueUse와 같은 커스텀 훅 라이브러리를 활용하면 이미 구현된 유용한 훅들을 사용할 수 있습니다.
Vue 3 사용자 훅: 다양한 예시 및 활용법
1. 양식 유효성 검사 훅
import { ref, computed } from 'vue';
export function useFormValidation(rules) {
const formData = ref({});
const errors = ref({});
const validate = () => {
// rules에 따라 formData를 검증하고 errors에 오류 메시지 저장
};
const handleChange = (event) => {
formData.value[event.target.name] = event.target.value;
validate();
};
return { formData, errors, handleChange };
}
2. 데모 모드 훅
import { ref } from 'vue';
export function useDemoMode() {
const isDemoMode = ref(false);
const toggleDemoMode = () => {
isDemoMode.value = !isDemoMode.value;
};
return { isDemoMode, toggleDemoMode };
}
3. 지연 로딩 이미지 훅
import { ref, onMounted } from 'vue';
export function useLazyImage(src) {
const isLoaded = ref(false);
const imgRef = ref(null);
onMounted(() => {
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
isLoaded.value = true;
observer.disconnect();
}
});
observer.observe(imgRef.value);
});
return { isLoaded, imgRef };
}
4. 모달 관리 훅
5. 디바이스 감지 훅
import { ref, onMounted } from 'vue';
export function useDeviceDetect() {
const isMobile = ref(false);
onMounted(() => {
isMobile.value = window.innerWidth <= 768;
});
return { isMobile };
}
6. 데이터 페칭 및 캐싱:
import { ref, onMounted } from 'vue';
export function useFetchDataWithCache(url) {
const data = ref(null);
const isLoading = ref(false);
const error = ref(null);
const fetchData = async () => {
// ... 데이터 페칭 로직
};
onMounted(async () => {
// 캐시에서 데이터 가져오기
if (cachedData) {
data.value = cachedData;
} else {
isLoading.value = true;
try {
const response = await fetchData();
data.value = response;
// 캐시에 저장
} catch (error) {
error.value = error;
} finally {
isLoading.value = false;
}
}
});
return { data, isLoading, error };
}
7. 드래그 앤 드롭:
import { ref } from 'vue';
export function useDraggable(element) {
const isDragging = ref(false);
const offsetX = ref(0);
const offsetY = ref(0);
const handleDragStart = (event) => {
// ... 드래그 시작 이벤트 처리
};
const handleDragEnd = (event) => {
// ... 드래그 종료 이벤트 처리
};
const handleDrag = (event) => {
// ... 드래그 중 이벤트 처리
};
return { isDragging, offsetX, offsetY, handleDragStart, handleDragEnd, handleDrag };
}
8. 무한 스크롤
import { ref, onMounted } from 'vue';
export function useInfiniteScroll(fetchMoreData) {
const isLoading = ref(false);
const hasMore = ref(true);
const handleScroll = () => {
// ... 스크롤 이벤트 처리
};
onMounted(() => {
// ... 스크롤 이벤트 리스너 등록
});
return { isLoading, hasMore, handleScroll };
}
728x90
'웹개발 > vuejs' 카테고리의 다른 글
[Vue] Vue3에서 onBeforeUpdate() 훅 사용 가이드 (0) | 2024.07.30 |
---|---|
[Vue] Vue3에서 slot 사용하기 (0) | 2024.07.30 |
[Vue] VeeValidate 사용 가이드 (0) | 2024.07.30 |
[Vue] Vue3에서 onUpdated() 훅 사용 가이드 (0) | 2024.07.29 |
[Vue] Vue3에서 onBeforeUnmount() 훅 사용 가이드 (0) | 2024.07.29 |