문제 정의
- 목표: 사용자가 최대 3개의 태그를 입력할 수 있는 UI 구현해야 했습니다.
- 처음엔 인풋 하나만 보이고, 사용자가
Tab
또는Enter
로 다음 인풋을 추가하는 방식입니다.
- 처음엔 인풋 하나만 보이고, 사용자가
- 문제: 한글 입력 중(
IME
조합 상태)Tab
또는Enter
를 누르면,- 새 인풋이 빈 값이 아니라 마지막에 조합되던 한글이 남은 채로 생성되었습니다.
- 의문: 영문 입력에서는 멀쩡한데 왜 한글에서만 이런 문제가 발생하는 것인지 의문이었습니다.
해결 과정
- useFieldArray 오류 의심
처음에는 React Hook Form의useFieldArray
사용 방식이 잘못됐다고 생각해,append
시 ID 중복 문제,setValue
강제 초기화 등 여러 시도를 했으나 실패하였습니다. - 한글 입력 시 IME(입력기) 조합중 이벤트
문제를 검색해보다가 Composition Event(onCompositionStart
,onCompositionEnd
)가 있다는 사실을 알게 되었습니다. 한글은 자모음 조합이 완전히 끝나기 전에(글자가 확정되기 전)onKeyDown
이 먼저 호출되고 Enter/
Tab 입력을 처리해버려서 “조합 중인 문자가 그대로 넘어가” 버리는 것이 문제의 원인이었습니다. - 조합 중임을 판단해 무시하기
onCompositionStart
/onCompositionEnd
에서isComposing
을 true/false로 저장하기로 하였습니다.- 다음은
onKeyDown
에서 isComposing이 true면(조합 중이면) Tab, Enter 처리를 막았습니다. - 이렇게 하면 한글 조합이 완전히 완료된 뒤에만 새 태그 인풋을 생성하게 됩니다.
function ExampleComponent() {
const [isComposing, setIsComposing] = useState(false);
// 한글 IME 조합 시작/종료
// onCompositionStart / onCompositionEnd 이벤트 핸들러
const handleComposition = (e: React.CompositionEvent<HTMLInputElement>) => {
if (e.type === 'compositionstart') {
setIsComposing(true);
} else if (e.type === 'compositionend') {
setIsComposing(false);
}
};
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
// 한글 조합 중이라면 조합 완료 후에만 Enter/Tab 동작 처리
if ((e.nativeEvent as any).isComposing || isComposing) return;
// ... 나머지 로직
};
return (
<input
onKeyDown={handleKeyDown}
onCompositionStart={handleComposition}
onCompositionEnd={handleComposition}
/>
)
}
결과
한글/영문 상관없이, 입력 중에 특정 조건으로 새 인풋을 생성해도 마지막 조합 중인 글자가 새 인풋에 남지 않게 할 수 있었습니다. 이를 통해 이전처럼 임의로 setValue 등을 통해 문자열을 강제로 지우는 편법 로직을 제거할 수 있었습니다.
배운 점 (인사이트)
- IME(입력기) 특성
- 한글, 일본어, 중국어 등 조합형 언어는 키보드 입력 과정에서 자모음(문자)이 “완전히 확정”되기 전까지, 브라우저가 Composition Event를 통해 조합 상태를 관리한다는 점을 알게 되었습니다.
- 와 동시에 onKeyDown 등의 이벤트도 발생할 수 있으므로, 조합 중인 상태는 무시하도록 처리해야 합니다.
- 에러 발생의 범위
- 영문 입력만 테스트하면 문제를 못 찾을 수 있으므로, 다국어(특히 IME 사용 언어) 입력 시에도 제대로 동작하는지 체크하는 습관이 중요하다는 것을 깨닳았습니다.
- React, React Hook Form 문제 X
- 이런 이슈가 발생하면 우선 브라우저 이벤트 흐름을 의심해볼 수 있다는 것을 알게되었습니다.
- 프레임워크나 라이브러리가 아니라 브라우저 입력 방식이 핵심 요인이었습니다.
- CompositionEvent의 활용
- onCompositionStart, onCompositionUpdate, onCompositionEnd를 통해 조합 상태를 세밀하게 제어 가능 하다는 것도 알게 되었습니다.
- 주로 한글, 일본어, 중국어 입력 시 발생하며, 서버 사이드 렌더링(SSR) 환경이나 Edge 케이스에서는 또 다른 주의가 필요할 수 있다고 합니다!
'TIL' 카테고리의 다른 글
[250207 TIL] 제어 역전, 의존성 주입 (1) | 2025.02.07 |
---|---|
[250205 TIL] 냄새나는 코드? (0) | 2025.02.05 |
[250110 TIL] jest, react-testing 기본(1) (0) | 2025.01.14 |
[241220 TIL] 기본적인 husky 세팅 (1) | 2024.12.20 |
[241219 TIL] Severless (0) | 2024.12.19 |