Vue 기본 문법 2. v-model 총 정리

손근영·2025년 5월 12일

Vue

목록 보기
3/7

1. v-bind + v-on 조합으로 만드는 양방향 바인딩

v-bindv-on을 조합하면 사용자 입력에 따라 JavaScript의 값이 실시간으로 업데이트되도록 만들 수 있습니다. 아래 코드는 사용자가 input에 입력한 값을 inputText1 변수에 반영합니다.

<template>
  <div>
    <p>{{ inputText1 }}</p>
    <input :value="inputText1" @input="onInput" />
  </div>
</template>

<script setup>
import { ref } from 'vue'
const inputText1 = ref('')
const onInput = function (event) {
  inputText1.value = event.target.value
}
</script>

이처럼 v-bindinput 요소의 값을 화면에 반영하고, v-on은 사용자의 입력 이벤트를 감지해 데이터에 반영합니다.
즉, 양방향 바인딩을 수동으로 구현하고 있는 셈입니다.


2. 기본 v-model 사용

Vue의 v-model은 위 코드에서 사용한 v-bindv-on의 조합을 한 줄로 축약한 디렉티브입니다.
같은 기능을 아래처럼 훨씬 간단하게 작성할 수 있습니다.

<template>
  <div>
    <p>{{ inputText2 }}</p>
    <input v-model="inputText2" />
  </div>
</template>

<script setup>
import { ref } from 'vue'

const inputText2 = ref('')
</script>

주의할 점: 모든 태그나 이벤트에 v-model을 쓸 수 있는 건 아닙니다.

v-model은 기본적으로 <input>, <textarea>, <select> 같은 폼 요소에 최적화되어 있으며, 내부적으로 value 속성과 input 이벤트를 통해 동작합니다.

따라서, <button>처럼 값 입력이 없는 요소에는 v-model이 의미 없습니다.

제가 공부하며 가장 놀란 점은, v-model이 단순 input 뿐만 아니라 checkbox, radio, select 등의 요소까지도 자동으로 적절하게 처리해준다는 것입니다.

예를 들어, 다음과 같은 코드를 봅시다.

<template>
  <div>
    <input type="checkbox" id="checkbox" v-model="checked" />
    <label for="checkbox">{{ checked }}</label>
  </div>
</template>

<script setup>
	import { ref } from 'vue'
	const checked = ref(false)
</script>

v-modelcheckbox 타입의 <input> 요소에 대해 자동으로 true/false 값을 바인딩해줍니다.

사용자가 체크박스를 클릭하면 checked 변수는 true 또는 false로 즉시 반응하며 변경됩니다.
별도의 이벤트 핸들러나 event.target.checked 같은 코드를 작성할 필요가 없습니다.

다중 checkbox도 당연히 적절하게 처리해줍니다.

<template>
	<div>Checked names: {{ checkedNames }}</div>

    <input type="checkbox" id="alice" value="Alice" v-model="checkedNames" />
    <label for="alice">Alice</label>

    <input type="checkbox" id="bella" value="Bella" v-model="checkedNames" />
    <label for="bella">Bella</label>
</template>

<script setup>
	import { ref } from 'vue'
	const checkedNames = ref([])
</script>

또, v-modelselect 태그도 적절하게 잘 처리해줍니다.

<div>Selected: {{ selected }}</div>

<select v-model="selected">
      <option disabled value="">Please select one</option>
      <option>Alice</option>
      <option>Bella</option>
      <option>Cathy</option>
</select>
    
    <script setup>
import { ref } from 'vue'
const selected = ref('')
</script>


3. v-model modifiers

v-model은 기본적으로 input 이벤트와 value를 자동으로 연결해주지만,
사용자 입력을 다룰 때 조금 더 정교한 동작이 필요할 때는 modifier를 활용할 수 있습니다.

Vue에서 제공하는 주요 v-model modifier는 다음과 같습니다.

Modifier설명
.lazyinput 이벤트가 아니라 change 이벤트에서 동기화
.number입력 값을 자동으로 숫자로 변환
.trim앞뒤 공백 제거 후 값 반영

  1. .lazy - 사용자가 입력을 마치고 나서 반영
<template>

    <input type="text" v-model="inputText1" />
    <div>
        {{ inputText1 }}
    </div>
    <input type="text" v-model.lazy="inputText2">
    <div>
    	{{ inputText2 }}
    </div>

</template>
  
<script setup>
  import { ref } from 'vue'

  const inputText1 = ref('');
  const inputText2 = ref('');
</script>
  

기본적으로는 입력할 때마다 v-model이 반응하지만,

.lazy를 사용하면 포커스를 잃거나 Enter 등의 키를 눌러야 값이 반영됩니다.

  1. .number - 자동 숫자 변환

사용자 입력이 자동으로 숫자로 유형 변환되도록 하려면, v-model 수식어로 .number를 추가하면 됩니다:

<template>

    <input type="text" v-model="inputText1" />
    <div>
        {{ inputText1 + 1}}
    </div>
    <input type="text" v-model.number="inputText2">
    <div>
        {{ inputText2 + 1}}
    </div>
    <input type="number" v-model="inputText3">
    <div>
        {{ inputText3 + 1}}
    </div>

</template>
  
<script setup>
  import { ref } from 'vue'

  const inputText1 = ref('');
  const inputText2 = ref('');
  const inputText3 = ref('');
</script>
  

주의

값을 parseFloat()로 파싱할 수 없으면 원래 값이 대신 사용됩니다.

인풋에 type="number"가 있으면 .number 수식어가 자동으로 적용됩니다.

  1. .trim - 입력값 양끝 공백 제거

사용자 입력의 공백이 자동으로 트리밍되도록 하려면 v-model 수식어로 .trim을 추가하면 됩니다:

<template>
    <input v-model.trim="username" />
    [{{ username }}]
</template>
  
<script setup>
  import { ref } from 'vue'

  const username = ref("");
</script>
  

참고자료 Vue.js 공식문서

0개의 댓글