[SvelteKit] 프론트엔드 UX 개선의 디테일: tabindex="-1"와 .blur() 활용법

2025. 11. 11. 16:58·💻 개발/📒 JavaScript
728x90
반응형

| 서론

훌륭한 사용자 경험(UX)은 종종 눈에 잘 띄지 않는 작은 디테일에서 시작됩니다. 특히 사용자가 키보드만으로 서비스를 원활하게 이용할 수 있도록 하는 '키보드 네비게이션'과, 현재 활성화된 요소를 명확히 보여주는 '포커스(Focus) 관리'는 매우 중요한 부분입니다.

 

최근 're-log' 프로젝트의 회고 작성 페이지를 개선하면서, 바로 이 포커스 관리를 통해 사용자 경험을 한 단계 끌어올릴 수 있었는데요. 이번 포스팅에서는 다소 생소할 수 있는 tabindex="-1" 속성과 .blur() 메서드를 어떻게 활용했는지 공유해 보겠습니다.

 

 

 

| 문제 상황: 원치 않는 포커스 이동과 잔상

회고 작성 페이지에는 여러 입력 섹션이 있고, 각 섹션 사이를 쉽게 이동할 수 있도록 "이전", "다음" 네비게이션 버튼을 추가했습니다. 하지만 이로 인해 두 가지 불편한 점이 발생했습니다.

  1. 키보드 함정 (Tab Trap)
    : 사용자가 회고 내용을 입력하다가 Tab 키를 눌러 다음 입력창으로 이동하려고 할 때, 의도와 다르게 네비게이션 버튼(이전/다음)으로 포커스가 이동했습니다. 이 버튼들은 주로 마우스나 터치 사용자를 위한 보조 기능인데, 키보드 사용자의 주된 작업 흐름(폼 작성)을 방해하는 '함정'이 된 것입니다.
  2. 끈적한 포커스 (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 키를 이용한 순차적인 키보드 네비게이션 흐름에서 이 버튼들을 제외시켰습니다.

Svelte
 
<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()를 호출했습니다.

Svelte
 
<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 요소들의 포커스 상태를 한번 점검해 보시면 어떨까요? 작은 디테일이 서비스의 완성도를 크게 높일 수 있습니다.

728x90
반응형

'💻 개발 > 📒 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
'💻 개발/📒 JavaScript' 카테고리의 다른 글
  • [JavsScript] 자바스크립트의 마법사: Unary Plus(+) 연산자 활용법
  • [JS] JavaScript 필수 자료구조 & 메서드 정리 — 배열·문자열·객체·Set·정렬까지 한 번에
  • 테스트보다 구현이 먼저,,? - 로또 발매기 프로젝트에서 배운 TDD의 전환점
  • 하나의 클래스가 너무 많은 일을 할 때 — LottoMachine 리팩토링 이야기
pangil_kim
pangil_kim
기록을 통해 지속적인 성장을 추구합니다.
  • pangil_kim
    멈추지 않는 기록
    pangil_kim
  • 전체
    오늘
    어제
  • 📝 글쓰기
      ⚙️ 관리

    • 분류 전체보기 (434) N
      • 💻 개발 (188) N
        • ※ 참고 지식 (10)
        • 🦕 React (16)
        • 🎩 Next.js (25)
        • 📘 TypeScript (4)
        • 📒 JavaScript (9)
        • 🟩 Node.js (7)
        • 📀 MySQL (24)
        • 🌸 Spring Boot (5)
        • 👷 SveleteKit (24)
        • 🩵 Flutter (11)
        • 🌀 Dart (2)
        • 🌈 CSS (5)
        • 🔸Git (1)
        • 🔥 Firebase (4)
        • 🧑🏻‍💻 코테 (29)
        • 🕸️ 알고리즘 (5)
        • 🌤️ AWS (1)
        • 🤖 AI Agent (1)
        • 🧬 Backend (2)
        • 🅰️ Angular (3) N
      • 📋 프로젝트 (6)
        • ☄️ 트러블 슈팅 (3)
        • 🧑🏻‍💻 서비스 소개 (3)
      • ✍🏻 회고 (67)
        • ☀️ 취준일지 (13)
        • 🍀 우테코 (32)
        • 👋 주간회고 (6)
      • 📰 정보 공유 (12)
      • 🧑🏻‍💻 개발자라면? (1)
      • 🏫 한동대학교 (153)
        • Database (15)
        • Software Engineering (18)
        • EAP (22)
        • 일반화학 (26)
        • 25-1 수업 정리 (19)
        • Computer Networking (36)
        • OPIc (2)
        • 미술의 이해 (15)
  • 최근 글

  • 인기 글

  • 태그

    부트캠프
    GLS
    주일
    묵상
    날마다 솟는 샘물
    예배
    데이터베이스
    찬양
    한동대학교
    웹 프론트엔드 8기
    웹개발
    전산전자공학부
    우테코 8기
    우테코
    QT
    csee
    날솟샘
    네트워킹
    프론트엔드
    typeScript
    CCM
    어노인팅
    프리코스
    우아한테크코스
    컴네
    설교
    computer networks and the internet
    고윤민교수님
    글로벌리더십학부
    FE
  • 최근 댓글

  • 250x250
  • hELLO· Designed By정상우.v4.10.4
pangil_kim
[SvelteKit] 프론트엔드 UX 개선의 디테일: tabindex="-1"와 .blur() 활용법
상단으로

티스토리툴바