WCAG 성공 기준 · Level A

WCAG 2.2.1: 시간 조정 가능

WCAG 2.2.1은 콘텐츠에 의해 설정된 모든 시간 제한을 사용자가 끄거나, 조정하거나, 연장할 수 있어야 한다고 요구합니다. 이는 웹 콘텐츠와 상호작용하는 데 더 많은 시간이 필요한 사람들이 접근하지 못하는 상황을 방지하기 위한 것입니다. 이 A 레벨 기준은 운동, 인지, 시각 장애가 있는 사용자들에게 필수적입니다.

이 규칙의 의미

WCAG 2.2.1 Timing Adjustable는 원칙 2(조작 가능성) 아래의 레벨 A 성공 기준이다. 이 기준은 콘텐츠에 의해 설정된 각 시간 제한에 대해 다음 중 최소 하나는 반드시 충족되어야 한다고 규정한다. 사용자가 시간 제한에 도달하기 전에 그 시간 제한을 끌 수 있어야 하거나, 사용자가 시간 제한을 넓은 범위(기본 설정의 최소 열 배)에서 조정할 수 있어야 하거나, 또는 사용자가 시간 제한이 만료되기 전에 키를 누르거나 버튼을 클릭하는 것과 같은 간단한 동작으로 시간 제한을 연장할 수 있어야 하며, 이때 최소 20초 전에 경고를 제공하고 최소 열 번 이상 연장할 수 있는 선택지를 제공해야 한다.

실질적으로 이 기준은 세션 타임아웃을 적용하는 웹 인터페이스, 시간에 따라 자동으로 넘어가는 슬라이드가 있는 자동 진행 캐러셀, 자동으로 지워지거나 제출되는 폼, 체크아웃 페이지의 카운트다운 타이머, 일시정지가 불가능한 시간 제한 자막이 있는 미디어 플레이어, 또는 사용자가 작업을 완료할 수 있는 시간을 제한하는 기타 모든 메커니즘에 적용된다. 페이지나 애플리케이션이 타이머를 설정하고, 그 타이머가 만료되면 사용자의 동의 없이 콘텐츠를 제거하거나, 사용자를 로그아웃시키거나, 새로운 상태로 진행시키는 경우, 반드시 그 시간 제한을 조정하거나 연장할 수 있는 방법을 제공해야 한다.

이 기준은 또한 위에서 설명한 조정 메커니즘 없이 시간 제한을 유지할 수 있게 해 줄 수 있는 세 가지 중요한 예외를 정의한다. 첫째, 실시간 예외이다. 시간 제한이 실시간 이벤트(예: 실시간 경매나 동기식 온라인 시험)의 필수적인 일부인 경우, 시간을 조정하면 활동 자체가 무효화되며, 대체 수단이 실질적으로 불가능하다. 둘째, 본질적 예외이다. 시간 제한이 본질적이며 이를 연장하면 활동이 무효화되는 경우 — 예를 들어, 반응 속도를 측정하는 것이 목적이어서 응답 속도 측정이 핵심인 시간 제한 기술 시험이 이에 해당한다. 셋째, 20시간 예외이다. 시간 제한이 20시간을 초과하는 경우, 사용자에게 가해지는 부담은 최소한으로 간주되며 조정 컨트롤은 요구되지 않는다.

준수는 시간 제한이 있는 상호작용이 명확한 메커니즘을 제공할 때 발생한다. 이상적으로는 사용자가 시간 제한에 도달하기 전에 제시되며, 사용자가 시간 제약을 비활성화하거나 연장하거나 조정할 수 있게 해 준다. 위반은 콘텐츠가 자동으로 만료되거나, 리디렉션되거나, 사용자를 로그아웃시키거나, 위의 세 가지 조정 옵션 중 어느 것도 제공하지 않은 채 진행되며, 세 가지 예외 중 어느 것도 적용되지 않을 때 발생한다.

중요한 이유

