[JS] keydown/keyup에서 한글 입력 시 함수가 두 번 실행되는 경우

Joohyun·2022년 2월 16일
35

MailedIt!

목록 보기
1/1
post-thumbnail

새로운 블로그로 이전했습니다!
https://corinthionia.github.io/post/javascript/keydown-keyup-twice


MailedIt! 서비스를 개발하다 오랫동안 해결하지 못한 에러가 있었다.
Notion처럼 텍스트를 입력하고 엔터를 누르면 새로운 블럭이 만들어지는데, 기존 텍스트의 마지막 음절이 딸려오는 에러가 발생했다.


원인 분석

1. onKeyDown과 onKeyPress?

구글링 해 본 결과, 단순히 onKeyDownonKeyPress로 바꾸면 해결된다고 한다.
그럼 우선 이 둘의 차이점을 알아보자.

onKeyDown: keycode 값 - 한/영, Shift, Backsapce 등 인식 가능
onKeyPress: ASCII 값 - 한/영, Shift, Backsapce 등 인식 불가

하지만 우리 프로젝트에서는 Shift 키와 Backspace 키를 인식해야 해서 onKeyPress사용할 수는 없었다.

2. KeyboardEvent.isComposing?

KeyboardEvent.isComposing은 입력한 문자가 조합문자인지 아닌지를 판단한다. 한글은 자음과 모음의 조합으로 한 음절이 만들어지기 때문에 조합문자이고, 영어는 조합문자가 아니다.

한글을 입력할 때 자세히 보면 입력 중인 글자 바로 아래에 검은 밑줄이 생기는 경우가 있는데, 이 밑줄이 보이는 상황에서 Enter키를 입력하면 이벤트가 2번 발생하는 이슈가 있다. 왜냐하면 글자가 조합 중인 건지, 조합이 끝난 상태인지 파악하기가 어렵기 때문이다.

그래서 이 이슈는 영어를 입력할 때에는 발생하지 않고, 한글을 입력할 때에만 발생한다 ㅠㅠ!


해결 과정

1. 프로젝트 로직 설명

  • Enter 키 입력 시 블럭 생성
  • Shift + Enter 키 입력 시 블럭 내에서 줄바꿈
  • Backspace키가 입력되고, 블럭 안의 텍스트가 없거나 공백 문자만 있다면 블럭 삭제

내가 작성한 코드는 아니지만,, 이전에 작성했던 코드는 다음과 같다.

onKeyDownHandler(e) {
    if (e.key === 'Enter') {
      if (this.state.previousKey !== 'Shift') {
        e.preventDefault();
        this.props.addBlock({ 새로운 블럭 추가 (코드 생략) });
      }
    } else if (
      e.key === 'Backspace' &&
      (this.state.html === '' || this.state.html === '<br>')
    ) {
      e.preventDefault();
      this.props.deleteBlock({ 블럭 삭제 (코드 생략) });
    }
    this.setState({ previousKey: e.key });
  }

2. onKeyDown을 onKeyPress로 바꿔 보기

이렇게 하면 Shift 키와 Delete 키를 인식하지 못해서 줄바꿈과 블럭 삭제가 안 되는 문제가 발생했다. 우리는 저 두 가지 키를 꼭 인식해야 하므로... onKeyDown을 사용하며 해결할 방법을 모색했다.

3. event.nativeEvent.isComposing === false 추가하기 ✓

onKeyDownHandler(e) {
    if (e.key === "Enter") {
      if (
        e.nativeEvent.isComposing === false &&
        this.state.previousKey !== "Shift"
      ) {
        e.preventDefault();
        this.props.addBlock({ 새로운 블럭 추가 (코드 생략) });
      }
    }

조건식에 e.nativeEvent.isComposing === false 을 추가했다.

콘솔에서 e.nativeEvent.isComposing 값을 확인해 보면, 첫 글자를 입력할 때와 공백을 입력할 때 false 값이 찍히고, 글자를 입력하는 동안에는 true, 마지막에 Enter 키를 누르면 truefalse함께 찍히게 된다.

따라서 이전에 입력한 키가 Shift 키가 아니고, Enter를 입력했을 때 e.nativeEvent.isComposing 값이 false이면 블럭을 추가하도록 구현하여 마지막 음절이 딸려오는 에러를 해결할 수 있었다!


profile
https://corinthionia.github.io

6개의 댓글

comment-user-thumbnail
2022년 2월 22일

입출력이 제일 쉬운 것 같으면서도 버그를 야기하는 상황이 많은 것 같아요😥

1개의 답글
comment-user-thumbnail
2023년 4월 13일

덕분에 에러를 해결했습니다 감사합니다 :)

답글 달기
comment-user-thumbnail
2024년 5월 2일

감사합니다

답글 달기
comment-user-thumbnail
2024년 5월 16일

잘 해결하고 갑니다 감사합니다~

답글 달기
comment-user-thumbnail
2024년 9월 12일

잘 보고 갑니다!

답글 달기