지식 정리 📝

<textarea />를 활용한 채팅 입력창에서 한글 Enter 키 입력 시 메시지가 두 번 전송되는 이유

엄성준 2025. 6. 19. 17:44
728x90

🧪  코드 및 현상 재현

처음에는 아래와 같은 로직으로 채팅 입력창을 구현했습니다.
사용자가 <textarea />에 메시지를 입력한 뒤 Enter 키를 누르면, 메시지를 전송하고 입력창을 초기화하는 구조입니다.

const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {
  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault(); // 줄바꿈 방지
    sendMessage(inputValue);
    setInputValue('');
  }
};

재현 GIF

 

한글로 "안녕하세요"를 입력하고 Enter를 누르면,

  • 메시지가 두 번 전송되거나
  • 마지막 글자인 "요"만 따로 전송되는 등 이상한 동작이 나타났습니다.

처음에는 handleSend() 함수가 두 번 호출되는 문제라고 생각했지만, 자세히 들여다보니 문제의 원인은 React 코드 내부가 아닌 브라우저의 한글 입력 처리 방식, IME(Input Method Editor)에 있었습니다.


🤔  왜 이런 현상이 발생할까?

이 문제의 원인은 한글 입력 방식(IME)에 있습니다.

IME(Input Method Editor)란?

한글, 일본어, 중국어 등 조합형 문자를 입력할 때 사용되는 입력기입니다.

 

예: 키보드로 ㅇ, ㅏ, ㄴ을 입력하면 브라우저는 안이라는 글자를 조합해서 보여줍니다.

 

이 과정에서 브라우저는 compositionstart, compositionend, 그리고 Enter와 같은 키 이벤트를 여러 번 발생시킵니다.

 

문제의 핵심

  • 사용자가 한글을 조합한 뒤 Enter를 누르면:
    1. 조합을 확정하는 Enter 이벤트가 먼저 발생하고
    2. 이어서 실제 Enter 입력 이벤트가 한 번 더 발생합니다.

즉, handleKeyDown이 두 번 호출되어 메시지를 두 번 보내게 되는 것입니다.


✅  해결 방법 isComposing 체크하기

React의 KeyboardEvent 객체는 e.nativeEvent.isComposing이라는 속성을 제공합니다.

이 값이 true이면 현재 IME 조합 중이라는 의미이므로, 이때는 Enter를 무시해 주면 됩니다.

🔧  수정된 코드

const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {
  if (e.nativeEvent.isComposing) return; // 한글 조합 중이면 무시

  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault();
    handleSend();
  }
};

문제 해결 GIF

 

이제 한글 입력 중 Enter를 눌러도, 메시지가 한 번만 전송됩니다.