[JavaScript] 한글 키보드 입력 시 이벤트가 두 번 호출되는 경우
문제상황
Ant Design의 Input에 onPressEnter를 사용하는 중 위와 같은 문제가 발생했다.
텍스트를 입력하고 엔터를 누르면 Select의 옵션 값으로 추가가 되도록 구현했는데, 함수가 두 번씩 호출되어 텍스트의 마지막 글자가 옵션값에 추가가 되어버렸다.
해결 방법
onKeyDown/onKeyUP 그리고 onKeyPress
onKeyDown, onKeyUp
- 키를 누르고 떼는 동작 자체에 반응
- 문자, 숫자, Ctrl, Shift, Alt, F1~F12, Scroll Lock, Pause, Enter를 인식하고 한/영, Print Screen은 인식하지 못함
onKeyPress
- 위와 달리 문자가 실제로 입력됐을 때 반응
- 따라서 문자, 숫자, Ctrl, Shift, Alt, F1~F12, Scroll Lock, Pause, Enter, 한/영, Print Screen과 같은 키들을 인식하지 못함
만약 onKeyPress를 사용해도 상관없는 로직이라면 단순히 onKeyDown/onKeyUp 함수를 onKeyPress 함수로 변경하면 문제를 해결할 수 있다.
하지만, Ant Design의 onPressEnter는 엔터값을 입력받는지 체크하는 함수임으로, 합성이벤트(SyntheticEvent)로 onKeyDown을 사용하고 있다.
KeyboardEvent.isComposing
onKeyDown을 사용하면서, 한글 입력문제를 해결하는 방법은 없을까?
한글을 입력할 때 자세히 보면 입력 중인 글자 바로 아래에 검은 밑줄이 생기는데, 이 밑줄이 보이는 상황에서 Enter 키를 입력하면 이벤트가 두번 호출되는 문제가 발생하게 된다. 왜냐하면 글자의 조합 중인지, 끝난 상태인지 파악하기 어렵기 때문이다.
한글은 자음과 모음의 조합으로 한 음절이 만들어지기 때문에 조합문자이며, 영어는 한 음절이 하나의 알파벳으로 이루어지므로 조합문자가 아니다.
해당 이슈가 영어를 입력할 때는 발생하지 않고, 한글을 입력할 때만 발생하는 이유이다.
KeyboardEvent.isComposing은 입력된 문자가 조합 문자인지 아닌지를 반환하는 함수로, 이벤트 내부에e.nativeEvent.isComposing을 호출해보면 첫 번째로 호출되는 이벤트는 ture를 반환하고 두 번째 이벤트에서는 false를 반환하는 것을 확인 할 수 있다.
즉, 글자가 조합되는 과정에 발생하는 이벤트는 무시되고, 이벤트가 끝난 뒤 발생하는 이벤트에 대해서만 처리를 하도록 구현할 수 있다.
Reference