| 서론
훌륭한 사용자 경험(UX)은 종종 눈에 잘 띄지 않는 작은 디테일에서 시작됩니다. 특히 사용자가 키보드만으로 서비스를 원활하게 이용할 수 있도록 하는 '키보드 네비게이션'과, 현재 활성화된 요소를 명확히 보여주는 '포커스(Focus) 관리'는 매우 중요한 부분입니다.
최근 're-log' 프로젝트의 회고 작성 페이지를 개선하면서, 바로 이 포커스 관리를 통해 사용자 경험을 한 단계 끌어올릴 수 있었는데요. 이번 포스팅에서는 다소 생소할 수 있는 tabindex="-1" 속성과 .blur() 메서드를 어떻게 활용했는지 공유해 보겠습니다.
| 문제 상황: 원치 않는 포커스 이동과 잔상
회고 작성 페이지에는 여러 입력 섹션이 있고, 각 섹션 사이를 쉽게 이동할 수 있도록 "이전", "다음" 네비게이션 버튼을 추가했습니다. 하지만 이로 인해 두 가지 불편한 점이 발생했습니다.
- 키보드 함정 (Tab Trap)
: 사용자가 회고 내용을 입력하다가 Tab 키를 눌러 다음 입력창으로 이동하려고 할 때, 의도와 다르게 네비게이션 버튼(이전/다음)으로 포커스가 이동했습니다. 이 버튼들은 주로 마우스나 터치 사용자를 위한 보조 기능인데, 키보드 사용자의 주된 작업 흐름(폼 작성)을 방해하는 '함정'이 된 것입니다. - 끈적한 포커스 (Sticky Focus)
: 사용자가 마우스로 "다음" 버튼을 클릭하면, 화면은 다음 섹션으로 스크롤되지만 포커스는 여전히 방금 클릭한 버튼에 남아 파란색 테두리(focus-ring)가 계속 표시되었습니다. 사용자의 시선과 작업 흐름은 이미 다음 섹션으로 넘어갔는데, 불필요한 포커스 잔상이 시각적인 노이즈를 만들었습니다.
이 두 가지 문제를 해결하기 위해 tabindex="-1"와 .blur()라는 간단하지만 강력한 해결책을 적용했습니다.
| 해결책 1: tabindex="-1"로 탭 순서에서 제외하기
첫 번째 '키보드 함정' 문제를 해결하기 위해 tabindex="-1" 속성을 사용했습니다.
1) tabindex란?
tabindex는 HTML 요소가 키보드 포커스를 받을 수 있는지, 그리고 탭 순서에서 몇 번째인지를 결정하는 속성입니다.
- tabindex="0": 요소를 자연스러운 탭 순서에 포함시킵니다.
- tabindex="1" (이상): 숫자 순서대로 강제적인 탭 순서를 부여합니다. (접근성 측면에서 권장되지 않음)
- tabindex="-1": 요소를 탭 순서에서는 제외하지만, JavaScript(.focus())를 통해서는 포커스를 받을 수 있도록 합니다.
즉, tabindex="-1"는 "키보드(Tab)로는 접근할 수 없지만, 코드를 통해서는 제어할 수 있는" 상태를 만들어 줍니다.
2) 적용 결과
네비게이션 버튼에 이 속성을 추가함으로써, Tab 키를 이용한 순차적인 키보드 네비게이션 흐름에서 이 버튼들을 제외시켰습니다.
<button
tabindex="-1"
class="navigation-button"
on:click|preventDefault={ ... }
>
<ArrowBigLeft size="18" />
</button>
이제 사용자는 Tab 키를 눌렀을 때 입력창 사이를 자유롭게 이동할 수 있으며, 네비게이션 버튼이 더 이상 작업 흐름을 방해하지 않습니다.
| 해결책 2: .blur()로 클릭 후 포커스 제거하기
두 번째 '끈적한 포커스' 문제는 .blur() 메서드로 해결했습니다.
1) .blur()란?
.blur()는 특정 HTML 요소에 적용된 포커스를 프로그래밍 방식으로 제거하는 JavaScript 메서드입니다. .focus()의 정반대 역할을 합니다.
2) 적용 결과
Svelte의 on:click 이벤트 핸들러에서, 섹션 이동 로직(scrollToSection)이 실행된 직후 클릭된 버튼 스스로의 포커스를 제거하도록 .blur()를 호출했습니다.
<button
tabindex="-1"
class="navigation-button"
on:click|preventDefault={(e) => {
scrollToSection(nextTitle);
// e.currentTarget은 현재 이벤트를 수신한 요소를 가리킵니다.
(e.currentTarget as HTMLButtonElement).blur();
}}
>
<ArrowBigRight size="18" />
</button>
이제 버튼을 클릭하면 다음 섹션으로 부드럽게 이동함과 동시에, 버튼에 남아있던 포커스 링이 깔끔하게 사라집니다. 사용자는 시각적인 방해 없이 새로운 섹션의 내용에만 집중할 수 있습니다.
| 결론
- tabindex="-1": 키보드 사용자의 주된 동선을 방해하지 않도록 보조적인 UI(버튼 등)를 탭 순서에서 제외할 때 사용합니다.
- .blur(): 상호작용이 끝난 요소(주로 클릭된 버튼)의 포커스를 명시적으로 제거하여 시각적 노이즈를 줄일 때 사용합니다.
이처럼 tabindex 속성과 .blur() 메서드는 웹 접근성과 사용자 경험의 미세한 부분을 조율할 수 있는 강력한 도구입니다.
여러분의 프로젝트에서도 사용자와 상호작용하는 UI 요소들의 포커스 상태를 한번 점검해 보시면 어떨까요? 작은 디테일이 서비스의 완성도를 크게 높일 수 있습니다.
'💻 개발 > 📒 JavaScript' 카테고리의 다른 글
| [JavsScript] 자바스크립트의 마법사: Unary Plus(+) 연산자 활용법 (0) | 2026.03.14 |
|---|---|
| [JS] JavaScript 필수 자료구조 & 메서드 정리 — 배열·문자열·객체·Set·정렬까지 한 번에 (0) | 2026.01.01 |
| 테스트보다 구현이 먼저,,? - 로또 발매기 프로젝트에서 배운 TDD의 전환점 (0) | 2025.11.03 |
| 하나의 클래스가 너무 많은 일을 할 때 — LottoMachine 리팩토링 이야기 (0) | 2025.11.03 |
| Matchers - Jest (0) | 2025.10.24 |