v-model과 사용자 정의 디렉티브의 차이점과 직접 구현해보기
Vue에서 양방향 바인딩을 할 때 자주 사용하는 v-model.
이번 시간에는 v-model의 작동 방식과, 비슷한 기능을 디렉티브로 직접 만들어보는 방법을 다룹니다.
v-model이란?
- 양방향 바인딩을 위한 기본 디렉티브
- 사용자가 입력한 값을 자동으로 변수에 반영하고, 변수 값이 바뀌면 화면도 바뀜
예시
<input v-model="message" />
<p>{{ message }}</p>
사용자가 입력한 값이 message에 자동으로 들어가고, message가 바뀌면 다시 화면도 자동 업데이트 됩니다.
사용자 정의 디렉티브로 v-model처럼 만들기
목표
v-model 없이도, 사용자의 입력값을 변수에 실시간으로 반영할 수 있는 디렉티브 만들기
구현
v-model-lite 디렉티브 만들기
// directives/modelLite.js
export default {
mounted(el, binding) {
el.value = binding.value
// 사용자가 입력한 값을 부모 변수에 전달
el.addEventListener('input', (e) => {
binding.instance[binding.expression] = e.target.value
})
},
updated(el, binding) {
// 부모 값이 바뀌면 input 요소에도 반영
if (el.value !== binding.value) {
el.value = binding.value
}
}
}
- binding.expression: 문자열로 전달된 변수 이름
- binding.instance: 현재 컴포넌트 인스턴스
사용 예시
<template>
<input v-model-lite="nickname" />
<p>입력값: {{ nickname }}</p>
</template>
<script setup>
import { ref } from 'vue'
const nickname = ref('')
</script>
이제 v-model 없이도 입력값이 반영되고, 화면도 업데이트됩니다.
디렉티브 등록
// directives/index.js
import modelLite from './modelLite'
export default {
install(app) {
app.directive('model-lite', modelLite)
}
}
v-model과 디렉티브의 차이 정리
항목 v-model 사용자 정의 디렉티브
사용 편의성 | 매우 간편 | 약간의 설정 필요 |
내부 구현 | Vue에서 자동 처리 | 직접 처리해야 함 |
커스터마이징 | 한계 있음 | 마음대로 조작 가능 |
동작 범위 | input, textarea, 일부 컴포넌트 | 모든 DOM 요소 가능 |
단계 요약 (한눈에 정리)
- v-model은 Vue에서 기본 제공하는 양방향 바인딩 디렉티브
- 비슷한 기능을 v-model-lite 사용자 디렉티브로 직접 구현할 수 있음
- binding.instance, binding.expression을 사용하면 변수 제어 가능
- 디렉티브는 복잡한 바인딩 제어나 외부 조건 처리에 더 유리할 수 있음
💬 댓글
이번 글이 도움이 되었길 바랍니다. 궁금한 점이나 요청이 있다면 언제든 댓글로 남겨주세요. 댓글은 저에게 큰 힘이 됩니다. 다음 글도 기대해주세요.
'프론트엔드 개발 실무 > Vue3 + Vite 실전 가이드' 카테고리의 다른 글
『Vite + Vue3로 만드는 TodoList 실습 』 시리즈 강의안 (2) | 2025.06.15 |
---|---|
[Vue3 디렉티브 완전 정복 시리즈]10 사용자 정의 디렉티브 실전 프로젝트: v-guard로 로그인 상태 제어하기 (0) | 2025.06.07 |
[Vue3 디렉티브 완전 정복 시리즈]8 외부 라이브러리를 디렉티브로 감싸서 사용하는 방법 (0) | 2025.06.07 |
[Vue3 디렉티브 완전 정복 시리즈]7 디렉티브 vs 컴포넌트, 언제 무엇을 써야 할까? (2) | 2025.06.07 |
[Vue3 디렉티브 완전 정복 시리즈]6 실무에서 유용한 사용자 정의 디렉티브 예제 3가지 (0) | 2025.06.07 |