본문 바로가기

FrontEnd/React

[리액트] 한글 입력 시 KeyDown 이벤트가 두 번 호출되는 문제 해결 방법

서론

한글 입력 시 발생하는 keydown 이벤트가 두 번 호출되는 문제를 해결하는 방법을 공유하려 합니다.

이 문제는 한글의 자음과 모음을 합성하는 과정에서 발생하며, 이를 해결하기 위해 useKeyComposing이라는 커스텀 훅을 만들어 사용했습니다. 또한, 네이티브 이벤트와 리액트 합성 이벤트를 혼용하지 말라는 권장 사항도 설명하겠습니다.

 

문제 설명: 한글 입력 시 keydown 이벤트의 중복 호출

한글 입력의 특성상 자음과 모음이 합성되어 하나의 완성된 글자가 만들어집니다. 그런데 이 과정에서 keydown 이벤트가 두 번 호출되는 문제가 발생할 수 있습니다. 예를 들어, 키보드에서 방향키를 누르면 handleKeyDown 함수가 호출되고, 뒤이어 onCompositionEnd 이벤트가 발생하면서 다시 keydown 이벤트가 호출되는 현상이 발생합니다. 이 문제는 한글 입력 필드에서 자주 나타나며, 결국 원치 않는 동작이나 버그를 유발할 수 있습니다.

 

문제 원인: 한글 입력의 합성 과정

한글 입력은 영어와 달리 자음과 모음이 따로 입력되고, 이들이 합쳐져 완성된 글자를 구성합니다. 따라서 자음과 모음이 입력되는 중간 상태에서는 입력이 완료되었는지 확정할 수 없습니다. 이 과정에서 브라우저는 각 자음과 모음 입력에 대해 keydown 이벤트를 처리하고, 마지막에 글자가 완성되면 다시 onCompositionEnd 이벤트를 트리거합니다. 이러한 이유로 한글 입력 중에는 keydown 이벤트가 두 번 호출되면서 의도치 않은 결과를 발생시키는 것이죠.

 

해결 방법: useKeyComposing 커스텀 훅 구현

이 문제를 해결하기 위해선 한글 입력 중에는 keydown 이벤트가 발생하지 않도록 조정할 필요가 있습니다. 이를 위해, 한글 입력 중인지를 감지할 수 있는 커스텀 훅 useKeyComposing을 구현하여 사용합니다. 이 훅은 onCompositionStart와 onCompositionEnd 이벤트를 통해 한글의 조합 상태를 감지하고, 상태 값을 관리합니다.

 

import { useState } from 'react'

const useKeyComposing = () => {
  const [isComposing, setIsComposing] = useState(false)

  const keyComposingEvents = {
    onCompositionStart: () => setIsComposing(true),
    onCompositionEnd: () => setIsComposing(false),
  }

  return { isComposing, keyComposingEvents }
}

export default useKeyComposing

 

useKeyComposing 훅은 매우 간단하지만, 효과적으로 한글 입력 시 발생하는 문제를 해결할 수 있습니다. isComposing 상태를 통해 현재 한글 입력 중인지를 감지하고, 이를 기반으로 keydown 이벤트가 발생할지 여부를 결정할 수 있습니다.

 

훅 사용 예시:

이 훅을 사용하는 방식은 매우 직관적입니다. 아래와 같이 useKeyComposing 훅을 사용해 keydown 이벤트가 중복 호출되지 않도록 설정할 수 있습니다.

 

<SearchInput
  isFocus={isFocused}
  onKeyDown={handleKeyDown}
  autoFocus={autoFocus}
  handleFocus={handleFocus}
  {...keyComposingEvents}
/>

 

이처럼, 한글 입력 상태를 감지하여 한글 조합 중일 때는 keydown 이벤트를 차단하고, 입력이 완료되면 다시 이벤트를 처리하는 방식으로 문제를 해결할 수 있습니다.

 

이벤트 디버깅은 아래와 같습니다.

 

네이티브 이벤트와 리액트 합성 이벤트 혼용 문제

처음 이 문제를 해결하려 할 때, e.nativeEvent.isComposing 속성을 사용하여 처리해보려 했을 수 있습니다. 그러나 이는 네이티브 이벤트와 리액트 합성 이벤트의 혼용 문제로 이어질 수 있기 때문에 권장되지 않습니다.

리액트는 자체적으로 이벤트를 합성하여 일관된 API를 제공하고 있습니다. 리액트의 합성 이벤트는 브라우저의 네이티브 이벤트보다 일관성이 높고, 이벤트 풀링(Event Pooling) 등의 최적화 처리가 포함되어 있습니다. 반면, 네이티브 이벤트는 브라우저마다 동작 방식이 다를 수 있어 이를 혼용할 경우 예기치 못한 버그가 발생할 수 있습니다.

따라서 네이티브 이벤트와 리액트 합성 이벤트를 혼용하기보다는, 리액트가 제공하는 이벤트 시스템을 사용하는 것이 더욱 안전하며, 이번 해결책에서도 리액트 합성 이벤트만을 사용한 방식으로 구현한 것이죠.

 

결론

한글 입력 시 keydown 이벤트가 두 번 호출되는 문제는 자음과 모음의 합성 과정을 제대로 처리하지 않았을 때 발생하는 일반적인 문제입니다. 이를 해결하기 위해 useKeyComposing이라는 커스텀 훅을 사용하여 한글 입력 중에는 keydown 이벤트를 차단할 수 있습니다. 또한, 네이티브 이벤트와 리액트 합성 이벤트를 혼용하지 말라는 권고에 따라 더욱 안전한 방식으로 코드를 작성하는 것이 좋습니다.

이 글이 한글 입력 시 발생하는 keydown 이벤트 문제를 해결하는 데 도움이 되었기를 바랍니다. 더 궁금한 점이나 추가적인 피드백이 있으시면 언제든지 댓글로 남겨 주세요.

 

추가 예제 및 참고 자료