본문으로 건너뛰기
개발 머꼬
개발 노트Vue
hohyeon.dev18

한글을 입력하는 동안 검색 결과가 갱신되지 않은 이유

  • #Common Pitfall
  • #Engineering Note
  • #Vue

문제 발생

실시간 검색을 만들었는데 한글에서만 반응이 늦었습니다.

<input v-model="query" />

검색을 치면 , , 단계에서는 아무 일도 없다가, 스페이스를 누르거나 다음 글자를 시작해 글자가 확정되는 순간 한꺼번에 반영됐습니다. 영문 입력에서는 글자마다 즉시 갱신됐습니다.

원인 분석

IME 조합 중에는 값이 올라가지 않습니다. Vue 문서가 이 동작을 명시적으로 적어둡니다 — IME가 필요한 언어(중국어, 일본어, 한국어 등)에서는 v-model이 IME 조합 중에 갱신되지 않는 것을 볼 수 있습니다. 이런 갱신에도 반응하려면 v-model 대신 직접 input 이벤트 리스너와 value 바인딩을 사용하십시오.

기본값이 이런 데는 이유가 있습니다. 조합 중인 글자는 아직 확정되지 않은 중간 상태라, 그대로 state에 넣으면 , 같은 값이 폼 데이터나 서버 요청에 섞입니다. 그래서 v-model은 조합이 끝난 값만 반영합니다.

문제는 검색어 자동완성처럼 중간 상태가 의미 있는 경우입니다. 여기서는 기본 동작이 오히려 방해가 됩니다.

해결 방안

  1. 조합 중 값이 필요하면 v-model을 풀어 씁니다.
<template>
  <input :value="query" @input="query = $event.target.value" />
</template>
  1. 조합 상태를 직접 구분하고 싶으면 composition 이벤트를 씁니다. 검색은 조합 중에도 하고, 저장은 확정된 값으로 하는 식으로 나눌 수 있습니다.
<script setup>
const composing = ref(false);
</script>

<template>
  <input
    :value="query"
    @compositionstart="composing = true"
    @compositionend="composing = false; query = $event.target.value"
    @input="query = $event.target.value"
  />
</template>
  1. 디바운스를 함께 겁니다. 조합 중 값까지 반영하면 요청 수가 크게 늡니다. 200~300ms 디바운스로 충분한 경우가 많습니다.

  2. 반대 방향의 요구에는 .lazy가 있습니다. 문서 설명대로 v-model은 기본적으로 input 이벤트마다 동기화하는데, .lazy를 붙이면 change 이벤트 이후에 동기화합니다 — 매 글자 검증이 거슬리는 폼에 맞습니다.

  3. .trim.number도 여기서 함께 정리합니다. .number는 문서 설명대로 parseFloat()로 파싱되지 않으면 원래 문자열을 그대로 두고, 입력이 비면 빈 문자열을 돌려줍니다. type="number"인 입력에는 자동으로 적용됩니다.

  4. 한글로 실제 테스트합니다. 영문만으로 확인하면 이 문제는 절대 드러나지 않습니다 — MEOKKO처럼 한국어가 기본인 서비스에서는 검색·태그·댓글 입력에서 반드시 확인합니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.