export default function TeamPageHeader() {
const teamNameRef = useRef<HTMLInputElement>(null)
const { mutate: addTeam } = usePostNewTeam(teamNameRef)
const addTeamEnter = (e: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => {
if (e.key === 'Enter' && teamNameRef.current) {
e.preventDefault()
addTeam(teamNameRef.current.value)
}
}
return (
<InputBase
inputRef={teamNameRef}
sx={{ ml: 1, flex: 1 }}
placeholder={t('teamPageHeader.팀 추가')}
inputProps={{ 'aria-label': 'search google maps' }}
onKeyDown={addTeamEnter}
/>
)
}
input 태그에 위 코드와 같이 onkeydown이벤트 발생 시 함수가 호출되도록 코드를 작성했으나, input 내부 값이 한글로 입력되면 함수가 두 번 호출되는 문제가 발생했다. 특이한 점은 영어나 숫자 입력 시엔 정상적으로 동작하지만, 한글 입력시에만 문제가 발생한다는 점이였다.
해당 문제의 원인은 IME때문이였는데, IME란 한글과 같이 자음 모음이 조합되는 언어체계에서 자음 모음이 분리되지 않고 한 글자로 입력할 수 있도록 도와주는 시스템 소프트웨어이다. 엔터키 입력 시 이벤트가 두 번 발생하는 이유는, 가장 최근에 입력된 한글 자모가 조합이 완료된 상태인지, 조합이 완료되지 않은 상태인지 알 수 없기 때문에, 각각의 상태에서 모두 이벤트를 호출하기 때문이였다.
찾아보니 두 가지 해결방법이 있었다. onkeydown 이벤트를 활용하는 것이아니라, onkeypress 이벤트를 활용하는 것이 첫 번째 해결방법이였다.
https://developer.mozilla.org/en-US/docs/Web/API/Element/keypress_event
하지만 mdn 공식문서에서 onkeypress가 최근의 웹표준에서 제거되어 더이상 지원되지 않을 예정이라고 하여 다른 방법을 알아보았다.
문제가 발생하는 원인이 한글 문자의 자모가 조합중인 상태일 때, 조합이 완료된 상태일 때 모두 이벤트를 호출하기 때문에 발생하는 것이니, 조합중인 상태일때는 이벤트가 발생하지 않도록 하거나, 이벤트에 등록된 함수가 동작하지 않도록 하면 된다.
그럼 자모가 조합중인 상태를 알아야할텐데 이는 기본적으로 event객체의 isComposing 값을 통해 알 수 있다. 만약 조합중이라면 isComposing이 true, 아니라면 false로 boolean값이 나타난다.
하지만 리액트의 경우 event객체에서 바로 isComposing에 접근할 수 없고, nativeEvent에 먼저 접근 후, isComposing에 접근해야한다.
https://ko.legacy.reactjs.org/docs/events.html#overview
const addTeamEnter = (e: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => {
if (e.nativeEvent.isComposing) {
return
}
// isComposing이 true일 때, 얼리 리턴을 통해 함수가 종료되도록 함.
if (e.key === 'Enter' && teamNameRef.current) {
e.preventDefault()
addTeam(teamNameRef.current.value)
}
}