시간 제한은 장애가 있는 사람들에게 불균형적인 영향을 미친다. 스크린 리더에 의존하는 사용자는 콘텐츠를 선형적으로 듣고, 익숙하지 않은 인터페이스를 순차적으로 탐색해야 하기 때문에 시력이 있는 사용자보다 페이지 탐색 속도가 더 느린 경우가 많다. 스위치 액세스 장치, 시선 추적 소프트웨어, 마우스 스틱, 음성 제어 소프트웨어 등을 사용하는 사람을 포함한 운동 장애가 있는 사용자는 폼 필드를 채우거나, 구매를 확정하거나, 다음 단계로 이동하는 데 훨씬 더 오랜 시간이 걸릴 수 있다. 난독증, 주의력 결핍, 기억력 장애 등 인지 또는 학습 장애가 있는 사용자는 지시 사항을 읽고 이해하고 응답하는 데 추가 시간이 필요할 수 있다. 고령자 역시 동일한 작업에 더 많은 시간이 필요한 경우가 흔하며, 이들은 전 세계 인터넷 인구에서 빠르게 증가하는 집단을 이루고 있다.

구체적인 실제 상황을 생각해 보자. 뇌성마비가 있는 한 사람이 터키 항공사 웹사이트에서 항공편 예약을 완료하고 있다. 체크아웃 세션은 5분 동안 아무 활동이 없으면 자동으로 만료된다. 사용자는 머리 포인터 장치를 사용해 천천히 타이핑하며 이름, 여권 번호, 결제 정보를 입력했지만, 페이지가 새로 고침되면서 모든 데이터가 지워지고 홈페이지로 돌아가 버린다. 사용자의 노력은 모두 사라졌을 뿐 아니라, 사이트에 대한 신뢰도 흔들리며, 결국 구매를 완료하지 못할 수도 있다. 이는 디지털 상거래에 동등하게 참여하는 데 대한 직접적인 장벽이다.

영향은 개별 사용자에 그치지 않는다. 세계보건기구(WHO)에 따르면 전 세계적으로 약 13억 명이 어떤 형태로든 중대한 장애를 가지고 살아가고 있다. 터키만 보더라도 TÜİK의 공식 통계에 따르면 850만 명이 넘는 사람이 일상 활동에 영향을 미치는 장애를 가지고 있다. 시간 제한이 있는 인터페이스는 어떤 웹 애플리케이션이든 잠재 사용자 기반의 상당 부분을 배제한다.

접근성을 넘어, 임의의 시간 제한을 제거하거나 조정 가능하게 만드는 것은 저대역폭 환경의 사용자, 일시적으로 운동 기능이 저하된 사용자(예: 팔이 부러진 경우), 그리고 단순히 작업 도중 방해를 받는 사용자에게도 도움이 된다. 이러한 사용성 개선은 폭넓게 적용되며, 폼 이탈률을 줄이고, 전자상거래 사이트의 전환율을 높이며, 고객 지원 문의량을 줄일 수 있다.

관련 Axe-core 규칙

WCAG 2.2.1은 수동 테스트를 요구한다. axe-core, Lighthouse 및 유사 엔진을 포함한 자동화 도구는 시간 제한이 종종 서버 측 세션 로직, 비동기적으로 실행되는 JavaScript, 또는 서드파티 통합으로 구현되기 때문에 타이밍 위반을 신뢰할 수 있게 감지할 수 없다. 도구는 DOM을 검사하거나 정적 분석을 수행하는 것만으로는 페이지가 5분 후에 만료되는지, 또는 캐러셀이 사용자 입력 없이 진행되는지를 관찰할 방법이 없다. 다음 고려 사항은 테스터가 수동으로 평가해야 하는 내용을 설명한다.

  • 세션 타임아웃(수동): 테스터는 세션 타임아웃을 기다리거나 이를 시뮬레이션하여 페이지가 사전 경고를 표시하는지, 연장 옵션을 제공하는지, 그리고 사용자가 응답할 수 있도록 최소 20초를 제공하는지 확인해야 한다. 자동 규칙은 실제로 타임아웃이 발생할 때까지 기다리지 않고는 세션 지속 시간이나 경고 대화 상자가 제때 나타나는지를 판단할 수 없다.
  • 자동 진행 캐러셀 및 슬라이더(수동): 테스터는 캐러셀이 자동으로 진행되는지, 그렇다면 일시정지 또는 정지 컨트롤이 존재하며 키보드로 접근 가능한지를 관찰해야 한다. Axe-core는 캐러셀 구성 요소에서 일부 누락된 ARIA 속성을 감지할 수 있지만, 시간에 따른 진행 자체가 조정 가능한지 여부는 판단할 수 없다.
  • 자동 제출 또는 자동 초기화 폼(수동): 폼이 일정 시간 비활성 상태 후에 내용을 제출하거나 지우는 경우, 테스터는 관찰이나 코드 검토를 통해 이러한 동작을 파악해야 한다. DOM만으로는 자동 스캐너에 이 동작이 드러나지 않는다.
  • 거래 흐름의 카운트다운 타이머(수동): 체크아웃 페이지, 티켓 예매 흐름, 시험 환경에는 카운트다운 타이머가 포함되는 경우가 많다. 이러한 타이머가 본질적인 것(따라서 예외에 해당)인지, 아니면 연장 메커니즘이 필요한지는 구현과 비즈니스 맥락 모두에 대한 인간의 검토가 필요한 판단 사항이다.

