πŸ“¦ μž‘λ™μ‚¬λ‹ˆ

ν•˜λ‚˜μ˜ ν‚€μ›Œλ“œλ₯Ό 작고 μ’€ νŽΈν•˜κ²Œ μ •λ¦¬ν•˜κ³  μ‹Άμ–΄ λ§Œλ“  μž‘λ™μ‚¬λ‹ˆ

μž‘λ™μ‚¬λ‹ˆλŠ” μ‘°μ„  ν›„κΈ° ν•™μž μ•ˆμ •λ³΅μ΄ νŽΈμ°¬ν•œ μž‘λ™μ‚°μ΄(ι›œεŒζ•£η•°)μ—μ„œ 유래된 말이닀.
μž‘λ™μ‚°μ΄λŠ” 작기(ι›œθ¨˜)의 ν˜•νƒœλ₯Ό 빌렀온 μ±…μœΌλ‘œ ꡬ체적인 체계가 μž‘ν˜€μžˆμ§€ μ•Šμ€ ν˜•μ‹μ΄λ‹€.
ν•­λͺ©μ΄ λ‹€μ†Œ λ‚œμž‘ν•˜κ³  λ‚΄μš©μ˜ ꡬ뢄이 ν˜Όλ™λ˜μ–΄μžˆλ‹€κ³  ν•œλ‹€. 🀣

πŸ—‚οΈ onKeyDown in Korean

λ¦¬μ•‘νŠΈμ—μ„œ onKeyDown 이벀트λ₯Ό μ‚¬μš©ν•˜λ‹€κ°€ ν•œκΈ€ μž…λ ₯ μ‹œ μ΄λ²€νŠΈκ°€ λ‘λ²ˆ λ°œμƒν•˜λŠ” λ¬Έμ œκ°€ μžˆμ—ˆλ‹€.
λ¨Όμ € μ½”λ“œλŠ” μ•„λž˜μ™€ κ°™λ‹€.

// μœ—λΆ€λΆ„μ€ μƒλž΅...

return (
  <div className={styles['input-item']}>
    <input
      type="text"
      placeholder="ν•  일을 μž…λ ₯ν•΄μ£Όμ„Έμš”."
      value={inputText}
      onChange={handleInput}
      onKeyDown={(e) => {
        console.log(e);
        // λ¬Έμ œκ°€ λ˜λŠ” 곳은 μ—¬κΈ°λ‹€.
        if (e.key === 'Enter') {
          handleAdd();
          (inputRef.current as HTMLInputElement).focus();
        }
      }}
      ref={inputRef}
    />
    <button
      onClick={() => {
        handleAdd();
        (inputRef.current as HTMLInputElement).focus();
      }}
    >
      Add
    </button>
  </div>
);

μœ„ 처럼 onKeyDown μ΄λ²€νŠΈκ°€ λ°œμƒν–ˆμ„ λ•Œ, 이벀트(e)의 key값이 Enter인 κ²½μš°μ—λ§Œ handleAdd ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•˜λ„λ‘ ν–ˆλ‹€.
그런데 λ¬Έμ œλŠ” ν•œκΈ€μ„ 적고 Enterλ₯Ό μž…λ ₯ν•˜λ©΄ ν•œκΈ€ ν•œλ²ˆ, κ·Έ ν•œκΈ€μ˜ 끝 κΈ€μž ν•˜λ‚˜κ°€ 또 μž…λ ₯λ˜λŠ” κ²ƒμ΄μ—ˆλ‹€.
ν•΄μ„œ μœ„μ™€ 같이 이벀트λ₯Ό μ½˜μ†”λ‘œ μ°μ–΄λ³΄μ•˜λ‹€.

μ•„λž˜λŠ” γ…‡λ§Œ μž…λ ₯ ν›„, Enterλ₯Ό λˆŒλ €μ„ λ•Œμ˜ μ½˜μ†”μ΄λ‹€.

μ½˜μ†” 3개 사진

λΆ„λͺ… γ…‡κ³Ό Enter만 ν–ˆλŠ”λ°, event κ°μ²΄λŠ” 3κ°œκ°€ μ°ν˜€μžˆλ‹€. 3개의 객체λ₯Ό 쒀더 μžμ„Ένžˆ μ‚΄νŽ΄λ³΄μž.

