Focus Order — 개념, 원칙 및 모바일 앱에서 설정 방법

저자: IT Sectr 게시일: 2026-05-16 읽는 시간: 9 분

Focus Order는 키보드, Switch Control, VoiceOver 또는 TalkBack으로 탐색할 때 인터페이스 요소가 포커스를 받는 순서입니다. 모바일 애플리케이션에서 포커스 순서는 사용자가 제스처나 버튼을 통해 컨트롤 간을 이동하는 방식을 결정합니다. W3C WCAG 2.2, Success Criterion 2.4.3, 2023에 따르면 포커스는 콘텐츠의 의미를 유지하는 논리적 순서를 따라야 합니다. 이 원칙을 위반하면 접근성 감사에서 실패하는 일반적인 원인 중 하나입니다.

핵심 사항

  • Focus Order — 키보드 또는 스크린 리더로 탐색할 때 대화형 요소를 순회하는 순서
  • 포커스는 시각적 순서(왼쪽에서 오른쪽, 위에서 아래)를 따라야 하며 콘텐츠 논리를 유지해야 합니다
  • iOS에서는 shouldGroupAccessibilityElement 및 accessibilityElements 배열을 통해 순서가 제어됩니다
  • Android에서는 nextFocusDown, nextFocusUp, nextFocusLeft, nextFocusRight 속성이 포커스 이웃을 정의합니다
  • 사용자 정의 화면(지도, 캔버스, 게임)은 UIAccessibilityPostNotification을 통한 프로그래매틱 포커스 관리가 필요합니다

접근성에서 Focus Order란

Focus Order는 사용자가 대체 입력 방법(키보드(Tab), Switch Control(단계별), VoiceOver(오른쪽/왼쪽 스와이프), TalkBack)을 사용하여 대화형 요소 간을 이동하는 순서입니다. 마우스나 터치 스크린과 달리 사용자가 직접 요소를 선택하는 방식이 아닌, 포커스 탐색은 선형적이며 각 단계마다 다음 요소로 포커스가 이동합니다.

Apple HIG, 2024에 따르면 VoiceOver는 접근성 트리에서 요소의 순서를 사용하며, 이는 시각적 배치(왼쪽 상단 모서리 → 오른쪽 하단 모서리)를 기반으로 구축됩니다. 화면에 복잡한 레이아웃(열, Grid, ZStack)이 있는 경우 트리가 시각적 순서와 일치하지 않을 수 있습니다.

WCAG 2.4.3 원칙: “웹 페이지를 섹션별로 순차적으로 탐색할 수 있고 포커스 순서가 의미에 영향을 미치는 경우, 포커스는 의미와 작동 가능성을 유지하는 순서를 따라야 합니다”. 예외: 주의를 끌기 위해 포커스가 점프할 수 있는 동적 콘텐츠(경고, 모달 창).

Focus Order가 접근성에 중요한 이유

Switch Control 사용자(운동 장애가 있는 사람)는 자동으로 요소 간을 이동합니다(주기 반복). 순서가 깨지면 사용자는 양식 작성에 3배 더 많은 시간이 소요됩니다. Deque University, 2024에 따르면 올바른 Focus Order는 보조 기술 사용자의 양식 작성 시간을 60% 단축합니다.

Focus Order 및 모달 창

특별히 주의해야 할 사항은 모달 창입니다. 모달을 연 후 포커스는 모달 내의 첫 번째 대화형 요소(일반적으로 “닫기” 또는 “확인” 버튼)로 즉시 이동해야 합니다. 닫은 후에는 모달을 트리거한 요소로 돌아가야 합니다. 이는 WCAG 2.4.3의 요구 사항이자 동시에 일반적인 실수입니다.

iOS: 포커스 순서 관리

iOS에서 VoiceOver는 기하학을 기반으로 자동으로 순서를 구성합니다. 요소는 Y로 정렬된 다음 X로 정렬됩니다. 복잡한 구조의 화면에서는 이 순서가 올바르지 않을 수 있으며 개발자가 개입해야 합니다.

주요 도구:

  • shouldGroupAccessibilityElement — 하위 요소를 하나의 논리적 블록으로 그룹화
  • accessibilityElements — 하위 요소의 사용자 정의 순서를 정의하는 배열
  • UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, element) — 프로그래매틱 포커스 이동

제품 카드에 대한 사용자 정의 순서 설정 예시:

swift
class ProductCardView: UIView {
    let titleLabel = UILabel()
    let priceLabel = UILabel()
    let buyButton = UIButton()

    override var accessibilityElements: [Any]? {
        get {
            return [titleLabel!, priceLabel!, buyButton!]
        }
        set {}
    }
}

작업 후 프로그래매틱 포커스 이동:

swift
UIAccessibility.post(
    notification: .layoutChanged,
    argument: newlyAddedItem
)

실제 shouldGroupAccessibilityElement 사용

shouldGroupAccessibilityElement 속성은 컬렉션의 카드에 유용합니다. 부모 카드에서 true로 설정하면 VoiceOver는 전체 카드를 하나의 요소로 인식합니다. 사용자는 더블 탭으로 전체 카드를 활성화하거나 내부 탐색을 위한 로터를 구성할 수 있습니다. UICollectionViewCell 및 UITableViewCell에 권장됩니다.

