iBetter Books
수정

도입 스토리

"접근성 오류가 릴리스 직전에 발견됐어요." 팀장이 말했습니다. "스테이징에서야 알았는데, 개발 중에 미리 알 수 없나요?"

박멘토가 답했습니다. "린팅으로 가능해요. ESLint 플러그인을 설정하면 코드를 작성하는 순간 IDE에서 경고가 떠요. alt 없는 이미지, 레이블 없는 인풋, 클릭 이벤트만 있는 div — 코드를 저장하기 전에 잡을 수 있어요."

핵심 개념 설명

eslint-plugin-jsx-a11y

React 프로젝트에서 JSX 접근성을 정적 분석하는 ESLint 플러그인입니다.

npm install --save-dev eslint-plugin-jsx-a11y
// .eslintrc.jsmodule.exports = {  extends: [    'react-app',    'plugin:jsx-a11y/recommended'  // 권장 규칙 모두 활성화  ],  plugins: ['jsx-a11y'],  rules: {    // 특정 규칙 강도 조정    'jsx-a11y/alt-text': 'error',          // alt 없음: 오류    'jsx-a11y/label-has-associated-control': 'error',    'jsx-a11y/click-events-have-key-events': 'warn',  // 클릭 이벤트만 있음: 경고    'jsx-a11y/no-static-element-interactions': 'warn',  }};

주요 규칙 목록

규칙 탐지 내용 기본 수준
alt-text <img> alt 속성 누락 error
label-has-associated-control 레이블-입력 연결 미흡 error
button-has-type <button> type 속성 누락 warn
click-events-have-key-events 클릭 이벤트 있는 요소에 키보드 이벤트 없음 warn
no-autofocus autofocus 사용 warn
no-distracting-elements <marquee>, <blink> 사용 error
heading-has-content 비어 있는 헤딩 error
anchor-is-valid 유효하지 않은 <a> 사용 error
aria-role 유효하지 않은 role 값 error
aria-props 유효하지 않은 aria 속성 error

ESLint 경고 예시

// 오류: alt 없음
<img src="product.jpg" />
// eslint-plugin-jsx-a11y: "img elements must have an alt prop"

// 올바름
<img src="product.jpg" alt="노트북 Pro 제품 이미지" />

// 경고: div에 클릭 이벤트만 있음
<div onClick={handleClick}>클릭</div>
// "Static HTML elements with event handlers require a role"

// 올바름
<button type="button" onClick={handleClick}>클릭</button>

// 오류: label 연결 없는 input
<label>이름</label>
<input type="text" />
// "Form label must be associated with a control"

// 올바름
<label htmlFor="name">이름</label>
<input type="text" id="name" />

HTML/Vanilla JS 프로젝트의 린팅

React 없이 HTML을 직접 작성할 때는 다른 도구를 사용합니다.

axe-linter (VS Code 확장):

  • VS Code Marketplace에서 "axe Accessibility Linter" 설치
  • HTML, JSX, Vue 파일에서 실시간 접근성 경고

htmlhint + accessibility 규칙:

npm install --save-dev htmlhint
// .htmlhintrc{  "alt-require": true,  "attr-value-not-empty": true,  "id-unique": true,  "title-require": true}

Stylelint로 CSS 접근성 검사

npm install --save-dev stylelint stylelint-a11y
// .stylelintrc{  "plugins": ["stylelint-a11y"],  "rules": {    "a11y/no-outline-none": true,  // outline: none 금지    "a11y/no-display-none": [true, {"severity": "warning"}],    "a11y/font-size-is-readable": true,    "a11y/line-height-is-vertical-rhythmed": true  }}

단계별 실습

따라하기: React 프로젝트에 jsx-a11y 설치

# Create React Appcd my-react-appnpm install --save-dev eslint-plugin-jsx-a11y# package.json의 eslintConfig 수정
// package.json{  "eslintConfig": {    "extends": [      "react-app",      "react-app/jest",      "plugin:jsx-a11y/recommended"    ],    "plugins": ["jsx-a11y"]  }}

VS Code에서 ESLint 확장 프로그램을 설치하면 코드 작성 중 즉시 경고를 확인할 수 있습니다.

변형하기: 엄격 모드 적용

// .eslintrc.js — 엄격한 접근성 규칙module.exports = {  extends: [    'plugin:jsx-a11y/strict'  // recommended보다 엄격  ],  rules: {    // 커스텀 예외 — 이미 다른 방법으로 처리된 경우    'jsx-a11y/no-autofocus': 'off',  // 모달에서는 허용  }};

정리와 확인

핵심 내용 요약

  • eslint-plugin-jsx-a11y: React JSX 접근성 정적 분석
  • plugin:jsx-a11y/recommended: 권장 규칙, strict는 더 엄격
  • 주요 규칙: alt-text, label-has-associated-control, anchor-is-valid
  • axe Accessibility Linter: VS Code에서 HTML/JSX 실시간 경고
  • Stylelint: outline: none 같은 CSS 접근성 문제 탐지

확인 문제

문제 1. jsx-a11y/click-events-have-key-events 규칙이 경고하는 상황은?

<div onClick={fn}>처럼 클릭 이벤트만 있고
onKeyDown, onKeyPress, onKeyUp 이벤트가 없는 경우입니다.
키보드 사용자가 접근할 수 없음을 의미합니다.

문제 2. ESLint로 접근성 오류를 잡는 것의 한계는?

정적 분석이므로 런타임 동작(동적 ARIA 업데이트, 포커스 이동, Live Region)은 검사할 수 없습니다.
또한 레이블이 존재하는지만 확인하고, 레이블 내용이 적절한지는 판단하지 못합니다.

다음 챕터에서는 Storybook과 디자인 시스템에서 접근성을 컴포넌트 수준에서 관리하는 방법을 다룹니다.