μˆœμ„œλŒ€λ‘œ 객체의 이미지λ₯Ό λ‚˜μ—΄ν•˜λ©΄

  • γ…‡-229 γ…‡-229

  • Enter-229 Enter-229

  • Enter-13 Enter-13

λ­”κ°€ μ΄μƒν•˜λ‹€. 첫번째 γ…‡κ³Ό λ‘λ²ˆμ§Έ Enterκ°€ λΆ„λͺ…νžˆ λ‹€λ₯Έ 킀인데 μ™œ 같은 keyCode 값을 κ°–λŠ”κ±ΈκΉŒ?

이λ₯Ό μ•ŒκΈ° μœ„ν•΄μ„œλŠ” IME KeyCode 229 Issue(feat. Chrome + ν•œκΈ€)λ₯Ό μ°Έκ³ ν•˜μž.

정말 κ°„λ‹¨ν•˜κ²Œ μ„€λͺ…ν•˜λ©΄ ν•œκΈ€κ³Ό 같이 λ¬Έμžλ“€μ˜ μ‘°ν•©μœΌλ‘œ μƒˆλ‘œμš΄ λ¬Έμžκ°€ λ˜λŠ” μ–Έμ–΄μ˜ κ²½μš°μ—λŠ” keyλ₯Ό μž…λ ₯ μ‹œμ—, λΈŒλΌμš°μ €μ˜ IME(Input Method Editor)κ°€ μž…λ ₯을 λ°›κ³  isComposing = true μƒνƒœκ°€ λœλ‹€. 즉, 아직 문자λ₯Ό μ‘°ν•©ν•˜κ³  μžˆλŠ” μ€‘μ΄λΌλŠ” μ˜λ―Έμ΄λ‹€. 이 λ‹¨κ³„μ—μ„œλŠ” λͺ¨λ“  key 값이 229둜 λ‚˜μ˜€κ²Œ λœλ‹€.
κ²°κ΅­ λ§ˆμ§€λ§‰ Enterλ₯Ό μž…λ ₯ μ‹œ, isComposing이 true인 이벀트, false인 μ΄λ²€νŠΈκ°€ 2번 λ°œμƒν•˜λŠ” 것이닀.

κ·Έλ ‡λ‹€λ©΄ 이제 해결책은 간단해보인닀! if 쑰건문으둜 keyCode ν˜Ήμ€ which 값이 229인 경우 early return μ‹œν‚€λ©΄ λœλ‹€.

μ΄λ ‡κ²Œ 해결은 λμ§€λ§Œ, κ²½κ³ κ°€ ν•˜λ‚˜ λ“±μž₯ν•œλ‹€. λ°”λ‘œ keyCode와 whichλŠ” 곧 deprecated 될 μ˜ˆμ •μ΄λΌλŠ” 경고이닀. κ·Έλ ‡λ‹€λ©΄ λ§ˆμ§€λ§‰ 남은 μˆ˜λ‹¨μ΄ μžˆλ‹€. λ°”λ‘œ e.isComposing을 μ‚¬μš©ν•˜λŠ” 것이닀. 그런데 또 ν•˜λ‚˜ μ£Όμ˜ν•  점은, λ¦¬μ•‘νŠΈ onKeyDown μ΄λ²€νŠΈλŠ” ν•œλ²ˆ 감싸진 μƒνƒœμ΄κΈ° λ•Œλ¬Έμ— e.nativeEvent.isComposing을 톡해 μ ‘κ·Όν•˜λ©΄ λœλ‹€.

μ•„λž˜λŠ” ν•΄κ²°ν•œ μ˜ˆμ‹œ μ½”λ“œμ΄λ‹€.

return (
  <div className={styles['input-item']}>
    <input
      type="text"
      placeholder="ν•  일을 μž…λ ₯ν•΄μ£Όμ„Έμš”."
      value={inputText}
      onChange={handleInput}
      onKeyDown={(e) => {
        // μ•„λž˜μ™€ 같이 isComposing이 true인 κ²½μš°λŠ” early return μ‹œν‚¨λ‹€.
        if (e.nativeEvent.isComposing) return;
        if (e.key === 'Enter') {
          handleAdd();
          (inputRef.current as HTMLInputElement).focus();
        }
      }}
      ref={inputRef}
    />
    <button
      onClick={() => {
        handleAdd();
        (inputRef.current as HTMLInputElement).focus();
      }}
    >
      Add
    </button>
  </div>
);

μ°Έκ³