본문 바로가기

개발/Vue

(14)
[Nuxt] useAsyncData 중복 API 호출 막기 Nuxt3 프로젝트에서 페이지를 새로고침을 하거나 같은 데이터를 패칭할 때 API가 두 번 이상 호출되는 문제가 생겼다. 중복 호출이 발생하는 이유Nuxt3는 SSR과 클라이언트 하이드레이션을 동시에 지원한다. 이 과정에서 동일한 데이터 패칭 로직이 서버와 클라이언트에서 각각 한번씩 실행될 수 있다. dedupe 옵션useAsyncData의 dedupe 옵션은 동일한 key로 중복 호출되는 API 요청을 제어하는 기능이다.dedupe 옵션을 사용하여 동일 key의 요청이 동시에 여러 번 발생하지 않도록 보장할 수 있다.cancel (기본값): 새 요청이 들어오면 기존 요청을 취소하고 새로 요청을 처리.defer: 기존 요청이 진행 중이면 새로운 요청을 만들지 않고, 기존 요청이 끝날 때까지 기다림. 사용..
[VUE] template render vs render function Vue 3에서 동적 컴포넌트를 임포트하는 두 가지 방식을 적용하고 비교해봤다. 1. 템플릿 방식- 코드가 직관적이고 가독성이 좋음- 일반적인 상황에서 권장되는 방식    2. 렌더 함수(h()) 방식 - 더 세밀한 프로그래밍적 제어가 가능함- 복잡한 렌더링 로직 구현에 유용함- 동적 컴포넌트 생성에 더 많은 유연성을 제공함import { h } from 'vue'const RenderComponent = { setup() { return () => h(currentComponent.value, { ...componentProps.value }); }};  두 가지 렌더링 방식을 실제로 비교해본 결과, 템플릿 방식이 가독성과 사용성 측면에서 더 좋았다. 렌더 함수(h()) 방식도 ..
[VUE] API 호출 중 로딩 화면 구현 Vue.와 Pinia를 사용하여 API 호출 중 로딩 화면을 구현하는 방법에 대해 설명한다. 로딩 상태 관리loadingStore.js 파일에서는 Pinia를 사용하여 로딩 상태를 관리한다.// loadingStore.js import { defineStore } from 'pinia';import { ref, computed } from 'vue';export const useLoadingStore = defineStore('loading', () => { // 로딩 상태를 추적하는 변수 const loadingCount = ref(0); // 로딩 카운트 증가 const increaseLoadingCount = () => { loadingCount.value++; }; // 로딩 카운트 감소 con..
[vue-dompurify-html] a태그 새 창 열기 HTML 코드를 안전하게 추가하기 위해 v-html 대신 vue-dompurify-html 라이브러리를 사용하고 있다. 그런데 a 태그에 target="_blank"를 설정해도 새 창으로 열리지 않는 문제가 발생했다.이 문제는 DOMPurify의 기본 설정에서 target 속성을 제거하기 때문이다. 이를 해결하기 위해 DOMPurify의 Hooks 기능을 사용하여 target="_blank"를 강제로 추가할 수 있었다.// main.jsimport { createApp } from 'vue';import VueDOMPurifyHTML from 'vue-dompurify-html';const app = createApp(App);app.use(VueDOMPurifyHTML, { // DOMPurify는 h..
[VUE] Scoped 스타일에서 자식 요소 스타일링 : deep() Vue에서 스타일 캡슐화(Scoped Styles)가 적용되면, 자식 컴포넌트나 특정 HTML 요소에 스타일을 적용하기 어려워진다.:deep()을 사용하면 scoped 스타일이 자식 컴포넌트나 외부 라이브러리의 컴포넌트에도 영향을 줄 수 있다.적용 예시1. 부모 컴포넌트에서 scoped 스타일을 자식 컴포넌트에 적용:deep()을 사용하여 부모 컴포넌트의 scoped 스타일을 자식 컴포넌트에도 적용할 수 있다. 자식 컴포넌트의 텍스트입니다. 2. 라이브러리를 사용한 컴포넌트에 적용Swiper, Vue-datepicker와 같은 외부 라이브러리의 컴포넌트에 scoped 스타일을 적용할 때도 :deep()을 사용하여 스타일을 캡슐화된 범위 내에서 적용할 수 있다. Slide 1 ..
[VUE3] swiper 부드럽게 흐르는 슬라이드, 일시정지 기능 추가 Swiper 카드 슬라이드가 천천히 흐르며, 일시정지/재생 버튼과 마우스를 올리면 슬라이드가 자동으로 일시정지되는 기능을 만들었다.  스와이퍼의 기본 멈춤 기능을 사용하면 슬라이드가 멈추긴 하지만, 이동이 완료된 후에야 멈추기 때문에 완전히 정지하는 데 시간이 걸린다. 이를 해결하기 위해 마우스를 올리거나 일시정지 버튼을 누르는 즉시 슬라이드가 멈추도록 controlSwiper 함수를 활용해 autoplay 멈춤 기능을 구현했다.스와이퍼가 부드럽게 흐르도록 하기 위해 swiper-wrapper 클래스에 transition-timing-function: linear !important;를 추가했다.또한, 스와이퍼 안의..
[VUE3 router] Navigation Guards로 로그인 페이지 이동 처리 라우터 네비게이션 가드를 활용하여 로그인 여부 체크 및 페이지 이동 프로젝트마다 라우터 네비게이션 가드를 사용해 로그인 상태를 확인했다.버전이 업데이트될 때마다 약간씩 수정해보았지만, 전체적인 구조는 비슷한 것 같다. routes meta 필드 추가라우터의 meta 필드에 requiresAuth를 추가했다.requiresAuth가 true인 경우: 로그인이 필요한 페이지 - 마이페이지requiresAuth가 없거나 false인 경우: 로그인 체크가 필요 없는 페이지 - 로그인, 회원가입// routerconst routes = [ // 마이페이지 { path: '/my-page', name: 'myPage', meta: { title: '마이페이지', requiresAuth: true, }..
[Pinia] Setup Stores 방식에 pinia-plugin-persistedstate 사용하기 기본적인 persist 적용 방법을 기록한다.설치$ npm i pinia-plugin-persistedstate 설정// main.jsimport { createPinia } from 'pinia'import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'const pinia = createPinia()pinia.use(piniaPluginPersistedstate) 사용setup 방식에서 저장할 값은 return 처리를 해야한다.// authStore.jsimport { defineStore } from 'pinia';import { ref } from 'vue';export const useAuthStore = defineStore( 'au..