frontend
한글 입력에서 Enter가 두 번 눌리는 버그
채팅 기능을 만들었더니 이상한 제보가 왔다. "마지막 글자가 한 번 더 전송돼요."
재현해보니 한글로 입력하고 Enter를 치면 메시지가 두 번 나갔다. 영어로 치면 멀쩡하다.
원인: IME 조합(composition)
한글은 자모를 조합해서 글자를 만든다. 이 조합 중에는 입력이 IME(입력기)가 관리하는 상태에 있는데, 조합이 끝나기 전에 Enter를 치면:
- IME가 조합을 확정하면서 keydown이 한 번
- 실제 Enter 입력으로 keydown이 또 한 번
핸들러가 두 번 불리고, 전송도 두 번 된다. Safari·Chrome 모두에서 재현되는 유서 깊은 문제다.
해결: isComposing
이벤트에 조합 중 여부가 들어있다. 이것만 거르면 끝.
const onEnter = (fn: () => void) => (e: KeyboardEvent) => {
if (e.key === "Enter" && !e.isComposing && e.keyCode !== 229) fn();
};
input.addEventListener("keydown", onEnter(sendMessage));
keyCode === 229는 구형 브라우저에서 IME 처리 중임을 뜻하는 매직 넘버다. isComposing만으로 대부분 되지만 안전벨트로 같이 채운다.
React라면
<input
onKeyDown={(e) => {
if (e.key === "Enter" && !e.nativeEvent.isComposing) send();
}}
/>
React 합성 이벤트에서는 e.nativeEvent.isComposing을 봐야 한다.
한국어 서비스 만들면 반드시 한 번은 밟는 지뢰. 입력 + Enter 조합이 있는 곳이면 지금 바로 확인해보자 — 채팅, 댓글, 검색창, 태그 입력까지 전부 해당된다.
조회 0