테스트 방법

  1. 자동 스캔 기준선: 페이지에 대해 axe DevTools 또는 Lighthouse를 실행하여 타이밍 문제를 악화시킬 수 있는 알려진 ARIA 또는 인터랙티브 요소 위반을 식별한다. 이 도구들은 시간 제한 자체를 표시하지는 않지만, 다른 접근성 문제의 기준선을 설정하는 데 도움이 된다. Chrome DevTools에서 Lighthouse 패널을 열고 Accessibility를 선택한 뒤 감사를 실행한다. axe DevTools에서는 브라우저 확장을 활성화하고 Analyze를 클릭한 후 결과를 검토한다. 타이밍 관련 규칙은 나타나지 않을 것이며, 이는 수동 테스트가 필요함을 확인해 준다.
  2. 모든 시간 제한 식별: 페이지의 JavaScript 소스, 네트워크 요청, 서버 측 세션 설정을 검토하여 모든 시간 제한을 식별한다. 일반적인 위치로는 JavaScript의 setTimeoutsetInterval 호출, 백엔드 프레임워크의 세션 만료 설정, 쿠키 만료 값, 결제 프로세서나 채팅 위젯과 같은 서드파티 위젯 설정이 있다.
  3. NVDA + Firefox로 세션 타임아웃 경고 테스트: Firefox에서 NVDA를 실행한 상태로 사이트를 연다. 다단계 폼이나 인증 구역을 탐색한다. 세션 경고 대화 상자(또는 경고가 나타나지 않는 경우 타임아웃 자체)를 기다린다. NVDA가 경고를 자동으로 — 이상적으로는 라이브 리전을 통해 — 알리는지, 그리고 사용자가 포커스된 버튼에서 Enter 또는 Space를 눌러 폼 데이터를 잃지 않고 세션을 연장할 수 있는지 확인한다.
  4. VoiceOver + Safari(macOS/iOS)로 세션 타임아웃 경고 테스트: Safari에서 VoiceOver를 활성화한 상태로 위 테스트를 반복한다. 로터를 사용해 인터랙티브 요소를 탐색하고, 타임아웃 경고가 안내되는지, 그리고 연장 컨트롤에 20초 이내에 접근할 수 있는지 확인한다.
  5. JAWS + Chrome으로 세션 타임아웃 경고 테스트: Chrome에서 JAWS로 반복 테스트한다. 포커스가 경고 대화 상자로 이동하는지, JAWS가 남은 시간과 연장 옵션을 읽어 주는지, 그리고 연장 버튼을 활성화했을 때 페이지 새로 고침 없이 세션이 유지되는지 확인한다.
  6. 키보드만으로 테스트(스크린 리더 없음): 마우스를 비활성화하고 Tab, Shift+Tab, Enter, Space만으로 탐색한다. 경고 대화 상자에 키보드로 접근할 수 있는지, 연장 버튼에 포커스를 둘 수 있는지, 세션이 연장된 후 포커스가 폼 내의 올바른 위치로 돌아오는지 확인한다.
  7. 캐러셀 및 미디어 타이밍 테스트: 자동 진행 캐러셀을 모두 식별한다. Tab으로 캐러셀에 이동한다. 마우스 없이 접근 가능한 일시정지 또는 정지 버튼이 있는지 확인한다. 이를 활성화하고 진행이 멈추는지 확인한다. 캐러셀이 사용자 상호작용 후 다시 시작되는 경우, 자동으로 재시작되지 않는지 확인한다.
  8. 예외 적용 가능성 검증: 발견된 각 시간 제한에 대해 실시간 예외, 본질적 예외, 20시간 예외 중 어느 것이 적용되는지 판단한다. 그 근거를 문서화한다. 예외가 적용되지 않고 조정 메커니즘도 존재하지 않는다면, 이를 WCAG 2.2.1 위반으로 기록한다.

