[Vue 3] 디렉티브(Directive)

예진·2024년 12월 2일

개인 공부

목록 보기
14/15
post-thumbnail

Vue 디렉티브란?

Vue의 디렉티브(Directives)는 HTML 요소에 데이터와 동작을 선언적으로 연결하기 위한 템플릿 문법
DOM을 직접 조작하지 않고도 상태 변화에 따라 UI를 자동으로 업데이트 해줌

  • 모든 디렉티브는 v- 접두사로 시작
  • HTML 속성처럼 보이지만, Vue가 해석 후 반응형 데이터에 맞춰 DOM을 자동으로 업데이트

📌 예시

<p v-if="isVisible">Hello</p>

isVisible이 true면 DOM에 추가, false면 제거됨


⚙️ 디렉티브 구조

v-on:click.prevent="doSomething"
구성 요소설명예시
디렉티브 이름Vue가 인식하는 기본 기능v-on, v-bind, v-if
매개 변수(Argument)디렉티브 대상 속성 또는 이벤트click, src, submit
수식어(Modifier)추가 동작 제어.prevent, .stop, .once
값(Value)실행할 표현식 또는 데이터"doSomething", "imageUrl"

📘 예시 해석

  • v-on → 이벤트 바인딩 디렉티브
  • click → click 이벤트를 대상
  • .preventevent.preventDefault() 자동 실행
  • "doSomething" → 해당 메서드 실행

🧩 디렉티브의 특징

  • 데이터 중심: 데이터가 바뀌면 Vue가 자동으로 DOM을 갱신
  • 표현식 가능: 단일 JavaScript 표현식만 허용 (단일 표현식만 가능, if / for 문 같은 제어문은 불가)
  • 축약형 지원: v-on@ , v-bind:, v-slot#
  • UI/로직 분리 용이: DOM 직접 접근 없이 데이터만 조작하므로 유지보수 쉬움

✅ 자주 쓰는 기본 디렉티브

디렉티브설명예제
v-if조건부 렌더링. 조건이 false면 DOM에서 제거<p v-if="isVisible">Hello</p>
v-showCSS display 속성 on/off<p v-show="isVisible">Hello</p>
v-for배열/객체를 반복 렌더링<li v-for="item in items" :key="item.id">{{ item.name }}</li>
v-model양방향 데이터 바인딩<input v-model="text" />
v-bind (:)HTML 속성 동적 바인딩<img :src="imageUrl" />
v-on (@)이벤트 바인딩<button @click="doSomething">Click</button>
v-htmlHTML 문자열 렌더링 (XSS 주의)<div v-html="rawHtml"></div>
v-textHTML 해석 없이 텍스트만 바인딩<span v-text="msg"></span>
v-pre템플릿 문법 해석 없이 구문을 그대로 출력<div v-pre>{{ rawTemplate }}</div>
v-cloak컴파일 완료 전 내용 숨김<div v-cloak>{{ msg }}</div>
v-once최초 한 번만 렌더링, 이후 업데이트 무시<p v-once>{{ title }}</p>

v-cloak 사용 시 CSS 필요 → [v-cloak] { display: none; }


💡 실무에서 자주 헷갈리는 디렉티브 비교

1. v-if vs v-show


<!-- DOM 생성/제거 -->
<p v-if="isVisible">보입니다</p>

<!-- CSS 토글 -->
<p v-show="isVisible">보입니다</p>
구분v-ifv-show
렌더링 방식DOM 생성/제거CSS display on/off
초기 렌더링 비용높음낮음
토글 빈도드물 때 유리자주 바뀔 때 유리
  • v-if: 조건이 자주 변하지 않을 때 (DOM 생성/제거 비용 높음)
  • v-show: 조건이 자주 바뀔 때 (CSS 속성만 변경)

2. v-for 성능 최적화

<li v-for="item in items" :key="item.id">{{ item.name }}</li>
  • :key 반드시 지정 (재렌더링 최소화, 고유한 값 사용)
  • v-for + v-if 동시 사용 지양 → computed로 필터링 처리
    (v-forv-if보다 우선순위가 높아서 모든 항목을 순회한 후 조건 체크)

3. v-html 보안 주의

<script setup>
import DOMPurify from 'dompurify' // npm install dompurify
import { ref, computed } from 'vue'

const userInput = ref('<img src=x>')

// 안전하게 정제된 HTML
const safeHtml = computed(() => DOMPurify.sanitize(userInput.value))
</script>

<template>
  <!-- ❌ 위험: XSS 공격 가능 -->
  <div v-html="userInput"></div>
  
  <!-- ✅ 안전: 악성 스크립트 제거 -->
  <div v-html="safeHtml"></div>
</template>

→ 사용자 입력을 그대로 v-html에 바인딩하면 XSS 공격 가능하므로, DOMPurify 같은 라이브러리로 반드시 정제(sanitize) 해야 함


🛠️ 커스텀 디렉티브(Custom Directive)

Vue 내장 디렉티브로 충분하지 않을 때, 개발자가 직접 디렉티브를 정의할 수 있음

언제 사용할까?

  • 주로 DOM 직접 접근이 필요한 기능을 구현할 때 사용
    (ex. 자동 포커스, 스크롤 감시, 외부 클릭 감지, 드래그/드롭 기능 등)
  • Vue의 반응형 데이터 흐름과 무관하게 순수 DOM 조작 구현 가능

📌 작성 방법

app.directive('focus', {
  mounted(el) {
    el.focus();
  }
});

사용 예시

<input v-focus />

→ 마운트 시 자동으로 커서가 해당 input으로 이동


⚙️ 커스텀 디렉티브의 라이프사이클 훅

시점설명
created디렉티브 바인딩 시초기 설정 (DOM 접근 불가)
beforeMount요소 DOM 삽입 전초기화 준비
mounted요소 DOM 삽입 후DOM 조작 가능
beforeUpdate부모 업데이트 전변경 전 처리
updated부모 업데이트 후변경 후 처리
beforeUnmountDOM 제거 전정리 작업
unmountedDOM 제거 후이벤트 리스너 해제 등

💡 정리

구분권장 사용비고
내장 디렉티브✅ 데이터 중심 UI 조작반응형 시스템과 완전히 통합
커스텀 디렉티브⚠️ DOM 직접 접근이 꼭 필요할 때만유지보수 부담 증가

→ DOM 직접 제어가 꼭 필요한 특수한 상황에 한해 커스텀 디렉티브를 최소한으로 사용하는 것이 좋음

profile
😊

0개의 댓글