아티클

Swiper 라이브러리의 접근성 개선을 위한 수동 적용 방법 - 2부

엔비전스 접근성 2024-09-24 16:30:08

안녕하세요, 엔비전스입니다.

이번 아티클에서는 Swiper 라이브러리를 활용하여 웹 콘텐츠의 접근성을 개선하는 방법을 2부로 나누어 소개하고 있습니다. 1부에서는 Swiper 라이브러리의 기본 접근성 기능과 이를 커스터마이즈하는 방법을 중점적으로 다루었습니다. 자동 재생 설정, 내비게이션 및 페이지네이션 요소의 접근성 적용, 슬라이드 그룹화 및 레이블링, 접근성 옵션의 활성화와 비활성화 등을 통해 Swiper의 기본 기능을 활용하여 접근성을 높이는 방법을 설명했습니다.

2부에서는 Swiper 라이브러리의 접근성을 더욱 향상시키기 위해 개발자가 수동으로 추가해야 하는 기능들을 다루겠습니다. 자동 재생 슬라이드에서의 재생/정지 버튼 구현, 슬라이드 전환 시 초점 관리, 가려진 슬라이드 요소에 대한 접근 방지 등 구체적인 기술들을 소개할 예정입니다. 이러한 방법을 통해 Swiper를 사용하는 모든 사용자가 원활하게 콘텐츠를 탐색하고 이용할 수 있도록 도울 것입니다.

 

1. 재생/정지 버튼의 수동 구현

자동 재생 기능이 활성화된 Swiper 슬라이드는 사용자가 컨트롤할 수 있는 재생/정지 버튼을 제공해야 합니다. 특히, 접근성을 고려할 때 이 버튼은 스크린 리더 사용자와 키보드 사용자도 쉽게 접근하고 사용할 수 있도록 구현해야 합니다.

1.1. 기본 구조

재생/정지 버튼은 슬라이드 콘텐츠 앞에 위치시켜야 합니다. 이렇게 하면 키보드 사용자나 모바일 웹 스크린 리더 사용자가 슬라이더에 접근하기 전에 슬라이드를 정지시킬 수 있으므로, 슬라이드 전환으로 인한 초점 잃어버림을 방지할 수 있습니다.

<div class="swiper-container">
    <button class="swiper-button-play-pause" aria-label="슬라이드 쇼 제어">정지</button>
    <div class="swiper">
        <!-- 슬라이드 내용 -->
    </div>
</div>
        

 

1.2. 재생/정지 기능 구현

재생/정지 버튼은 Swiper의 autoplay 기능과 연동하여, 사용자가 버튼을 클릭할 때마다 슬라이드 쇼를 시작하거나 멈추도록 구현해야 합니다. 또한, 버튼의 상태에 따라 적절한 aria-label을 업데이트하여 스크린 리더 사용자에게 현재 상태를 알릴 수 있도록 해야 합니다.

const swiper = new Swiper('.swiper', {
    autoplay: {
        delay: 3000,
        disableOnInteraction: false,
    },
    // 다른 옵션들...
});

const swiperWrapper = document.querySelector('.swiper-wrapper');
const playPauseButton = document.querySelector('.swiper-button-play-pause');

playPauseButton.addEventListener('click', function() {
    if (swiper.autoplay.running) {
        swiper.autoplay.stop();
        swiperWrapper.setAttribute('aria-live', 'polite');
        this.textContent = '재생';
        this.setAttribute('aria-label', '슬라이드 쇼 재생');
    } else {
        swiper.autoplay.start();
        swiperWrapper.setAttribute('aria-live', 'off');
        this.textContent = '정지';
        this.setAttribute('aria-label', '슬라이드 쇼 정지');
    }
});
        

1.3. 접근성 고려 사항

  • 버튼 위치: 앞에서 설명한 것처럼, 재생/정지 버튼은 슬라이드 콘텐츠 앞에 위치시켜, 키보드 사용자나 스크린 리더 사용자가 슬라이드에 접근하기 전에 정지할 수 있도록 해야 합니다.
  • aria-label: 버튼의 텍스트가 변경될 때마다 aria-label 속성도 함께 업데이트하여 스크린 리더 사용자가 현재 버튼의 상태를 정확하게 인식할 수 있도록 해야 합니다.

이러한 재생/정지 버튼 구현은 Swiper 슬라이더의 접근성을 크게 향상시키며, 특히 자동 재생 슬라이드의 경우 모든 사용자가 컨트롤을 쉽게 할 수 있도록 돕습니다.

 

2. 슬라이드 전환 시 초점 관리

2.1. 초점 이동의 중요성