수정 방법

경고 없는 세션 타임아웃 — 잘못된 예

<!-- Session expires silently after 5 minutes; page reloads with no warning -->
<script>
  setTimeout(function() {
    window.location.href = '/session-expired';
  }, 300000);
</script>

경고 및 연장이 있는 세션 타임아웃 — 올바른 예

<!-- Warn user 60 seconds before expiry; offer extension; announce via live region -->
<div
  id='session-warning'
  role='alertdialog'
  aria-modal='true'
  aria-labelledby='warning-title'
  aria-describedby='warning-desc'
  hidden
>
  <h2 id='warning-title'>Your session is about to expire</h2>
  <p id='warning-desc'>
    Your session will expire in <span id='countdown'>60</span> seconds.
    Select "Stay logged in" to continue your session.
  </p>
  <button id='extend-btn' type='button'>Stay logged in</button>
  <button id='logout-btn' type='button'>Log out now</button>
</div>

<script>
  var SESSION_DURATION = 300000; // 5 minutes
  var WARNING_BEFORE   = 60000;  // warn 60 seconds before
  var sessionTimer, warningTimer, countdownInterval;

  function startSessionTimer() {
    warningTimer = setTimeout(showWarning, SESSION_DURATION - WARNING_BEFORE);
    sessionTimer = setTimeout(expireSession, SESSION_DURATION);
  }

  function showWarning() {
    var dialog = document.getElementById('session-warning');
    dialog.hidden = false;
    document.getElementById('extend-btn').focus(); // move focus to dialog
    var seconds = 60;
    countdownInterval = setInterval(function() {
      seconds--;
      document.getElementById('countdown').textContent = seconds;
      if (seconds <= 0) clearInterval(countdownInterval);
    }, 1000);
  }

  function extendSession() {
    clearTimeout(sessionTimer);
    clearTimeout(warningTimer);
    clearInterval(countdownInterval);
    document.getElementById('session-warning').hidden = true;
    startSessionTimer();
    // Return focus to last active element
  }

  function expireSession() {
    window.location.href = '/session-expired';
  }

  document.getElementById('extend-btn').addEventListener('click', extendSession);
  document.getElementById('logout-btn').addEventListener('click', expireSession);
  startSessionTimer();
</script>

컨트롤 없는 자동 진행 캐러셀 — 잘못된 예

<!-- Slides advance every 4 seconds; no pause control; no keyboard access -->
<div class='carousel'>
  <div class='slide active'>Slide 1 content</div>
  <div class='slide'>Slide 2 content</div>
  <div class='slide'>Slide 3 content</div>
</div>

일시정지 컨트롤이 있는 자동 진행 캐러셀 — 올바른 예

<!-- Pause button stops auto-advance; button label updates to reflect state -->
<section aria-roledescription='carousel' aria-label='Featured announcements'>
  <div aria-live='off' aria-atomic='true'>
    <div class='slide active' role='group' aria-roledescription='slide' aria-label='Slide 1 of 3'>
      Slide 1 content
    </div>
    <div class='slide' role='group' aria-roledescription='slide' aria-label='Slide 2 of 3'>
      Slide 2 content
    </div>
    <div class='slide' role='group' aria-roledescription='slide' aria-label='Slide 3 of 3'>
      Slide 3 content
    </div>
  </div>
  <button id='carousel-pause' type='button' aria-pressed='false'>
    Pause slideshow
  </button>
