Input 태그 내 한글 텍스트 입력 후, 엔터 시 마지막 글자가 중복되어 두 번 입력되는 이슈

JH.P·2024년 6월 27일

에러 상황

  • 진행 중인 프로젝트에서 input 태그에 텍스트를 입력 후, 엔터키를 누를 시 목록에 입력한 텍스트가 추가되는 기능을 개발 중이였다.
  • 영어 텍스트를 입력 시에는 문제가 없었지만, 한글 텍스트를 입력하는 경우에 해당 문제가 발생되어 원인을 검색해보았다.
  /** 입력 중 엔터키 누를 시 할일이 추가되는 함수 */
  const handlePressEnter = (event: React.KeyboardEvent) => {
    if (event.key === "Enter") {
      if (toDoList.map((todo) => todo.name).includes(typedTodo)) {
        alert("중복된 할일이 존재합니다.");
        return;
      }
      handleAddTodo(id, { name: typedTodo });
      setTypedTodo("");
    }
  };

원인

  • 원인은 IME에 있었다.

IME(Input Methond Editor)

  • 일반 키보드에서 쉽게 입력될 수 없는 언어로 텍스트를 입력할 수 있는 OS 레벨의 입력 에디터
  • 한글을 입력 시, 한글의 어휘는 자음+모음 및 받침으로 구성이 되기 때문에, IME가 해당 구성요소들을 하나의 글자로 합성(Composition)하는 것을 도와준다.

ex)

  • "리엑트"라는 글자가 있다고 가정하자.
  • "리엑트"라는 글자를 입력하고 엔터를 눌렀을 때, "리엑"은 입력 및 합성(Composition)이 완료되었지만, "트"는 합성이 완료되지 않았을(Composing) 수 있다. 이때 "리엑트" 와 "트" 총 두 번의 이벤트 핸들러가 동작하게 되는 흐름이다.

버튼 클릭 vs 엔터키

  • 버튼 클릭 시에는 IME가 입력한 글자를 이미 완성된 상태로 간주(마우스 클릭 이벤트는 IME와 관련없이 동작)한다. 즉 모든 글자의 합성이 완료되어 중복 입력 이슈가 발생되지 않는다.
  • 엔터키를 누를 경우 텍스트를 입력 한 후 엔터를 누를 시, IME가 아직 합성 중인 글자가 있다고 판단하게 된다. 따라서 합성이 완료된 글자에 대한 이벤트("리엑트")와 합성 중인 글자에 대한 이벤트("트"), 이렇게 두 번의 중복 이벤트가 발생하게 된다.

해결

  • 아래와 같이 Composing(합성중)일 때는 이벤트 핸들러가 동작하지 않도록 하여 해결하였다.
  /** 입력 중 엔터키 누를 시 할일이 추가되는 함수 */
  const handlePressEnter = (event: React.KeyboardEvent) => {
    if (event.nativeEvent.isComposing) {
      return;
    }

    if (event.key === "Enter") {
      if (toDoList.map((todo) => todo.name).includes(typedTodo)) {
        alert("중복된 할일이 존재합니다.");
        return;
      }
      handleAddTodo(id, { name: typedTodo });
      setTypedTodo("");
    }
  };
profile
꾸준한 기록

0개의 댓글