웹 서비스를 만들 때 사용자의 정보를 입력받는 '폼(Form)'은 절대로 빼놓을 수 없는 기능입니다.
회원가입, 로그인, 게시글 작성, 댓글 달기 등 대부분의 상호작용이 폼을 통해 이루어지기 때문입니다.
오늘은 Vue.js가 얼마나 쉽고 강력하게 폼 입력을 처리하는지 보여주는,
v-model
에 대해 집중적으로 배워보겠습니다.
v-model
을 사용하면 사용자가 입력 필드에 타이핑하는 값이 스크립트 내의 데이터와 실시간으로 동기화되며, 이것을
양방향 데이터 바인딩
이라고 부릅니다.
v-model
을 이해하려면 먼저
양방향 데이터 바인딩
이 무엇인지 알아야 합니다.
데이터 바인딩
스크립트 코드의 데이터(state)와 화면에 보이는 HTML 요소(view)를 연결하는 것을 의미합니다.
단방향 데이터 바인딩
데이터는 코드에서 화면 방향으로만 흐릅니다.
React의 기본 방식처럼, 데이터가 바뀌면 화면이 업데이트되지만, 화면의 입력이 직접 데이터를 바꾸지는 못합니다.
양방향 데이터 바인딩
데이터가 코드에서 화면으로, 그리고 화면에서 코드로 양쪽 방향 모두 흐릅니다.
사용자가 입력창에 글자를 쓰면, 그 값이 즉시 코드의 데이터에 반영되고, 반대로 코드에서 데이터를 바꾸면 입력창의 값도 바로 바뀝니다.
v-model
은 이 양방향 데이터 바인딩을 단 한 줄의 코드로 구현해주는 아주 편리한 디렉티브입니다.
사실
v-model
은 내부적으로
v-bind
와
v-on
을 합쳐놓은 것입니다.
예를 들어 아래 두 코드는 완전히 동일하게 동작합니다.
<!-- v-model을 사용한 경우 -->
< input v-model = "searchText" >
<!-- v-bind와 v-on으로 풀어쓴 경우 -->
< input :value = "searchText" @input = "event => searchText = event.target.value" >
v-model
덕분에 우리는 복잡한 이벤트 처리 코드를 매번 작성할 필요 없이, 아주 간결하게 폼을 다룰 수 있습니다.
양방향 데이터 바인딩
v-model
은 텍스트 입력창뿐만 아니라 체크박스, 라디오 버튼, 드롭다운 메뉴 등 거의 모든 종류의 폼 요소에서 사용할 수 있습니다.
✅
1. 텍스트 입력 (input, textarea) 🔗
가장 기본적인 사용법입니다.
ref
로 만든 반응형 변수에
v-model
을 연결하면 됩니다.
< script setup >
import { ref } from 'vue'
const message = ref ( '' )
</ script >
< template >
< p >메시지: {{ message }}</ p >
< input v-model = " message " placeholder = "메시지를 입력하세요" />
</ template >
위 코드에서 입력창에 무언가를 타이핑하면, 그 내용이 <p>
태그에 실시간으로 나타나는 것을 볼 수 있습니다. textarea
도 동일하게 사용할 수 있습니다.
체크박스는 두 가지 경우로 나뉩니다.
하나의 체크박스
: true
또는 false
의 불리언(boolean) 값과 연결합니다.
< script setup >
import { ref } from 'vue'
const isChecked = ref ( false )
</ script >
< template >
< input type = "checkbox" id = "checkbox" v-model = " isChecked " />
< label for = "checkbox" >{{ isChecked }}</ label > <!-- isChecked 값(true/false)이 출력됩니다. -->
</ template >
여러 개의 체크박스
: 여러 선택지를 그룹으로 묶을 때는 배열(Array)과 연결합니다.
< script setup >
import { ref } from 'vue'
const checkedNames = ref ([]) // 빈 배열로 시작
</ script >
< template >
< div >선택된 이름: {{ checkedNames }}</ div >
< input type = "checkbox" id = "jack" value = "잭" v-model = " checkedNames " >
< label for = "jack" >잭</ label >
< input type = "checkbox" id = "john" value = "존" v-model = " checkedNames " >
< label for = "john" >존</ label >
</ template >
사용자가 체크박스를 선택하면 해당 value
가 checkedNames
배열에 추가되고, 체크를 해제하면 배열에서 제거됩니다.
라디오 버튼은 여러 개 중 하나만 선택할 때 사용하며, 선택된 항목의 value
를 하나의 변수에 연결합니다.
< script setup >
import { ref } from 'vue'
const picked = ref ( '' )
</ script >
< template >
< div >선택: {{ picked }}</ div >
< input type = "radio" id = "one" value = "첫 번째" v-model = " picked " />
< label for = "one" >첫 번째</ label >
< input type = "radio" id = "two" value = "두 번째" v-model = " picked " />
< label for = "two" >두 번째</ label >
</ template >
드롭다운 메뉴(select)도 라디오 버튼과 비슷하게 선택된 <option>
의 value
를 변수에 연결합니다.
< script setup >
import { ref } from 'vue'
const selected = ref ( '' )
</ script >
< template >
< div >선택됨: {{ selected }}</ div >
< select v-model = " selected " >
< option disabled value = "" >하나를 선택하세요</ option >
< option >가</ option >
< option >나</ option >
< option >다</ option >
</ select >
</ template >
🚀
v-model을 더 편리하게 만드는 수식어 🔗
v-model
에는 특별한 기능을 추가하는
수식어(Modifiers)
를 붙일 수 있습니다.
자주 사용되는 세 가지를 소개합니다.
기본적으로
v-model
은
input
이벤트가 발생할 때마다, 즉 키보드를 누를 때마다 데이터를 업데이트합니다.
.lazy
수식어를 붙이면
change
이벤트가 발생한 후에(주로 입력창에서 포커스가 벗어났을 때) 데이터를 업데이트합니다.
실시간 동기화가 불필요할 때 유용합니다.
< input v-model.lazy = "message" >
사용자의 입력을 자동으로 숫자로 변환해 줍니다.
v-model
은 기본적으로 모든 입력을 문자열로 다루기 때문에, 숫자 값을 다룰 때 이 수식어가 없으면
parseInt()
같은 함수를 직접 써야 합니다.
< input v-model.number = "age" type = "number" >
사용자가 입력한 값의 앞뒤 공백을 자동으로 제거합니다.
아이디나 이메일 입력창에 유용합니다.
< input v-model.trim = "username" >
사용자가 입력을 모두 마친 후 '제출' 버튼을 누르면, 우리는 그 데이터를 어딘가로 보내야 합니다.
이때는
<form>
태그의
submit
이벤트를 이용합니다.
여기서 중요한 점은,
submit
이벤트는 기본적으로 페이지를 새로고침한다는 것입니다.
우리는 페이지 새로고침 없이 데이터를 처리하고 싶기 때문에,
@submit.prevent
처럼
.prevent
수식어를 붙여 기본 동작을 막아주어야 합니다.
< script setup >
import { ref } from 'vue'
const username = ref ( '' )
const password = ref ( '' )
function handleSubmit () {
// .prevent 덕분에 페이지가 새로고침되지 않습니다.
alert ( `제출된 아이디: ${ username . value }, 비밀번호: ${ password . value }` )
// 여기서 axios 등을 이용해 서버로 데이터를 보낼 수 있습니다.
}
</ script >
< template >
< form @ submit . prevent = " handleSubmit " >
< input v-model = " username " placeholder = "아이디" >
< input v-model = " password " type = "password" placeholder = "비밀번호" >
< button type = "submit" >제출</ button >
</ form >
</ template >
이제 handleSubmit
함수 안에서 사용자가 입력한 모든 데이터를 안전하게 다룰 수 있습니다.
오늘은 Vue의 v-model
을 이용해 사용자의 입력을 손쉽게 다루는 방법을 배웠습니다.
v-model
은 데이터와 화면을 연결하는 양방향 데이터 바인딩
을 구현해 줍니다.
텍스트 입력, 체크박스, 라디오 버튼, 셀렉트 등 다양한 폼 요소에 일관된 방식으로 적용할 수 있습니다.
.lazy
, .number
, .trim
과 같은 수식어를 통해 부가적인 기능을 쉽게 추가할 수 있습니다.
@submit.prevent
를 사용하면 페이지 새로고침 없이 폼 제출 이벤트를 안전하게 처리할 수 있습니다.