Engineering note · Vue

Vue 3 emit 실행 순서와 props 갱신 타이밍

2026년 08월 05일이현수
태그vue3reactivityemitnext-tick

자식 컴포넌트에서 emit 직후 props를 조회했을 때 이전 값이 유지되는 이유와 Vue의 update queue 비동기 렌더링 동작 원리를 정리한다.

자식 컴포넌트에서 update:modelValue 를 실행한 직후 props.modelValue를 출력하면 여전히 이전 값이 찍히는 현상이 있다. 부모의 이벤트 리스너는 분명 실행되었는데 자식이 받은 props는 바로 바뀌지 않는다.

ts
// 자식 컴포넌트
function handleIncrease() {
  const nextValue = props.modelValue + 1

  console.log('before emit:', props.modelValue) // 0
  emit('update:modelValue', nextValue)
  console.log('after emit:', props.modelValue)  // 여전히 0
}

emit() 호출하면 부모의 리스너 함수는 현재 실행 컨텍스트에서 즉시 동기적으로 실행된다. 부모 내부의 반응형 상태값도 그 시점에 바로 바뀐다.

하지만 부모 상태 변경으로 인한 컴포넌트 리렌더링과 자식 컴포넌트로의 새로운 props 전달은 Vue의 비동기 업데이트 큐에 담겨서 실행을 기다린다.

emit 호출과 Vue 업데이트 큐 처리 순서

자식 이벤트 호출과 부모 상태 변경, 그리고 비동기 렌더링 큐 플러시의 동작 흐름이다.

자식의 자바스크립트 함수 handleIncrease 가 완전히 끝나기 전까지는 렌더링 배치 작업이 실행되지 않는다. 도중에 props.modelValue 를 다시 읽어도 아직 새 props를 받지 못해 이전 값 그대로 남아 있는 것이다.

올바른 상태 접근과 nextTick 활용

함수 안에서 다음 변경 값이 필요할 때는 이미 계산해 둔 로컬 변수를 직접 사용하는 편이 직관적이고 안전하다.

ts
import { nextTick } from 'vue'

async function handleIncrease() {
  const nextValue = props.modelValue + 1

  emit('update:modelValue', nextValue)

  // 1. 현재 함수 로직에서는 이미 계산한 nextValue를 바로 사용한다.
  doSomething(nextValue)

  // 2. 갱신된 DOM이나 자식에게 다시 전달된 props가 꼭 필요할 때만 nextTick을 기다린다.
  await nextTick()
  console.log('after nextTick:', props.modelValue) // 갱신된 값 (1)
}

갱신된 DOM 엘리먼트를 참조해야 하거나, 부모의 변경 사항이 완전히 반영된 props를 자식 함수 안에서 다시 사용해야할 할 때 nextTick 을 사용해 업데이트 플러시를 기다린다.

좋아요와 댓글

댓글 남기기

댓글 0개

댓글을 불러오는 중입니다.