슬라이드가 전환될 때, 업데이트된 콘텐츠들이 상호작용이 가능한 버튼이나 링크와 같은 요소인 경우 해당 요소로 초점을 이동시켜 주면 연속적인 탐색이 가능합니다.

2.2. 기본 초점 관리 구현

슬라이드 전환 후 초점을 새 슬라이드의 첫 번째 포커스 가능한 요소로 이동시키는 방법은 Swiper의 slideChangeTransitionEnd 이벤트를 활용하여 구현할 수 있습니다. 예를 들어, 다음과 같이 코드를 작성할 수 있습니다:

swiper.on('slideChangeTransitionEnd', function () {
    const activeSlide = this.slides[this.activeIndex];
    const firstFocusableElement = activeSlide.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
    
    if (firstFocusableElement) {
        firstFocusableElement.focus();
    }
});
        

2.3. 접근성 고려 사항

  • 자동 재생 슬라이드: 슬라이드가 자동 재생되는 동안에는 초점이 자동으로 이동해서는 안 됩니다. 사용자가 이전 또는 다음, 페이지네이션 등을 눌러 슬라이드 콘텐츠가 변경되었을 때 초점이 이동하면 됩니다.

이러한 초점 관리 기능을 구현하면, 슬라이드 전환 시 사용자 경험을 크게 향상시킬 수 있으며, 특히 키보드 사용자와 스크린 리더 사용자를 위한 접근성을 크게 개선할 수 있습니다.

 

3. 가려진 슬라이드 요소 접근 방지

화면 상에 슬라이드가 표시될 때, 가려진 슬라이드에 대한 접근성 대응을 하지 않으면 화면에 보이지 않는 다른 슬라이드에 접근될 수 있습니다. 이는 슬라이드가 화면에서 보이지 않더라도 여전히 DOM(Document Object Model) 내에서 존재하며, 포커스 가능한 요소를 포함하고 있기 때문입니다. 이러한 요소들이 여전히 키보드 탐색이나 스크린 리더 접근 대상으로 남아 있게 되어, 사용자가 의도치 않게 가려진 슬라이드에 초점을 맞추게 되는 문제가 발생할 수 있습니다. 이러한 문제는 특히 키보드 사용자와 스크린 리더 사용자에게 혼란을 줄 수 있습니다.

이 섹션에서는 가려진 슬라이드 요소에 접근하지 못하도록 설정하는 방법을 설명합니다.

3.1. 가려진 슬라이드에 inert 속성 적용

inert 속성은 HTML 요소를 비활성화하여, 해당 요소와 그 자식 요소들이 포커스를 받을 수 없도록 만듭니다. 이 속성을 활용하여 현재 화면에 보이지 않는 슬라이드 요소에 접근하지 못하게 설정할 수 있습니다.

슬라이드 전환 시, slideChange 이벤트를 활용하여 활성화된 슬라이드 외의 모든 슬라이드에 inert 속성을 적용할 수 있습니다:

function updateInertAttribute(swiper) {
    swiper.slides.forEach((slide, index) => {
        if (index === swiper.activeIndex) {
            slide.removeAttribute('inert');
        } else {
            slide.setAttribute('inert', '');
        }
    });
}

swiper.on('slideChange', function () {
    updateInertAttribute(this);
});

// 초기 로드 시에도 적용
updateInertAttribute(swiper);
        

이 코드에서는 슬라이드 전환이 발생할 때마다, 현재 활성화된 슬라이드를 제외한 나머지 슬라이드에 inert 속성을 추가합니다. 이를 통해 보이지 않는 슬라이드 요소들이 키보드 탐색이나 스크린 리더 접근 대상에서 제외됩니다.

 

4. 슬라이드 내 포커스 이벤트 관리

4.1. 포커스 이벤트와 자동 재생 제어

사용자가 슬라이드 내에서 특정 요소에 포커스를 두는 경우, 자동 재생을 일시적으로 중단시켜야 합니다. 그렇게 하지 않으면 슬라이드가 전환되면서 초점을 잃어버리게 됩니다.

다음 예제는 Swiper의 focusin 및 focusout 이벤트를 활용하여, 슬라이드 내 포커스 상태에 따라 자동 재생을 제어하는 방법을 보여줍니다:

let wasPlayingBeforeFocus = true;

swiper.el.addEventListener('focusin', (e) => {
    if (e.target.closest('.swiper-slide')) {
        wasPlayingBeforeFocus = swiper.autoplay.running;
        if (swiper.autoplay.running) {
            swiper.autoplay.stop();
            swiperWrapper.setAttribute('aria-live', 'polite');
            playPauseButton.textContent = '재생';
            playPauseButton.setAttribute('aria-label', '슬라이드 쇼 재생');
        }
    }
});

