Skip to content

beforeinput/input의 inputType

inputType의 종류, 환경별 차이, 차이가 발생하는 구조적 이유

inputType브라우저가 편집 동작을 해석해 붙이는 이름이다. OS IME가 보낸 실제 동작이 아니라 브라우저가 판단한 결과이므로, 같은 동작도 환경에 따라 다른 inputType이 올 수 있다.


inputType의미발생 조건
insertText일반 텍스트 삽입영문 입력, composition 없이 오는 입력
insertCompositionText조합 중 텍스트 삽입IME 조합 중 (iOS Safari 제외)
insertReplacementText텍스트 교체자동 수정, 추천 후보 선택
insertFromPaste붙여넣기Ctrl+V, 컨텍스트 메뉴 붙여넣기
insertFromDrop드롭드래그 앤 드롭으로 텍스트 삽입
insertLineBreak줄바꿈 삽입Shift+Enter
insertParagraph문단 삽입Enter
inputType의미발생 조건
deleteContentBackward커서 앞 1자 삭제Backspace
deleteContentForward커서 뒤 1자 삭제Delete
deleteWordBackward커서 앞 단어 삭제Ctrl+Backspace (Windows), Option+Delete (macOS)
deleteWordForward커서 뒤 단어 삭제Ctrl+Delete (Windows), Option+Fn+Delete (macOS)
deleteByCut잘라내기Ctrl+X
deleteByDrag드래그로 삭제드래그 앤 드롭 원본 삭제
inputType의미
historyUndoUndo
historyRedoRedo
formatBold굵게
formatItalic기울임

상황다른 환경iOS Safari
한글 조합 중insertCompositionTextinsertText 또는 composition 이벤트 없이 insertText
딕테이션insertCompositionTextinsertText (composition 이벤트 없음)
단어 삭제deleteWordBackwarddeleteWordBackward 또는 deleteBackwardWord

핵심: iOS Safari는 insertCompositionText를 사용하지 않는다.

브라우저동작
Chrome (Windows)compositionstartcompositionupdatecompositionend
Chrome (macOS)insertText 한 번 (composition 없음)
SafariinsertText 한 번 (composition 없음)
Firefox브라우저 버전에 따라 다름

핵심: 데드 키가 composition을 발생시키는지는 OS/브라우저 조합에 따라 다르다.

기능inputType
자동 수정 (autocorrect)insertReplacementText 또는 insertText
추천 후보 탭insertReplacementText 또는 insertText
단어 삭제 제스처deleteWordBackward, deleteBackwardWord, 또는 여러 번의 deleteContentBackward

핵심: 모바일 IME는 composition 이벤트 없이 inputType만으로 처리할 수 있다.


플랫폼IME API브라우저가 받는 정보
WindowsTSF (Text Services Framework)조합 범위 + commit 문자열
macOSNSTextInputClientsetMarkedText (preedit) + insertText (commit)
LinuxIBus/Fcitxpreedit/commit 문자열

같은 “한글 가 입력”이라도:

  • Windows: TSF가 조합 범위를 관리 → 브라우저가 insertCompositionText로 매핑
  • macOS: setMarkedText("가") → 브라우저가 insertCompositionText 또는 insertText로 매핑
  • iOS: 키보드가 직접 문자열 전송 → 브라우저가 insertText로 매핑

같은 macOS에서도 Chrome, Firefox, Safari가 OS 이벤트를 DOM 이벤트로 변환하는 로직이 다르다.

브라우저특징
Chrome명세를 비교적 충실히 따름
Firefox조기 compositionend 버그 (Enter 시)
Safari이벤트 순서 역전, insertCompositionText 사용 불규칙

같은 iOS Safari라도:

  • 기본 한글 키보드 → 간헐적으로 composition 발생
  • 서드파티 키보드 (예: Gboard) → 다른 패턴

같은 Android Chrome이라도:

  • Gboard → 특정 패턴
  • Samsung 키보드 → 다른 패턴

명세가 강제하지 않는 부분:

  • beforeinput발생하지 않을 수 있음 (MDN: IME, 자동 완성, 비밀번호 관리자 등)
  • beforeinputnon-cancelable일 수 있음
  • “단어 삭제”의 단어 경계 정의가 언어마다 다름

결과: 브라우저가 재량으로 구현하는 부분이 많아 동작이 다르다.


// 1. composition 이벤트가 오면 최우선 처리
// 2. composition 없으면 inputType 기반 처리
// 3. beforeinput 없으면 input으로 동일 처리
let isComposing = false;
el.addEventListener('compositionstart', () => { isComposing = true; });
el.addEventListener('compositionend', (e) => {
isComposing = false;
if (e.data) commit(e.data);
});
el.addEventListener('beforeinput', (e) => {
if (isComposing) return; // composition이 처리
switch (e.inputType) {
case 'insertText':
commit(e.data);
break;
case 'insertReplacementText':
const range = e.getTargetRanges()?.[0];
replaceRange(range, e.data);
break;
case 'deleteContentBackward':
deleteBackward(1);
break;
case 'deleteWordBackward':
case 'deleteBackwardWord':
deleteWordBackward();
break;
}
});
el.addEventListener('beforeinput', (e) => {
const ranges = e.getTargetRanges();
if (ranges.length > 0) {
const range = ranges[0];
// range.startContainer, range.startOffset,
// range.endContainer, range.endOffset 로 정확한 범위 파악
}
});

주의: getTargetRanges()는 모든 환경에서 지원되지 않는다. 없으면 직접 계산해야 한다.