한글이 복사가 되는 버그 IsComposing

골두·2024년 6월 17일
0

Frontend

목록 보기
30/30
post-thumbnail

혼자 만드는 사이드 프로젝트 개발 중 enter키를 누르면 다음 element가 생성되면서 다음 input element가 만들어지는 기능 개발 중 엔터 키를 누르고 새로운 input element가 생성 시 마지막에 입력했던 한글(영어, 숫자는 재현 안됨)의 한글자만 새로운 input 창에 그대로 반영되는 문제가 발생하였다.

관련해서 문제를 찾다 KeyboardEvent의 isComposing을 사용하면 해결이 된다고 해 왜 이런 문제가 발생하였고, isComposing이 어떤 기능이길래 이 결과가 나온지에 대해 알아보자

이슈 원인 및 현상

우선 Input에서 한글의 마지막 한글자만 다음 element에 반영되는 문제의 현상과 원인을 먼저 알아야 할 것 같다.

현상

  • input에서 한글로 끝나는 value를 전부 입력하고 enter를 누르면 keydown event가 2번 동작하게 된다.
  • 다음에 만들어지는 input element에 이전 input의 마지막 한글 글자가 들어가게 된다.

원인

많은 구글링을 통해 알아본 결과 IME가 원인임을 알았다.

IME란?

IME는 입력 방식 편집기의 줄임말로 키 입력을 다른 언어로 된 문자로 변환하는 역할을 한다. 평소에 사용하는 영어 (qwerty) 키보드 자판을 한/영 키를 누르고 한글을 집어넣는 기능이 이 IME에서 단일 문자 대신에 IME로 해석되는 키 조합을 입력해주고 합성해주는 역할을 한다.

단순히 A,B,C,D를 쓰는 서구권 보다 다양한 글자를 조합해서 하나의 글자를 만드는 동양권에서 주로 사용되며, HTML, JS에서는 composition이라는 이벤트로 관리가 된다.

문제의 정확한 원인

한글도 여러개의 글자를 조합해서 하나의 글자를 만드는 언어체계 중 하나이기 때문에 이 IME에서 글자 조합에 동참하게 된다.composition 이벤트도 당연하게 발생하게 되는데 밑의 코드를 기반으로 확인해보면 정확한 문제를 파악할 수 있게 된다.

    <input
        onCompositionStart={() => {
            console.log("조합 중...");
        }}
        onCompositionEnd={() => {
            console.log("조합 완료...");
        }}
    />

위 코드로 실제로 값을 입력해보게 된다면 영어를 입력하게 된다면 어떠한 콘솔도 입력되지 않지만 한글을 입력하게 되면 콘솔의 로그가 남게 된다.

그리고 저 compositionEvent가 한번 더 발생하게 되면서 keydown 이벤트도 같이 발생하게 되어 한글의 경우 keydown이벤트가 철자의 완성 때 2번 발생하게 되는 것이다.

밑에는 composition에 대한 반응 사례이다.

글자 입력만 진행하였을 때

한글을 입력하다 보면 우리가 생각한 것과 다른 결과를 볼 수 있는데, 한글자만 입력이 끝나면 콘솔에는 "조합 중..." 이라는 문구만 남게된다.

아직 글자의 완성이 이루어지지 않았기 때문에 발생하는 현상으로 다음 글자로 넘어가기 전 까지는 End 상태가 아니고, 다음 글자를 입력하게 된다면 "조합 완료..."라는 compositionEnd 이벤트가 발생하고 다시 새로운 compositionStart 이벤트가 발생한다.

글자를 지울 때

글자를 지우게 될 때는 크게 2가지 케이스로 나뉘게 된다.

  1. 입력 직 후 마지막 글자를 지울 때
  • 마지막 글자를 입력한 직후에는 아직 compositionEvent가 끝나지 않은 상태이다. 그래서 지울 때 철자 하나하나가 다시 지워지면서 글자 자체가 사라지는 순간 compositionEnd Event 가 발생하게 된다.
  1. 나머지 케이스
  • 1번을 제외한 나머지 상황 (마지막 글자가 아닌 글자를 지우거나 입력 직후가 아닌 글자를 지우는 경우) 즉 철자 단위로 지우지 않는 경우는 compositionEvent가 시작하지도 끝나지도 않는다. 철자의 입력 상황에서만 compositionEvent가 발생하기 때문이다.

해결 방안

원인은 파악했으니 당연히 해결해야한다. composition의 이벤트에 대해 파악을 하였으니 keydown에서 composition event를 감지 해 composition event가 종료되는 시점에서만 keydown 이벤트를 실행시켜주면 되는 문제다.

keyDown event 객체안의 nativeEvent 객체안에는 isComposing이라는 boolean값이 존재하는데 이 값은 composition event가 진행되고 있는가를 검증하는 boolean 값이다. 이 값을 이용해 composition event가 진행되고 있지 않는 경우에만 keydown 이벤트를 실행할 수 있게 변경해주면 끝나는 문제다.

profile
나 볼려고 만든 블로그 (블로그 이전: https://goldfrosch.tistory.com/)

0개의 댓글