WeniVooks

검색

아는 만큼 보이는 웹접근성 WCAG 2.2

가이드라인 2.3 발작 및 신체적 반응 예방

발작 및 신체적 반응 지침은 웹 콘텐츠가 발작이나 부정적인 신체적 반응을 유발하지 않도록 설계해야 한다는 원칙입니다. 이 지침의 주요 목적은 광과민성 발작 장애가 있는 사용자를 보호하고, 모든 사용자에게 안전한 브라우징 경험을 제공하는 것입니다.

핵심 내용으로는 깜박이는 콘텐츠의 사용을 제한하고, 특정 주파수와 크기를 초과하는 번쩍임을 피하며, 필요한 경우 사용자가 애니메이션을 제어할 수 있게 하는 것이 포함됩니다. 개발자는 이를 위해 초당 3회 이상 깜박이는 콘텐츠를 피하고, 필요한 경우 사용자가 애니메이션을 정지하거나 숨길 수 있는 옵션을 제공해야 합니다. 또한, 모션 애니메이션의 사용을 신중히 고려하고, 가능한 경우 사용자가 이를 비활성화할 수 있는 방법을 제공해야 합니다.

광과민성 발작이란?

비디오 게임 등에서 볼 수 있는 번쩍이는 빛이나 무늬 같은 시각적 이미지에 노출되어 현기증, 환각, 눈이나 얼굴의 경련, 팔이나 다리의 경련이나 떨림, 방향 감각 상실, 정신 착란, 일시적인 의식 상실 등의 여러가지 증상을 일으키는 간질 발

1. 성공 기준 2.3.1 세 번의 깜박임 또는 임계값 이하

(레벨 A)

포켓몬스터 애니메이션

1997년 일본에서 포켓몬스터 전뇌 전사 폴리곤 편이 방영되었을 때 약 750명 정도의 어린아이들이 구토, 어지럼증 심한 경우에는 경련, 의식 상실, 호흡 장애를 겪었습니다. 이는 ‘광과민성 발작’의 증상이었는데 해당 영상에서 초당 12번 밝게 반짝이는 장면이 포함되어 있어 나타난 증상이었습니다.

그러므로 웹 페이지는 1초 기간 동안 3회 이상 깜박이는 콘텐츠를 포함해서는 안 되며, 또는 깜박임은 일반 깜박임 및 적색 깜박임 임계값 이하여야 합니다.

이 성공 기준을 만족하지 못하는 콘텐츠는 사용자가 전체 페이지를 사용하는 능력을 방해할 수 있으므로, 웹 페이지의 모든 콘텐츠(다른 성공 기준을 만족시키는 데 사용되는지 여부와 관계없이)는 이 성공 기준을 만족해야 합니다.

2. 성공 기준 2.3.2 세 번의 깜박임

(레벨 AAA)

웹 페이지는 어떤 1초 기간 동안 3회 이상 깜박이는 콘텐츠를 포함해서는 안 됩니다.

아래와 같은 프로그램을 통해 콘텐츠가 초당 몇 회 깜빡이는지도 확인할 수 있습니다.

Photosensitive Epilepsy Analysis Tool (PEAT) - TRACE RERC

3. 성공 기준 2.3.3 상호작용으로 인한 애니메이션

(레벨 AAA)

상호작용으로 인해 발생하는 모션 애니메이션은 비활성화할 수 있어야 합니다. 단, 애니메이션이 기능이나 전달되는 정보에 필수적인 경우는 예외입니다.

4. 프론트엔드 개발자를 위한 실제 적용 방법

4.1 깜박임 경고 시스템 구현
틱톡 광과민성 발작 경고 및 모두 건너뛰기 기능 제공 이미지 (출처:틱톡 공식 사이트)
  • 콘텐츠에 깜박이는 요소가 포함된 경우, 사용자에게 경고 메시지 표시
