LikeLion-FE-React-Project04 / project-repo

멋쟁이사자처럼 프론트엔드 스쿨 4기에서 Final Project로 진행한 Karly입니다.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[FEATURE] 캐로셀 2차 리팩토링

ssw6750 opened this issue · comments

📝 TASK 개요

💬 접근성 준수의 대전제는 “차별 없는 적절한 대체 수단 제공”이다. 현재까지 구현한 캐러셀 접근성은 4원칙 중 “운용의 용이성” 문제 해결만 신경쓴 것으로, “인식”, “이해” 등의 문제는 해결되지 않았다. (접근성 4원칙 = 인식, 운용, 이해, 견고)
동등하지 않은 정보를 제공하는 것은 제공하지 않는 것만 못하다. 정보는 누구에게나 동등하게 제공해야 한다.

캐로셀 접근성 향상

  • 기존 컬리 사이트 메인 캐로셀
    기존 컬리 메인캐로셀

자동 넘김 제어도 안될 뿐더러 화면에 보이지 않는 슬라이드도 모두 접근하고 심지어 내용조차 제대로 알 수 없다..!!

1. 현재 접근중인 컨텐츠가 캐로셀이라는 걸 알 수 있도록 정보 제공

  • 의미론적 관점에서 접근
  • 캐로셀이란 용어는 데이터에 대한 정보가 아닌 유저 인터페이스에 대한 정보이다.
  • 즉 캐로셀은 영역의 이름이 아닌 영역에 대한 부가 설명적인 정보이다.
 aria-label='메인 캐로셀'
 aria-roledescription='carousel'
 role='region'

2. 포커스 표시기가 눈에 보이도록 유지

  • outline-offset: -2px;추가하여 기존에 흐릿하던 포커싱을 잘 보이도록 개선

3. 자동 넘김을 일시 정지 할 수 있는 기능 제공

스와이퍼 속성에 autoplay={{ delay: 4000 }}를 추가하여 자동 넘김 기능 추가

const stop = (e) => {
    e.preventDefault();
    swiperRef.current.swiper.autoplay.stop();
  };
  const start = (e) => {
    e.preventDefault();
    swiperRef.current.swiper.autoplay.start();
  };

해당 event함수button에 부여하여 자동 넘김을 제어할 수 있도록 함

4. 보이지 않는 슬라이드는 접근 불가능 해야함

  • 메인 캐로셀 개선
    swiper의 isActive 속성을 활용하여 보이지 않는 슬라이더의 접근을 제어함
aria-hidden={isActive ? false : true}
tabIndex={isActive ? 'none' : -1}

해당 코드로 인해 스와이퍼에 활성화된 슬라이드(캐로셀에 보이는 하나의 슬라이드)만 접근 가능하다.

  • 상품 캐로셀 개선
    상품 캐로셀은 아이템이 4개씩 보여지기 때문에 swiper에서 제공하는 isActive 속성으로는 구현하기 어렵다고 판단함
const [focusableIndex, setFocusableIndex] = useState(0);
<div>
      ...
      <button
        ref={navigationPrevRef}
        aria-label="이전 항목 보기"
        className={classnames(classes.swiperPrevBtn, classes.swiperButton)}
        onClick={() => {
          setFocusableIndex((prev) => prev - 4);
        }}
      />
      <button
        ref={navigationNextRef}
        aria-label="다음 항목 보기"
        className={classnames(classes.swiperNextBtn, classes.swiperButton)}
        onClick={() => {
          setFocusableIndex((prev) => prev + 4);
        }}
      />
      ...
</div>

위 코드를 통하여 포커싱되는 슬라이드의 인덱싱을 저장함

  const productCards = productList.slice(0, 12).map((product, index) => (
    <SwiperSlide key={index}>
      <ProductCard
        product={product}
        isActive={focusableIndex <= index && index < focusableIndex + 4}
      />
    </SwiperSlide>
  ));

위 코드에서 isActive={focusableIndex <= index && index < focusableIndex + 4}으로 인해 상품 캐로셀에 보여지는 4개의 상품 카드만 isActivetrue로 받아옴, 이후 받아온 isActiveswiper의 isActive 속성 처럼 사용

forwardRef 사용해서 해결하려고 시도했으나 그러면 상품카드 내부의 장바구니 담기 버튼에는 여전히 접근이 가능하기 때문에 문제가 발생했음

5. 캐로셀 슬라이드가 넘어갔다면 사용자에게 알려줘야함

  • 메인캐로셀
    <div ref={notifyRef} aria-live="assertive" className="a11yHidden" />
    메시지를 알려주는 요소를 추가하고 숨김처리함
const [slideInfo, setSlideInfo] = useState(null);

useEffect(() => {
  if (slideInfo !== null) notifyRef.current.textContent = slideInfo;
}, [slideInfo]);

...
  if (isActive) {
    setSlideInfo(banner.title);
  }

swiperactive 요소가 바뀔때 slideInfo의 상태가 변경이 되고, useEffect가 이를 감지하여 notifyReftextContent를 변경하고 aria-live="assertive"가 이를 감지하여 textContent를 읽어주는 로직이다.

6. 실행화면

  • 메인 캐로셀
    메인캐로셀 웹접근성

  • 상품 캐로셀
    상품캐로셀 완벽

7. 레이아웃 버그 수정

뷰포트를 줄이면 메인 캐로셀 때문에 레이아웃이 무너지는 현상이 발생함.

  • 실제 컬리도 해당 버그 발생
    컬리버그1

  • 칼리 사이트 버그 수정
    컬리버그 고친거

✅ To Do 및 진행상황

  • 현재 접근중인 컨텐츠가 캐로셀이라는 걸 알 수 있도록 정보 제공
  • 포커스 표시기가 눈에 보이도록 유지
  • 자동 넘김을 일시 정지 할 수 있는 기능 제공
  • 보이지 않는 슬라이드는 접근 불가능 해야함
  • 캐로셀 슬라이드가 넘어갔다면 사용자에게 알려줘야함
  • 레이아웃 버그 수정