Android: 포커스 방향 속성

Android에서 TalkBack도 기하학적 순서를 사용하지만 명시적 nextFocus* 속성이 우선시됩니다. 이러한 속성은 XML 또는 프로그래매틱 방식으로 설정됩니다:

속성목적예시
nextFocusDown아래로 탐색할 때 요소@+id/field_email
nextFocusUp위로 탐색할 때 요소@+id/field_name
nextFocusLeft왼쪽 요소@+id/btn_back
nextFocusRight오른쪽 요소@+id/btn_next

등록 양식 예시:

xml
<EditText
    android:id="@+id/field_email"
    android:nextFocusDown="@+id/field_password" />

<EditText
    android:id="@+id/field_password"
    android:nextFocusDown="@+id/btn_submit" />

RecyclerView의 경우 포커스 순서는 동적이며 어댑터에 의해 결정됩니다. 셀의 구조가 복잡한 경우 descendantFocusability = “beforeDescendants”를 설정하고 목록 항목 노드에서 순서를 정의합니다. Jetpack Compose의 경우 포커스 순서는 Modifier.focusOrder() 및 FocusOrder를 통해 설정됩니다. 우선순위: previous(하위), next(다음), 사용자 정의 키.

TouchDelegate, 히트 영역 및 포커스 영역

요소가 포커스에 너무 작은 경우(44pt 미만) iOS의 TouchDelegate 또는 Android의 minWidth/minHeight를 통해 히트 영역을 늘립니다. Google Material Design, 2024에 따르면 최소 터치 영역은 48×48dp입니다. VoiceOver와 TalkBack은 요소의 경계 상자에 포커스를 맞춥니다. 30pt 미만의 요소는 제스처 포커스에 접근할 수 없을 수 있습니다. 사용자가 물리적으로 탭할 수 없습니다.

WCAG 2.4.3의 일반적인 위반

점프하는 포커스 — 작업(예: 요소 삭제) 후 포커스가 목록의 시작이나 시스템 “뒤로” 버튼으로 이동합니다. VoiceOver 사용자는 컨텍스트를 잃습니다. 해결책: 삭제된 요소에 가장 가까운 요소로 프로그래매틱 방식으로 포커스를 이동합니다.

보이지 않는 포커스 — 요소가 포커스를 받지만 시각적 표시기가 없습니다(키보드 사용자는 현재 위치를 볼 수 없음). iOS에서 사용자 정의 표시기를 위해 UIAccessibility.isVoiceOverRunning을 확인합니다. Deque University, 2024에 따르면 보이지 않는 포커스는 접근성 감사 실패의 두 번째로 흔한 원인입니다.

모달 — 모달을 연 후에도 포커스가 배경 콘텐츠에 남아 있습니다. iOS에서 modalPresentationStyle = .pageSheet가 설정된 경우 모달 보기가 자동으로 포커스를 캡처합니다. Android에서는 대화상자 컨테이너에 setFocusable(true)를 사용합니다.

포커스 트랩

반대 문제: 포커스가 모달 내부에 갇혀 빠져나올 수 없습니다(닫는 것 외에는). 이는 모달 창에만 허용됩니다. 사용자는 의도적으로 창을 닫아야 합니다. 일반 화면의 경우 포커스 트랩은 심각한 오류입니다. 해결책: 모달의 마지막 요소(“닫기” 버튼)가 포커스를 반환하는지 확인합니다.

사용자 정의 화면 및 프로그래매틱 포커스

사용자 정의 화면(지도, 캔버스, 게임)의 경우 자동 기하학적 순서를 적용할 수 없습니다. 개발자가 수동으로 접근성 트리를 구축해야 합니다. iOS에서는 이를 위해 UIAccessibilityContainer 메서드를 재정의합니다.

사용자 정의 캔버스 예시:

swift
class CanvasView: UIView {
    var shapes: [ShapeView] = []

    override var accessibilityElements: [Any]? {
        get {
            // Z-인덱스로 도형 정렬, 기하학 기준 아님
            return shapes.sorted { $0.zIndex < $1.zIndex }
        }
        set {}
    }
}

Android에서 사용자 정의 View의 경우 onInitializeAccessibilityNodeInfo를 재정의합니다:

kotlin
override fun onInitializeAccessibilityNodeInfo(
    info: AccessibilityNodeInfo
) {
    super.onInitializeAccessibilityNodeInfo(info)
    info.addChild(firstElement)
    info.addChild(secondElement)
    info.isFocusable = true
}

동적 목록(채팅, 뉴스 피드)의 경우 요소를 추가한 후 첫 번째 새 요소로 포커스를 이동합니다. iOS: UIAccessibility.post(notification: .layoutChanged, argument: newMessage). Android: sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED).

AccessibilityFrame 및 포커스 기하학

