Input 제일 뒤로 커서 보내기

Input 제일 뒤로 커서 보내기

2024-11-062 min read

배경

회사에서 진행 중인 프로젝트에서 UX 향상을 위해 키보드 사용성 개선 작업을 진행했어요. Input 컴포넌트 하위에 검색 결과가 리스트 형태로 노출되고, 해당 리스트 아이템들을 키보드로 쉽게 탐색하고 선택할 수 있는 UX를 구현하는 것이 목적이었어요.

기본적인 동작은 잘 작동했지만, 키보드 사용성을 강화하면서 새로운 UX적인 불편함이 발생했어요.
바로, 키보드로 포커싱한 리스트 아이템에서 다시 Input으로 포커스를 이동할 때, Input에 값이 있음에도 불구하고 커서가 항상 맨 앞으로 고정된다는 점이었어요.

Pain Point

이 이슈는 단순히 백로그 성격의 문제일 수 있지만, 개인적으로는 중요한 UX 결함이라고 느꼈어요.

사용자가 가장 불편하게 느낄 수 있는 지점은 다음과 같아요:

“타이핑을 잘못해서 다시 수정하려고 커서를 옮겼는데, 예상과 다르게 커서가 맨 앞으로 이동한다면?”

이런 경험은 사용자가 기대하는 UX와 실제 동작이 다르다고 느끼게 만들고, 불필요한 인지적 스트레스를 유발해요 🫠

해결방법

이 문제를 해결하기 위해 리서치를 진행하던 중, 아래와 같은 사실을 알게 되었어요.

  • input 요소에는 전체 선택을 위한 select 메서드가 있어요.
  • 커서 위치를 특정 지점으로 이동하거나 범위를 지정해 선택할 수 있는 setSelectionRange 메서드도 존재해요.
  • setSelectionRangeWHATWG forms spec에 따라 text, search, url, tel, password 타입에서만 사용할 수 있어요.

🔍 WHATWG란?
WHATWG는 Web Hypertext Application Technology Working Group의 약자로, 웹 표준을 정의하는 그룹이에요.
웹 표준은 브라우저 간 호환성을 보장하고, 웹 개발자들이 참고할 수 있는 명확한 지침을 제공해요.

키보드 사용성을 챙길때 제작한 React.Ref도 있었고, 기본적으로 Input 컴포넌트에서 onFocus 메서드를 지원해주니 포커스 이벤트 발생 시, 커서를 Input 맨 뒤로 이동시키면 되겠다고 판단했어요.

하지만… 예상대로 동작하지 않았어요 🥲

실패 원인 분석

생각을 조금 더 정리해보니, 실패 원인은 브라우저의 렌더링 타이밍에 있었어요.

focus 이벤트가 발생하고 onFocus 핸들러가 호출되는 시점에는 브라우저가 아직 Input의 포커스 상태나 커서 위치 정보를 완전히 반영하지 않은 상태일 수 있어요. 이로 인해 setSelectionRange를 즉시 호출해도 커서 위치가 예상대로 설정되지 않는 문제가 있었어요.

해결방법: setTimeout

저는 해당 문제를 해결하기 위해 setTimeout을 사용했어요. setTimeout는 콜백함수의 실행시점을 현재 실행중인 코드블록 다음 순서로 실행하기 때문이에요.

상세 이유: setTimeout API는 MacroTaskQueue로 분류되어 MicroTaskQueue에 등록된 핸들러가 먼저 실행되어 렌더링 업데이트가 처리된 후 실행되기 때문이에요. 비슷한 원리의 해결방법으론 requestAnimationFrame가 있어요.

const DELAY_TIME = 0; const INPUT_END_INDEX = inputRef.current?.value.length ?? 0; const handleFocusToEnd = () => { setTimeout(() => { inputRef.current?.setSelectionRange(INPUT_END_INDEX, INPUT_END_INDEX); }, DELAY_TIME); }

setTimeout의 delay를 0초로 두고 실행하게되면 Input에 포커스 되고 값이 반영되는 시점 이후의 이벤트 루프에서 코드를 실행하게 되기때문에 커서 위치를 원하는 대로 이동시킬 수 있어요.

마무리

이번 버그를 해결하면서 단순한 커서 위치 조정 문제를 넘어, 브라우저 렌더링 흐름, 이벤트 루프, WHATWG 명세까지 사고를 확장할 수 있었어요. 마이너한 이슈일 수 있지만 생각보다 얻은 지식이 많아서 좋았어요.

Profile Image

Clzzi

Frontend 개발자 손민재입니다. 방문해 주셔서 감사합니다!