본문 바로가기
프로그래밍

Vue3 템플릿 문법 변화 정리

by 유형제맘 2025. 7. 24.

– v-model, v-bind, 이벤트 바인딩의 변화 중심 –

Vue3는 템플릿 문법에 몇 가지 중요한 변화가 있습니다. 특히 v-model의 작동 방식이 크게 바뀌어, 컴포넌트 간 데이터 바인딩이 더 명확하고 유연해졌습니다.

1. v-model의 변화: prop과 이벤트 이름 변경

Vue2 방식:

<!-- 부모 컴포넌트 -->
<ChildComponent v-model="title" />

<!-- 자식 컴포넌트 -->
props: ['value'],
methods: {
  updateTitle() {
    this.$emit('input', '새로운 값')
  }
}

Vue2에서는 v-model이 자동으로 value prop을 받고, input 이벤트를 발생시켜 부모 값을 갱신했어요. 하지만 이 구조는 컴포넌트마다 여러 v-model을 사용하기 어렵다는 단점이 있었습니다.

Vue3 방식:

<!-- 부모 컴포넌트 -->
<ChildComponent v-model:title="title" />

<!-- 자식 컴포넌트 -->
defineProps(['title'])
defineEmits(['update:title'])

<!-- 혹은 Composition API 스타일: -->
const props = defineProps(['title'])
const emit = defineEmits(['update:title'])

function updateTitle() {
  emit('update:title', '새로운 값')
}

Vue3 변화 요약:

  • v-model:propName으로 다중 바인딩 가능
  • 이벤트 이름이 update:propName으로 명확화
  • 더 명시적이고 직관적인 데이터 흐름 가능

2. v-bind의 변화

기존과 기본 기능은 같지만, 동적 속성 바인딩에서 null, undefined 무시 동작이 좀 더 명확해졌습니다.
예시:

<!-- Vue3에서는 undefined/null은 속성으로 렌더링되지 않음 -->
<img v-bind:alt="undefined" /> <!-- alt 속성이 아예 빠짐 -->

또한, 컴포지션 API의 반응형 객체와 함께 쓸 때도 더 안정적으로 작동합니다:

const props = reactive({
  id: 'user-id',
  disabled: true
})
<button v-bind="props">Click</button>

3. 이벤트 바인딩 (v-on) 변화

@event 바인딩은 Vue2와 유사하지만, Vue3에서는 Composition API의 emit 함수와 함께 사용하는 방식이 강조됩니다.

Vue2 방식:

<Child @custom-event="handleEvent" />

Vue3 방식:

const emit = defineEmits(['custom-event'])

function triggerEvent() {
  emit('custom-event', someData)
}

이벤트 명도 문자열로 명시하고, TypeScript와의 궁합도 좋아졌습니다.

추가 변화: v-model 사용 시 .sync는 사라짐

Vue2에서는 .sync로 양방향 바인딩을 구현할 수 있었죠.

<modal :visible.sync="showModal" />

Vue3에서는 아래와 같이 v-model:visible 형태로 대체됩니다.
<modal v-model:visible="showModal" />

마무리 정리

항목 Vue2 Vue3
v-model value + input 고정 다중 모델 가능, update:propName
v-bind 객체 바인딩은 동일 null/undefined 무시 처리 명확
이벤트 $emit('event') defineEmits() 사용

Vue3는 템플릿 문법이 더 명확하고 구조적으로 바뀌었으며, TypeScript와의 통합성도 좋아졌습니다. 특히 v-model 개선은 컴포넌트의 재사용성과 유지보수성을 크게 높이는 핵심 변화입니다.