<input type="text">에서 keyCode를 이용해 이벤트를 짤 때 keyCode가 229가 나오는 버그를 발견했습니다. 특히 안드로이드 모바일에서는 숫자 키에도 229가 나왔습니다. 그래서 이 문제를 해결하면서 공부한 내용을 정리했습니다.
***
결론부터 말씀드리자면, input에서 한글자판 사용시 IME에서 메시지를 가로채기 때문에 keyCode가 229를 가리키는 것이었습니다.
"그래서 'keydown', 'keyup' 이벤트 대신 'input' 이벤트를 사용하는 것을 추천드립니다."
(Software Engineer, Mozilla)
***
한글이나, 일본어, 중국어 등 컴퓨터 자판의 개수보다 더 많은 글자를 쓰는 문자를 입력할 때 입력 방식 편집기(IME)를 씁니다. 안드로이드 모바일 역시 한글을 입력할 때 IME를 사용하고 있었습니다.
(주의: IME를 깊게 공부하진 않아서 정확한 정보는 아닙니다.)
IME는 한글을 입력 시 컴포징이라는 단계를 거칩니다. 예를 들어, "ㄱ"을 입력하면 아직 글자가 완성되지 않았다고 판단하고 글자가 완성될 때까지 조합을 하는데 이것을 컴포지션이라고 부릅니다.
참고 : https://developer.mozilla.org/en-US/docs/Mozilla/IME_handling_guide
그런데 문제는 컴포징이 진행 중일 때에도 keydown 및 keyup 이벤트를 보낸다는 것입니다.
컴포징이 시작되었을 때 미완성이라는 메시지로 keyCode로 229를 보내는 것입니다.
다음은 textarea에서 한글"ㅁ"을 입력했을 때 keydown과 keyup의 event를 console.log에 찍은 내용입니다.
(input type="text"에서도 같은 결과가 나옵니다.)
위의 두 이미지를 살펴보시면 keyCode: 229가 나온것을 확인 할 수 있습니다.
그리고 key: "Process"를 통해 IME의 프로세스로 들어간다는 것을 확인 할 수 있습니다.
그리고 특이하게도 keydown 이벤트에는 isComposing: false인데 반해 keyup 이벤트에는 isComposing: true라는 것을 확인 할 수 있습니다.
이것은 keydown에서는 아직 컴포징이 시작되지 않았기 때문입니다. 이때 "ㅏ"를 연달아서 치면 "마"가 되면서 keydown 이벤트 역시 isComposing: true가 되는 것을 확인할 수 있습니다. (아래 이미지)
그래서 만약 한글 입력인지 알고 싶다면, 아래와 같은 로직을 통해 이벤트 로직을 짤 수 있을 것입니다.
input.addEventListener("keyup", (event) => {
if(event.isComposing) {
// 한글 입력 중
// return을 입력하면 한글 입력 이벤트만 받을 수 있음
}
// Do something
}
하지만 keydown이나 keyup으로 input의 각 character에 즉각적으로 작동하는 이벤트는 사용하지 않는 것을 권고하고 있습니다. 왜냐하면 keydown과 keyup 이벤트에서 컴포지팅 메시지를 보내는 것이 고쳐지지 않을 수 도 있기 때문입니다.
대신, 'input' 이벤트를 사용하는 것을 추천하고 있습니다. (Software Engineer, Mozilla)
'input' 이벤트는 element의 value가 변할 때(change)마다 발화하는 이벤트입니다.
출처2: https://groups.google.com/forum/#!topic/mozilla.dev.platform/oZEz5JH9ZK8/discussion
'WEB > JS' 카테고리의 다른 글
(js)만 나이 계산 (0) | 2021.11.05 |
---|---|
(js) class 상속 연습 (0) | 2021.08.22 |
(js) prototype 상속 연습 (0) | 2021.08.22 |
(js)조건절에 boolean 대신 쓸 수 있는 값 (0) | 2020.10.10 |
[javascript] pc와 모바일을 구분하고 싶을 때 (0) | 2020.02.12 |