</section>

<script>
  var paused = false;
  var btn = document.getElementById('carousel-pause');
  btn.addEventListener('click', function() {
    paused = !paused;
    btn.setAttribute('aria-pressed', paused.toString());
    btn.textContent = paused ? 'Play slideshow' : 'Pause slideshow';
    // toggle the carousel's auto-advance logic accordingly
  });
</script>

연장 옵션이 없는 시간 제한 체크아웃 카운트다운 — 잘못된 예

<!-- 10-minute checkout lock; no extension offered; not an essential exception -->
<p>Your items are reserved for: <span id='timer'>10:00</span></p>
<!-- Timer expires, cart is cleared silently -->

연장 옵션이 있는 시간 제한 체크아웃 카운트다운 — 올바른 예

<!-- Warn before expiry and offer a one-click extension -->
<p>
  Your items are reserved for:
  <span id='timer' aria-live='polite' aria-atomic='true'>10:00</span>
</p>
<div id='extend-notice' hidden role='alert'>
  <p>Your reservation expires in 2 minutes.</p>
  <button type='button' id='extend-checkout'>Give me more time</button>
</div>
<!--
  When timer reaches 2:00, reveal #extend-notice.
  Clicking the button resets the reservation timer via an API call.
  aria-live='alert' ensures screen readers announce the warning immediately.
-->

일반적인 실수

  • 키보드 포커스 관리 없이 타임아웃 경고를 표시하는 경우: 경고 대화 상자는 시각적으로 나타나지만 포커스가 그곳으로 이동하지 않아, 키보드만 사용하는 사용자와 스크린 리더 사용자는 세션이 만료되기 전에 세션을 연장할 수 있다는 사실을 알지 못한다.
  • 타임아웃 경고에 응답할 수 있는 시간을 20초 미만으로 제공하는 경우: 로그아웃 10초 전에만 “세션이 만료됩니다”라는 경고를 표시하는 것은, 연장 동작을 위해 최소 20초를 제공해야 한다는 기준을 충족하지 못한다.
  • 상호작용이 필요한 타임아웃 대화 상자에 role='alert'를 사용하는 경우: alert 역할은 읽기 전용 알림을 위한 것이다. 사용자 입력이 필요한 대화 상자는 스크린 리더가 응답이 필요한 모달로 인식하도록 role='alertdialog', aria-modal='true', aria-labelledby를 사용해야 한다.
  • 일반 전자상거래 장바구니 타이머에 본질적 예외를 주장하는 경우: 장바구니에서 상품을 10분 동안만 예약하는 것은 비즈니스 편의일 뿐, 속도 측정이 목적이 되는 진정한 본질적 활동이 아니다. 여기서 본질적 예외를 적용하는 것은 잘못이며, 연장 메커니즘이 필요하다.
  • 눈에 보이는 키보드 접근 가능한 일시정지 버튼 없이 캐러셀을 자동 진행하는 경우: 마우스를 올렸을 때만 보이는 일시정지 버튼을 추가하거나, Tab 순서에 포함되지 않은 버튼을 두는 것은 기준을 충족하지 못한다. 컨트롤은 포인팅 장치 없이도 접근 가능해야 한다.
  • 마우스 움직임에는 타임아웃 카운터를 리셋하지만 키보드 이벤트에는 그렇지 않은 경우: mousemove 이벤트에서는 비활성 타이머를 연장하지만 keydown이나 focus 이벤트는 무시하는 JavaScript는, 페이지에서 적극적으로 작업 중인 키보드 전용 사용자의 세션을 조용히 만료시킨다.
  • 전체 페이지 새로 고침으로 세션을 연장하는 경우: 사용자가 “로그인 유지”를 클릭했을 때 페이지를 새로 고침하면, 사용자가 폼에 입력한 데이터가 모두 지워진다. 연장은 DOM 상태를 유지한 채 백그라운드에서 API 호출이나 쿠키 갱신을 통해 이루어져야 한다.
  • 사용자가 구성하거나 볼 수 없는 setTimeout 값을 사용하는 경우: 세션 길이를 5분으로 하드코딩하고, 사용자가 더 긴 기간을 선택할 수 있는 UI 컨트롤을 제공하지 않는 것은, 세 가지 조정 메커니즘(끄기, 조정, 연장) 중 하나라도 제공되지 않는 한 기준을 위반하는 것이다.
  • 출시 전에 실제 보조 기술로 타임아웃 흐름을 테스트하지 않는 경우: 마우스로만 테스트하는 개발자는 경고 대화 상자가 스크린 리더 사용자에게 접근 불가능하다는 사실을 눈치채지 못할 수 있다. 시각적 테스트만으로는 포커스 관리 실패가 드러나지 않기 때문이다.
  • 서드파티 임베디드 위젯이 자동으로 준수한다고 가정하는 경우: iframe이나 스크립트로 임베드된 결제 프로세서, 라이브 채팅 위젯, 예약 엔진은 종종 자체 시간 제한을 적용한다. 전체 페이지 — 여러분이 제어하는 임베디드 콘텐츠를 포함해 — 의 WCAG 준수 책임은 페이지 소유자에게 있다.