iOS는 요소의 프레임을 기반으로 자동으로 포커스 영역을 결정합니다. 요소에 변환(transform, rotation)이 있는 경우 VoiceOver가 잘못된 영역에 포커스할 수 있습니다. 화면 좌표로 accessibilityFrame을 명시적으로 설정합니다: element.accessibilityFrame = UIAccessibility.convertToScreenCoordinates(element.bounds, in: element). 이렇게 하면 VoiceOver가 올바른 영역을 강조 표시합니다.

UIKit Dynamics 및 접근성

애니메이션 화면(UIKit Dynamics, Lottie, SpriteKit)의 경우 프로그래매틱 포커스가 특히 중요합니다. VoiceOver는 동적으로 움직이는 요소에 대한 접근성 트리를 구축할 수 없습니다. 애니메이션 컨테이너에서 isAccessibilityElement = false를 설정하고 내부의 대화형 요소에만 true를 설정합니다.

포커스 순서 테스트

수동 테스트: VoiceOver(iOS) 또는 TalkBack(Android)을 활성화하고 전체 시퀀스를 오른쪽으로 스와이프합니다. 포커스는 시각적 순서(왼쪽에서 오른쪽, 위에서 아래)를 따라야 합니다. 각 대화형 요소는 정확히 한 번 포커스를 받아야 합니다.

자동화된 테스트는 어렵지만 가능합니다:

swift
func testKeyboardFocusOrder() {
    let app = XCUIApplication()
    app.launch()
    app.textFields["Email"].tap()
    // Tab — 하드웨어 키보드만 해당
}

Android의 경우 Accessibility Testing Framework를 사용합니다:

kotlin
@Test
fun testFocusOrder() {
    onView(withId(R.id.fieldEmail))
        .check(matches(isFocusable()))
    onView(withId(R.id.fieldEmail))
        .perform(focus())
    onView(withId(R.id.fieldPassword))
        .check(matches(isFocused()))
}

가장 신뢰할 수 있는 방법은 UI 시나리오 테스트입니다: 양식을 단계별로 작성하고(이메일 → 비밀번호 → 제출) 각 단계가 성공적으로 완료되는지 확인합니다. 포커스 순서가 깨지면 포커스 외부 요소와 상호 작용하려고 할 때 시나리오가 실패합니다.

디버깅을 위한 Xcode Accessibility Inspector

Xcode의 Accessibility Inspector 도구는 전체 접근성 트리를 표시합니다. VoiceOver 순서로 요소를 탐색하고 정확한 포커스 경로를 확인할 수 있습니다. “Audit” 탭을 사용하여 Focus Order 위반을 자동으로 감지합니다.

자주 묻는 질문

WCAG 2.4.3이란 무엇이며 포커스 요구 사항은 무엇인가요?

WCAG 2.4.3(Focus Order)은 레벨 A 성공 기준입니다. 순차적 탐색 중 포커스 순서가 콘텐츠 의미를 유지해야 합니다. 위반은 심각한 것으로 간주되며 인증을 차단합니다.

애니메이션 뒤에 숨겨진 요소의 포커스 순서를 설정하는 방법은?

숨겨진 요소는 iOS에서 isAccessibilityElement = false 또는 Android에서 visibility = gone/invisible이어야 합니다. 나타나면 UIAccessibility.post(notification: .layoutChanged)를 통해 프로그래매틱 방식으로 포커스를 이동합니다.

iOS와 Android에서 포커스의 차이점은 무엇인가요?

iOS는 accessibilityElements 및 shouldGroupAccessibilityElement를 통해 관리하고, Android는 nextFocus* 속성 및 AccessibilityNodeInfo를 통해 관리합니다. 원칙은 동일합니다: 기본적으로 기하학적 순서로 재정의 가능합니다.

RecyclerView의 순서가 잘못된 경우 어떻게 해야 하나요?

루트 요소에 descendantFocusability = “beforeDescendants”를 설정하고 각 셀에 대해 onInitializeAccessibilityNodeInfo를 통해 어댑터에서 순서를 구성합니다.

VoiceOver 없이 포커스를 테스트하는 방법은?

Bluetooth 또는 USB를 통해 하드웨어 키보드를 연결합니다. iOS에서 Tab을 눌러 포커스를 이동합니다. Android에서 TalkBack을 활성화하고 Tab 키와 화살표 키를 사용합니다.

요약

  • Focus Order — 키보드 또는 스크린 리더로 탐색할 때 요소 순회 순서, WCAG 2.4.3 기반
  • 포커스는 시각적 순서(왼쪽에서 오른쪽, 위에서 아래)를 따라야 함 — VoiceOver 및 TalkBack에서 자동
  • iOS에서는 accessibilityElements 및 shouldGroupAccessibilityElement로 순서 제어
  • Android에서는 nextFocusDown, nextFocusUp, nextFocusLeft, nextFocusRight 속성 사용
  • 사용자 정의 화면(지도, 캔버스)은 UIAccessibilityPostNotification을 통한 프로그래매틱 포커스 관리 필요
  • 순서 위반은 WCAG 2.4.3의 심각한 오류, 사용자는 컨텍스트를 잃고 시나리오를 완료할 수 없음
  • VoiceOver/TalkBack 제스처, 하드웨어 키보드 및 자동화된 시나리오로 포커스 테스트

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기