Input의 빈번한 사용과 문제 발생
프로젝트에서 텍스트를 작성하고 post하는 과정은 매우 빈번하다 검색창, 채팅, 블로그 글, 회원가입, 로그인 등
하지만, 가끔 위 사진과 같이 애를 먹는 경우가 있는데 다름 아닌 enter 이벤트를 통해 입력 값을 처리할 때 종종 등장하곤 한다
위와 같은 상황이 발생하는 경우는 다음과 같다
1. 영어가 아닌 한글을 작성 후 Enter를 클릭하는 경우
2. 한글 작성 후 스페이스바를 누르지 않고 바로 Enter를 클릭하는 경우
const handleKeyDown2 = async (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key !== "Enter") return;
setLogs2((prev) => [...prev, message2]);
setMessage2("");
};
<input
className="inputtest"
value={message2}
onChange={(e) => setMessage2(e.target.value)}
onKeyDown={handleKeyDown2}
placeholder="Enter 입력 테스트"
/>
기본적으로 이런 input 구성과 엔터키 클릭에 대한 핸들링 함수는 위와 같이 작성할 것이다
event가 Enter인 경우에 전송 버튼을 클릭하면 발생하는 전송관련 로직이 해당된다
왜 이런 문제가 발생할까
위의 예시 경우를 보여줄 때 숫자나 영어의 경우 언급하지 않았는데 실제로 영어 및 숫자의 경우 두 번 전송되지 않는다
한글 작성에만 이런일이 발생하는 이유는 IME(Input Method Editor)입력처리와 관련되어있다
영어의 경우 apple과 같이 글자 한 개 한 개가 조합없이 각자 글자로 인식되는 반면 한글의 경우 사과와 같이 조합글자로 인식된다
이때, 내가 사과를 작성하고 바로 엔터를 치는 경우 조합 중인 문자는 onKeyDown이벤트에서 아직 확정되지 않은 상태로, Enter를 입력하는 경우 다시 onKeyDown이벤트가 실행되며, 한번 더 발생하는 것이다
그래서 위 사진과 같이 안녕하세요를 보내는 경우
조합완료된 전체 문자열 안녕하세요 1번
최종 입력 문자열 요가 1번 총 두번 발생하는 것이다
해결
해결방법엔 두 가지가 있다
1. compositionend 이벤트 활용
조합이 끝나는 시점을 감지하는 onCompositionEnd를 사용해서 해결한다
const [isComposing, setIsComposing] = useState(false);
const handleKeyDown = async (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key !== "Enter" || isComposing || !message.trim()) return;
setLogs((prev) => [...prev, message]);
setMessage("");
};
<input
type="text"
className="inputtest"
value={message}
onChange={(e) => setMessage(e.target.value)}
onKeyDown={handleKeyDown}
onCompositionStart={() => setIsComposing(true)}
onCompositionEnd={() => setIsComposing(false)}
placeholder="Enter 입력 테스트"
/>
input에서 감지한 onComposition에 따라 isComposing 상태를 다르게 해 Enter클릭 시 isComposing이 종료된 시점에만 핸들링 함수가 발생하도록 하는 것이다
2. onKeyPress 이벤트 활용 (React 17부터 폐기된 속성)
<input
type="text"
className="inputtest"
value={message}
onChange={(e) => setMessage(e.target.value)}
onKeyPress={handleKeyDown}
placeholder="Enter 입력 테스트"
/>
물론 onKeyPress는 더 이상 최신 브라우저에서 표준이 아니지만 전 프로젝트에 사용했던 것이 기억이 나 적어본다
이 방법의 경우 onKeyUp, onKeyDown과는 다르게 중복 이벤트를 발생시키지 않기에 위의 isComposing상태없이 한글의 정상적인 이벤트 핸들링이 가능하다
setTImeout을 통해 확실히 조합이 된 값만을 전송하는 로직에 포함되도록 비동기처리하는 방법도 있지만 제일 좋은건 isComposing을 활용하는 방식같다
'코딩' 카테고리의 다른 글
Tailwind V4.1 달라진 점 (0) | 2025.04.10 |
---|---|
Tailwind V 4.0 config.js 어디로? (1) | 2025.04.08 |
불변객체와 순수 컴포넌트 (0) | 2025.03.29 |