터키 접근성 규정과의 관계

2025년 6월 21일 관보 제32933호에 게재된 터키 대통령령 2025/10은 터키에서 디지털 서비스를 운영하는 광범위한 공공 및 민간 주체에 대해 WCAG 2.2 레벨 AA와 정렬된 의무적 웹 접근성 요구 사항을 수립한다. WCAG 2.2.1 Timing Adjustable는 레벨 A 기준으로, 준수의 기초층에 해당한다. 즉, 적용 대상 기관이 가장 먼저 충족해야 하는 요구 사항 중 하나이다.

대통령령에 따라, 공공 기관 및 기관 — 부처, 지방자치단체, 대학, 국영 기업 등을 포함 — 은 대통령령 공포일로부터 1년 이내에 완전한 준수에 도달해야 한다. 규제 대상인 민간 부문 주체는 준수를 위해 2년의 기간을 가진다. 민간 부문의 범위는 명시적으로 넓다. 전자상거래 플랫폼, 은행 및 금융 기관, 민간 병원 및 보건 서비스 제공자, 가입자 200,000명 이상인 통신사, 여행사, 민간 여객 운송 회사, 그리고 국립교육부(MoNE) 인가를 받아 운영되는 민간 학교가 포함된다.

이 범주에 속한 조직에게 WCAG 2.2.1 위반은 단순한 모범 사례 미준수가 아니라, 규제 당국의 감시, 공식 채널을 통한 민원, 평판 훼손을 초래할 수 있는 법적 비준수이다. 이 위반을 가장 쉽게 유발할 수 있는 구체적인 비즈니스 흐름을 생각해 보자. 시간 제한 장바구니 예약이 있는 전자상거래 체크아웃, 고객이 결제 폼을 작성하는 동안 조용히 만료되는 온라인 뱅킹 세션, 운동 장애가 있는 사용자가 등록을 완료하기 전에 타임아웃되는 병원 예약 시스템, 계약 관리 흐름에서 사용자를 자동 로그아웃시키는 통신사의 셀프 서비스 포털 등이 있다. 이들 각각은 대통령령에 명시적으로 언급된 주체 유형 내에서 충분히 발생 가능한 실패 시나리오이다.

조직은 WCAG 2.2.1 준수를 단순한 기술적 체크박스가 아니라, 세션 관리 정책, 서드파티 위젯 조달 요구 사항, UI 구성 요소 표준 등 아키텍처 수준에서 해결해야 할 설계 요구 사항으로 취급해야 한다. 사후에 덧붙이는 방식으로 수정해서는 안 된다. 감사 프로그램에는 자동 스캔뿐 아니라 모든 시간 제한 상호작용에 대한 수동 테스트가 포함되어야 한다. 자동 도구는 사람의 관찰 없이는 이 유형의 위반을 감지할 수 없기 때문이다.