한글 입력 중 Enter가 두 번 실행될 때, IME composition 이벤트 처리법
한글 입력창에서 Enter가 두 번 발동하는 IME composition 이슈의 원인과 isComposing 가드 한 줄로 해결하는 방법을 정리했어요.
한글 입력 중 Enter가 두 번 실행될 때, IME composition 이벤트 처리법
메시지 입력창에서 한글 문장을 쓰고 Enter를 눌렀는데, 같은 내용이 두 번 전송된 적 없나요? 영어로 입력할 때는 멀쩡한데 한글에서만 생기는 문제라면, 원인은 거의 IME composition 이벤트예요.
저도 플랜티(plan-t)라는 마음 기록 앱을 만들면서 입력창을 붙였는데, 돌려 보니 마지막 글자가 조합 중인 상태에서 Enter를 치면 같은 기록이 2건씩 저장됐어요. 코드에는 submit을 한 번만 부르게 해놨는데도요.
왜 두 번 실행될까요
한글은 자음과 모음을 조합해서 한 글자를 완성하는 IME 입력 방식이에요. 브라우저는 조합이 끝나지 않은 상태의 Enter를 "조합 확정"과 "실제 키 입력"으로 나눠서 처리해요. 그래서 keydown 핸들러가 한 번의 Enter에 두 번 호출돼요.
콘솔에 이벤트를 찍어 보니 첫 번째 keydown은 isComposing이 true였고, 레거시 속성인 keyCode는 229로 찍혔어요. 229는 "IME가 처리 중인 키"라는 뜻이라, 이 값이 보이면 조합 중이라고 판단하면 돼요.
가드 한 줄로 해결
수정은 가드 1줄이면 끝나요. React에서는 합성 이벤트가 아니라 nativeEvent 쪽에서 isComposing을 확인하는 게 안전해요.
function handleKeyDown(e: React.KeyboardEvent<HTMLTextAreaElement>) {
if (e.nativeEvent.isComposing) return; // 조합 중인 keydown은 무시
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
submit();
}
}적용해 봤더니 조합 확정용 keydown이 걸러지면서 중복 저장이 사라졌어요. 순수 자바스크립트라면 event.isComposing을 바로 확인하면 되고, 오래된 환경까지 챙겨야 하면 keyCode === 229 체크를 함께 두는 방법도 있어요.
브라우저별로 꼭 확인하세요
한 가지 주의할 점이 있어요. 조합 관련 이벤트가 발생하는 순서는 브라우저마다 조금씩 달라요. 테스트해 보면 같은 코드인데도 크롬과 사파리에서 이벤트 로그가 다르게 찍히는 걸 볼 수 있어요. 그래서 입력창처럼 사용자가 매일 만지는 화면은 최소 2개 브라우저에서 직접 눌러 보는 게 좋아요. 저는 확인까지 10분 정도 걸렸는데, 그 10분이 중복 데이터 지우는 시간보다 훨씬 짧았어요.
- isComposing 가드
- nativeEvent 확인
- keyCode 229
- 브라우저 2종 테스트
한글 서비스를 만든다면 언젠가 한 번은 만나는 문제예요. 입력창을 새로 만들 때 가드 한 줄을 습관처럼 넣어 두면, 나중에 원인 모를 중복 버그를 쫓는 일이 줄어들어요.
관련 글
댓글
아직 댓글이 없어요. 첫 댓글을 남겨주세요.