[FE] 한글 입력 시 이벤트 중복 발생 (feat. keyup)

.DS_Store·2024년 2월 22일
0

FrontEnd

목록 보기
23/26

한글 입력시 api 호출이 두 번 되길래
엥 이거 왜이래!
하고 서치해보다 알게 된 것들을 정리해보려 한다.
(대부분 keydown에 관한 해결책이었어서 keyup을 쓰고 싶은 누군가에게 도움이 되었으면...)

가보자고~

문제점

이벤트의 중복 발생


일단 이미지에서 보이는 것 처럼
Input에 한글을 입력하고 엔터를 하면
onEnter에 걸려있는 api 호출 이벤트가 두 번 발생하는 문제가 있었다.

※ 참고

  • 위의 input은 Input이라는 공통 컴포넌트를 사용 중
  • 따라서, button이나 submit 사용 X (바로 onEnter 사용 불가)
  • onEnter 사용 방법:
    공통 컴포넌트인 InputonEnter로 이벤트를 넘겨주면,
    onKeyup에서 e === "Enter"일 때 실행'
const keyupCallback = useCallback(
  (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === "Enter" && is_composed) {
      onEnter && onEnter(e.key)
    }
    onKey && onKey(e)
  },
  [onEnter, onKey],
)
    
    // 중략
    
<input
    // ...props
    onKeyup={keyupCallback}
/>  

영어랑 숫자는 되는데, 한글만?

이건 IME라는 녀석 때문에 발생하는 문제다.

영어나 숫자와는 달리, 한국어는
ㅇ + ㅏ + ㄱ 이 '악'가 되어 한 글자가 되는 과정이 필요한데
브라우저도, IME도 두개 다 이걸 처리하느라 이벤트가 두 번 호출 되는 것이라고 한다.

해결방법

debounce로 해결하기

의도적으로 일정 시간 내에 발생하는 이벤트를 무시하는 방법이다.

  const debounceSearchEvent = useDebounce((name: string) => {
    search(name)
  }, 100)

기존 만들어두었던 useDebounce 훅을 활용해 구현했던 코드인데,
각 인터넷 속도나 사용 상황차이가 있을 수 있어
결국 두 번 호출 되는 문제를 근본적으로 막지는 못하는 코드라 생각된다.

isComposing으로 해결..?

관련 내용을 서치하다보면 가장 많이 뜨는 내용이다.
if e.nativeEvent.isComosing === true return;
changeEvent 등에서는 위 한 줄로 대부분을 막을 수 있겠지만..

이상하게 내 케이스에는 적용이 안됐다.

Composition 이벤트 순서를 이해하기!

그래서 고전하고 있던 차에 사수분이 찾아준 자료.


(이미지 출처: https://w3c.github.io/uievents/#events-composition-key-events)

보면 keydown -> composition -> keyup 의 순서를 거치고 있다.

그리고 한글 입력 후 엔터를 눌렀을 때는?
keydown -> composition -> keyup
keydown -> keyup
의 두가지 이벤트가 순서대로 일어났다.
그러니 isComposing으로 아무리 막아봐라... keyup에 걸린 이벤트는 싹 무시하고 일어나지...

따라서 composition 단계를 거치는 enter이벤트는 무시하게끔
is_composed라는 값을 추가했다 (true면 composition 단계를 거친 거니 무시!)

let is_composed
onKeydown => is_composed = true
onCompositionEnd => is_composed = false

그리고 이렇게 composition 단계를 잘 신경써주면...!

(급하게 쓰느라 글의 퀄리티는 안 성공)

0개의 댓글