4.2 애니메이션 비활성화 옵션
  • 사용자가 애니메이션을 끌 수 있는 토글 스위치 제공
  • 사용자 선택을 로컬 스토리지에 저장하여 설정 유지
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>애니메이션 제어 예시</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        margin: 0;
        padding: 0;
        background-color: #f0f0f0;
      }
      header {
        background-color: #333;
        color: white;
        padding: 10px 20px;
        display: flex;
        justify-content: space-between;
        align-items: center;
      }
      .toggle-switch {
        position: relative;
        display: inline-block;
        width: 60px;
        height: 34px;
      }
      .toggle-switch input {
        opacity: 0;
        width: 0;
        height: 0;
      }
      .slider {
        position: absolute;
        cursor: pointer;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: #ccc;
        transition: 0.4s;
        border-radius: 34px;
      }
      .slider:before {
        position: absolute;
        content: '';
        height: 26px;
        width: 26px;
        left: 4px;
        bottom: 4px;
        background-color: white;
        transition: 0.4s;
        border-radius: 50%;
      }
      input:checked + .slider {
        background-color: #2196f3;
      }
      input:checked + .slider:before {
        transform: translateX(26px);
      }
      .content {
        padding: 20px;
        text-align: center;
      }
      .animated-element {
        width: 100px;
        height: 100px;
        background-color: #3498db;
        margin: 20px auto;
        animation: pulse 2s infinite;
      }
      @keyframes pulse {
        0% {
          transform: scale(1);
        }
        50% {
          transform: scale(1.1);
        }
        100% {
          transform: scale(1);
        }
      }
      .no-animation {
        animation: none !important;
      }
    </style>
  </head>
  <body>
    <header>
      <h1>애니메이션 제어</h1>
      <div>
        <label class="toggle-switch">
          <input type="checkbox" id="animationToggle" />
          <span class="slider"></span>
        </label>
        애니메이션 켜기
      </div>
    </header>
 
    <div class="content">
      <div class="animated-element" id="animatedElement"></div>
      <p>위의 요소는 애니메이션이 적용된 예시입니다.</p>
    </div>
 
    <script>
      const animationToggle = document.getElementById('animationToggle');
      const animatedElement = document.getElementById('animatedElement');
 
      // 로컬 스토리지에서 애니메이션 설정 불러오기
      const isAnimationEnabled =
        localStorage.getItem('isAnimationEnabled') !== 'false';
      animationToggle.checked = isAnimationEnabled;
      updateAnimationState();
 
      // 토글 변경 시 이벤트 처리
      animationToggle.addEventListener('change', function () {
        localStorage.setItem('isAnimationEnabled', this.checked);
        updateAnimationState();
      });
 
      function updateAnimationState() {
        if (animationToggle.checked) {
          animatedElement.classList.remove('no-animation');
        } else {
          animatedElement.classList.add('no-animation');
        }
      }
    </script>
  </body>
</html>
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>애니메이션 제어 예시</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        margin: 0;
        padding: 0;
        background-color: #f0f0f0;
      }
      header {
        background-color: #333;
        color: white;
        padding: 10px 20px;
        display: flex;
        justify-content: space-between;
        align-items: center;
      }
      .toggle-switch {
        position: relative;
        display: inline-block;
        width: 60px;
        height: 34px;
      }
      .toggle-switch input {
        opacity: 0;
        width: 0;
        height: 0;
      }
      .slider {
        position: absolute;
        cursor: pointer;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: #ccc;
        transition: 0.4s;
        border-radius: 34px;
      }
      .slider:before {
        position: absolute;
        content: '';
        height: 26px;
        width: 26px;
        left: 4px;
        bottom: 4px;
        background-color: white;
        transition: 0.4s;
        border-radius: 50%;
      }
      input:checked + .slider {
        background-color: #2196f3;
      }
      input:checked + .slider:before {
        transform: translateX(26px);
      }
      .content {
        padding: 20px;
        text-align: center;
      }
      .animated-element {
        width: 100px;
        height: 100px;
        background-color: #3498db;
        margin: 20px auto;
        animation: pulse 2s infinite;
      }
      @keyframes pulse {
        0% {
          transform: scale(1);
        }
        50% {
          transform: scale(1.1);
        }
        100% {
          transform: scale(1);
        }
      }
      .no-animation {
        animation: none !important;
      }
    </style>
  </head>
  <body>
    <header>
      <h1>애니메이션 제어</h1>
      <div>
        <label class="toggle-switch">
          <input type="checkbox" id="animationToggle" />
          <span class="slider"></span>
        </label>
        애니메이션 켜기
      </div>
    </header>
 
    <div class="content">
      <div class="animated-element" id="animatedElement"></div>
      <p>위의 요소는 애니메이션이 적용된 예시입니다.</p>
    </div>
 
    <script>
      const animationToggle = document.getElementById('animationToggle');
      const animatedElement = document.getElementById('animatedElement');
 
      // 로컬 스토리지에서 애니메이션 설정 불러오기
      const isAnimationEnabled =
        localStorage.getItem('isAnimationEnabled') !== 'false';
      animationToggle.checked = isAnimationEnabled;
      updateAnimationState();
 
      // 토글 변경 시 이벤트 처리
      animationToggle.addEventListener('change', function () {
        localStorage.setItem('isAnimationEnabled', this.checked);
        updateAnimationState();
      });
 
      function updateAnimationState() {
        if (animationToggle.checked) {
          animatedElement.classList.remove('no-animation');
        } else {
          animatedElement.classList.add('no-animation');
        }
      }
    </script>
  </body>
</html>
4.3 리듀스드 모션(Reduced Motion) 미디어 쿼리 사용

리듀스드 모션(Reduced Motion)이란?