swiper.el.addEventListener('focusout', (e) => {
    if (!swiper.el.contains(e.relatedTarget) && wasPlayingBeforeFocus) {
        swiper.autoplay.start();
        swiperWrapper.setAttribute('aria-live', 'off');
        playPauseButton.textContent = '정지';
        playPauseButton.setAttribute('aria-label', '슬라이드 쇼 정지');
    }
});
        

이 코드는 사용자가 슬라이드 내 특정 요소에 포커스를 두면 자동 재생이 멈추고, 포커스가 슬라이드를 벗어나면 자동 재생이 다시 시작되도록 설정합니다. 또한, aria-live 속성을 사용하여 스크린 리더가 슬라이드 상태를 적절히 알릴 수 있도록 조정합니다.

이러한 포커스 이벤트 관리를 통해, 슬라이드의 자동 전환으로 인해 사용자가 콘텐츠를 놓치지 않도록 하며, 전체적인 사용자 경험을 향상시킬 수 있습니다.

 

5. 페이지네이션 요소의 수동 접근성 추가

Swiper 라이브러리의 기본 페이지네이션을 사용하는 경우, 접근성 옵션이 활성화되어 있는 한, 각 페이지네이션 불릿에 role="button" 속성, tabindex="0", 그리고 Enter 및 Space 키에 대한 키보드 접근성이 자동으로 적용됩니다. 또한, 각 페이지네이션 불릿에는 기본적으로 "Go to slide 1", "Go to slide 2"와 같은 aria-label이 자동으로 설정되며, 선택된 페이지네이션 불릿에는 aria-current="true" 속성이 추가됩니다.

렌더 불릿을 이용하여 페이지네이션을 커스텀하는 경우, 이러한 접근성 속성을 수동으로 추가해야 할 필요가 있습니다. 이 때에도 접근성 옵션을 끄는 경우에는 키보드 접근성까지 수동으로 구현해야 하며, 접근성 옵션을 켠 상태에서는 tabindex와 키보드 접근성, 그리고 aria-current 속성은 자동으로 추가됩니다. 이 섹션에서는 이러한 접근성 속성을 수동으로 추가하는 방법을 설명합니다.

5.1. 수동 접근성 속성 추가

페이지네이션 불릿 요소에 추가적인 접근성 속성을 수동으로 설정하여, 스크린 리더가 올바르게 내용을 전달하도록 할 수 있습니다. 예를 들어, aria-label 속성을 사용하여 각 불릿의 역할을 명확히 하거나, role 속성을 설정하여 불릿을 버튼으로 인식하게 할 수 있습니다.

다음은 Swiper의 renderBullet 옵션을 사용하여 페이지네이션 불릿 요소에 접근성 속성을 수동으로 추가하는 방법의 예시입니다:

const swiper = new Swiper('.swiper', {
    pagination: {
        el: '.swiper-pagination',
        clickable: true,
        renderBullet: function (index, className) {
            return `${index + 1}`;
        },
    },
});
        

이 예제에서는 각 페이지네이션 불릿에 role="button" 속성과 aria-label 속성을 추가하여, 스크린 리더가 불릿의 목적을 명확하게 전달하도록 설정합니다.

또한, 접근성 옵션이 꺼져 있는 경우 버튼 태그가 아닌 경우 Enter 및 Space 키로 페이지네이션을 활성화할 수 있도록 이벤트 리스너를 추가해야 합니다:

document.querySelectorAll('.swiper-pagination-bullet').forEach(bullet => {
    bullet.addEventListener('keydown', function(event) {
        if (event.key === 'Enter' or event.key === ' ') {
            event.preventDefault();
            this.click();
        }
    });
});
        

접근성 옵션이 꺼져 있는 경우, 선택된 페이지네이션 불릿에 대해서는 aria-current="true" 속성을 추가하여, 스크린 리더 사용자에게 현재 위치를 명확히 전달할 수 있습니다.

swiper.on('paginationUpdate', function () {
    this.pagination.bullets.forEach((bullet, index) => {
        if (index === this.activeIndex) {
            bullet.setAttribute('aria-current', 'true');
        } else {
            bullet.removeAttribute('aria-current');
        }
    });
});
        

이러한 수동 접근성 속성 추가를 통해 페이지네이션 요소의 접근성을 더욱 향상시킬 수 있으며, 특히 스크린 리더 사용자가 슬라이드를 탐색할 때 더 나은 사용자 경험을 제공할 수 있습니다.

댓글 0
댓글을 작성하려면 해주세요.