리액트 한글 중복 추가 현상 해결하기

최경락 (K_ROCK_)·2022년 6월 27일
0

개요

  • input 에 텍스트를 입력하고 엔터를 누르면 태그가 추가되도록 하는 기능을 만드는 중에, 한글을 입력 할 시 마지막 글자가 따로 추가되는 현상이 발생했다.

  • 이를 수정하기 위해 구글링을 해보았고, 아래의 블로그에 정리가 잘 되어 있어 참고했다.

https://velog.io/@corinthionia/JS-keydown에서-한글-입력-시-마지막-음절이-중복-입력되는-경우-함수가-두-번-실행되는-경우

  • 사실, 여기서 해결하고자 하는 문제는 onKeyPress 를 사용하면 해결되는 문제라고 한다.
  • 하지만, TS 상에서 해당 이벤트를 쓰려고 하면 취소선과 함께 @deprecated 라고 표시되므로, 다른 방법을 사용해 처리 할 것이다.
    @deprecated : 더 이상 사용되지 않는다.

키 입력 이벤트의 차이

  • 키 입력 이벤트로는 onKeyUp, onKeyDown, onKeyPress 가 가장 대표적이다.

keyCode / ASCII 감지

  • 예시 코드
<input
  type="text"
  onKeyDown={(e) =>
    console.log(
      'event : onKeyDown',
      '/ key :',e.key,
      'keyCode :',e.keyCode,
      'charCode :',e.charCode
    )
  }
  onKeyUp={(e) =>
    console.log(
      'event : onKeyUp',
      '/ key :',e.key,
      'keyCode :',e.keyCode,
      'charCode :',e.charCode
    )
  }
  onKeyPress={(e) =>
    console.log(
      'event : onKeyPress',
      '/ key :',e.key,
      'keyCode :',e.keyCode,
      'charCode :',e.charCode
    )
  }
/>;

→ 입력된 키와 keyCode, charCode 를 출력하는 코드이다.

  • 여기서 onKeyUponKeyDownkeyCode 를 감지하고, onKeyPressASCII 코드를 감지한다.
  • 콘솔로 이벤트를 출력할 때, onKeyUponKeyDownkeyCode 값은 불러오지만, charCode(ASCII) 값은 0으로 처리한다.
  • 반대로, onKeyPresscharCode 값을 불러오고, keyCode 를 0으로 처리한다.
  • 실행 결과는 아래와 같다.

  • 그리고, onKeyPress 의 경우 ASCII 코드에 포함되지 않은 키들(Meta, Backspace, 방향키, Shift, Ctrl, Alt 등…)은 감지해내지 못한다.

→ 즉, onKeyPress 를 사용하면 조합된 일부 키입력을 사용 할 수가 없다.

이벤트 실행 타이밍의 차이

  • onKeyPress : 키가 눌렸을 때 실행 됨
  • onKeyDown : 키가 눌려있는 동안 실행 됨
    → 만약 키를 계속 누르고 있는 상태라면 반복적으로 실행된다.
  • onKeyUp : 키를 눌렀다가 떼면 실행 됨.

KeyboardEvent.isComposing

  • 조합문자를 작성할 때 사용되는 composition session 이 실행 중인지 아닌지를 감지하여 그 결과를 Boolean 값으로 반환하는 프로퍼티이다.
    → 영어는 조합문자가 아니므로, 위와 같은 중복 이벤트 실행 문제가 발생하지 않는다.
  • 해당 프로퍼티가 false 인 경우를 조건문에 추가함으로써 composition session 이 종료된 뒤에 값을 추가하므로, 중복 이벤트 실행 문제를 해결 할 수 있다.

해결

const addKeyword = (e: React.KeyboardEvent<HTMLInputElement>) => {
  if (
    keywordValue &&
    !keywords.includes(keywordValue) &&
    e.key === 'Enter' && 
    e.nativeEvent.isComposing === false // 요기
  ) {
    setKeywords([...keywords, keywordValue]);
    setKeywordValue('');
  }
};

+

  • 현재는 keyCode 도 사용되지 않으며, key 를 사용한다.
  • 하지만, key 를 지원을 하지 않는 브라우저가 있다고 하니 참고만 해두자.
    → 비주류 브라우저라 크게 신경쓰지 않아도 될 듯 하다.

syntheticEvent / nativeEvent

  • syntheticEvent 는 리액트가 모든 브라우저에서 이벤트를 처리할 수 있게끔 전달하는 객체이다.
  • nativeEvent 는 브라우저 고유의 이벤트를 이야기하며, syntheticEvent는 이를 래핑하여 전달하는 역할을 한다.
  • 즉, nativeEvent 를 통해 리액트를 통해 래핑되지 않은 이벤트 프로퍼티, 메소드에 접근 할 수 있다.

0개의 댓글