움직임을 줄이거나 제거하는 접근성 설정입니다. 대부분의 현대 운영 체제(Windows, macOS, iOS, Android 등)는 시스템 수준에서 모션 감소 옵션을 제공합니다. 사용자가 이 옵션을 활성화하면, 운영 체제는 애플리케이션과 웹사이트에 이 정보를 전달합니다.

@media (prefers-reduced-motion: no-preference) {
  /* 일반 모드에서의 애니메이션 스타일 */
  .animated-element {
    animation: pulse 2s infinite;
  }
}
 
@media (prefers-reduced-motion: reduce) {
  /* 동작 줄이기 모드에서의 스타일 */
  .animated-element {
    animation: none;
  }
}
@media (prefers-reduced-motion: no-preference) {
  /* 일반 모드에서의 애니메이션 스타일 */
  .animated-element {
    animation: pulse 2s infinite;
  }
}
 
@media (prefers-reduced-motion: reduce) {
  /* 동작 줄이기 모드에서의 스타일 */
  .animated-element {
    animation: none;
  }
}
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Motion Reduction 예시</title>
    <style>
      .card {
        width: 200px;
        padding: 20px;
        margin: 20px;
        background-color: white;
        border-radius: 8px;
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        transition: transform 0.3s ease;
      }
 
      /* 일반적인 호버 효과 */
      @media (prefers-reduced-motion: no-preference) {
        .card:hover {
          transform: scale(1.05) rotate(2deg);
        }
      }
 
      /* 모션 감소가 필요한 경우 */
      @media (prefers-reduced-motion: reduce) {
        .card:hover {
          /* 회전이나 확대 대신 간단한 테두리 색상 변경만 적용 */
          border: 2px solid #2196f3;
        }
      }
 
      .settings {
        margin: 20px;
      }
 
      /* 시각적 스타일 */
      body {
        font-family: Arial, sans-serif;
        background-color: #f5f5f5;
        padding: 20px;
      }
 
      button {
        padding: 8px 16px;
        background-color: #2196f3;
        color: white;
        border: none;
        border-radius: 4px;
        cursor: pointer;
      }
 
      button:hover {
        background-color: #1976d2;
      }
    </style>
  </head>
  <body>
    <div class="settings">
      <p>운영체제의 '모션 감소' 설정을 변경하여 효과를 테스트해보세요.</p>
    </div>
 
    <div class="card">
      <h2>호버 해보세요</h2>
      <p>모션 감소 설정에 따라 다른 효과가 적용됩니다.</p>
    </div>
 
    <script>
      // 모션 감소 설정 감지
      const motionQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
 
      motionQuery.addEventListener('change', () => {
        console.log(
          '모션 감소 설정이 변경됨:',
          motionQuery.matches ? '활성화' : '비활성화',
        );
      });
    </script>
  </body>
</html>
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Motion Reduction 예시</title>
    <style>
      .card {
        width: 200px;
        padding: 20px;
        margin: 20px;
        background-color: white;
        border-radius: 8px;
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        transition: transform 0.3s ease;
      }
 
      /* 일반적인 호버 효과 */
      @media (prefers-reduced-motion: no-preference) {
        .card:hover {
          transform: scale(1.05) rotate(2deg);
        }
      }
 
      /* 모션 감소가 필요한 경우 */
      @media (prefers-reduced-motion: reduce) {
        .card:hover {
          /* 회전이나 확대 대신 간단한 테두리 색상 변경만 적용 */
          border: 2px solid #2196f3;
        }
      }
 
      .settings {
        margin: 20px;
      }
 
      /* 시각적 스타일 */
      body {
        font-family: Arial, sans-serif;
        background-color: #f5f5f5;
        padding: 20px;
      }
 
      button {
        padding: 8px 16px;
        background-color: #2196f3;
        color: white;
        border: none;
        border-radius: 4px;
        cursor: pointer;
      }
 
      button:hover {
        background-color: #1976d2;
      }
    </style>
  </head>
  <body>
    <div class="settings">
      <p>운영체제의 '모션 감소' 설정을 변경하여 효과를 테스트해보세요.</p>
    </div>
 
    <div class="card">
      <h2>호버 해보세요</h2>
      <p>모션 감소 설정에 따라 다른 효과가 적용됩니다.</p>
    </div>
 
    <script>
      // 모션 감소 설정 감지
      const motionQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
 
      motionQuery.addEventListener('change', () => {
        console.log(
          '모션 감소 설정이 변경됨:',
          motionQuery.matches ? '활성화' : '비활성화',
        );
      });
    </script>
  </body>
</html>
일반 모드
동작 줄이기 모드
  1. Mac에서 동작 줄이기 컨트롤하기

    시스템 설정 > 손쉬운 사용 > 디스플레이 > 동작 줄이기
  2. Window에서 동작 줄이기 컨트롤하기

    설정 > 접근성 > 시각 효과 > 애니메이션 효과
3.3 가이드라인 2.2 충분한 시간 제공3.5 가이드라인 2.4 내비게이션 용이성