Vue의 디렉티브(Directives)는 HTML 요소에 데이터와 동작을 선언적으로 연결하기 위한 템플릿 문법
DOM을 직접 조작하지 않고도 상태 변화에 따라 UI를 자동으로 업데이트 해줌
v- 접두사로 시작📌 예시
<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 이벤트를 대상.prevent → event.preventDefault() 자동 실행"doSomething" → 해당 메서드 실행if / for 문 같은 제어문은 불가)v-on → @ , v-bind → :, v-slot → #| 디렉티브 | 설명 | 예제 |
|---|---|---|
| v-if | 조건부 렌더링. 조건이 false면 DOM에서 제거 | <p v-if="isVisible">Hello</p> |
| v-show | CSS 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-html | HTML 문자열 렌더링 (XSS 주의) | <div v-html="rawHtml"></div> |
| v-text | HTML 해석 없이 텍스트만 바인딩 | <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; }
<!-- DOM 생성/제거 -->
<p v-if="isVisible">보입니다</p>
<!-- CSS 토글 -->
<p v-show="isVisible">보입니다</p>
| 구분 | v-if | v-show |
|---|---|---|
| 렌더링 방식 | DOM 생성/제거 | CSS display on/off |
| 초기 렌더링 비용 | 높음 | 낮음 |
| 토글 빈도 | 드물 때 유리 | 자주 바뀔 때 유리 |
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
:key 반드시 지정 (재렌더링 최소화, 고유한 값 사용)v-for + v-if 동시 사용 지양 → computed로 필터링 처리v-for가 v-if보다 우선순위가 높아서 모든 항목을 순회한 후 조건 체크)<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) 해야 함
Vue 내장 디렉티브로 충분하지 않을 때, 개발자가 직접 디렉티브를 정의할 수 있음
📌 작성 방법
app.directive('focus', {
mounted(el) {
el.focus();
}
});
사용 예시
<input v-focus />
→ 마운트 시 자동으로 커서가 해당 input으로 이동
| 훅 | 시점 | 설명 |
|---|---|---|
| created | 디렉티브 바인딩 시 | 초기 설정 (DOM 접근 불가) |
| beforeMount | 요소 DOM 삽입 전 | 초기화 준비 |
| mounted | 요소 DOM 삽입 후 | DOM 조작 가능 |
| beforeUpdate | 부모 업데이트 전 | 변경 전 처리 |
| updated | 부모 업데이트 후 | 변경 후 처리 |
| beforeUnmount | DOM 제거 전 | 정리 작업 |
| unmounted | DOM 제거 후 | 이벤트 리스너 해제 등 |
| 구분 | 권장 사용 | 비고 |
|---|---|---|
| 내장 디렉티브 | ✅ 데이터 중심 UI 조작 | 반응형 시스템과 완전히 통합 |
| 커스텀 디렉티브 | ⚠️ DOM 직접 접근이 꼭 필요할 때만 | 유지보수 부담 증가 |
→ DOM 직접 제어가 꼭 필요한 특수한 상황에 한해 커스텀 디렉티브를 최소한으로 사용하는 것이 좋음