한글을 입력하는 동안 검색 결과가 갱신되지 않은 이유
문제 발생
실시간 검색을 만들었는데 한글에서만 반응이 늦었습니다.
<input v-model="query" />검색을 치면 ㄱ, 거, 검 단계에서는 아무 일도 없다가, 스페이스를 누르거나 다음 글자를 시작해 글자가 확정되는 순간 한꺼번에 반영됐습니다. 영문 입력에서는 글자마다 즉시 갱신됐습니다.
원인 분석
IME 조합 중에는 값이 올라가지 않습니다. Vue 문서가 이 동작을 명시적으로 적어둡니다 — IME가 필요한 언어(중국어, 일본어, 한국어 등)에서는 v-model이 IME 조합 중에 갱신되지 않는 것을 볼 수 있습니다. 이런 갱신에도 반응하려면 v-model 대신 직접 input 이벤트 리스너와 value 바인딩을 사용하십시오.
기본값이 이런 데는 이유가 있습니다. 조합 중인 글자는 아직 확정되지 않은 중간 상태라, 그대로 state에 넣으면 ㄱ, 거 같은 값이 폼 데이터나 서버 요청에 섞입니다. 그래서 v-model은 조합이 끝난 값만 반영합니다.
문제는 검색어 자동완성처럼 중간 상태가 의미 있는 경우입니다. 여기서는 기본 동작이 오히려 방해가 됩니다.
해결 방안
- 조합 중 값이 필요하면
v-model을 풀어 씁니다.
<template>
<input :value="query" @input="query = $event.target.value" />
</template>- 조합 상태를 직접 구분하고 싶으면 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>-
디바운스를 함께 겁니다. 조합 중 값까지 반영하면 요청 수가 크게 늡니다. 200~300ms 디바운스로 충분한 경우가 많습니다.
-
반대 방향의 요구에는
.lazy가 있습니다. 문서 설명대로v-model은 기본적으로input이벤트마다 동기화하는데,.lazy를 붙이면change이벤트 이후에 동기화합니다 — 매 글자 검증이 거슬리는 폼에 맞습니다. -
.trim과.number도 여기서 함께 정리합니다..number는 문서 설명대로parseFloat()로 파싱되지 않으면 원래 문자열을 그대로 두고, 입력이 비면 빈 문자열을 돌려줍니다.type="number"인 입력에는 자동으로 적용됩니다. -
한글로 실제 테스트합니다. 영문만으로 확인하면 이 문제는 절대 드러나지 않습니다 — MEOKKO처럼 한국어가 기본인 서비스에서는 검색·태그·댓글 입력에서 반드시 확인합니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.