
수동 및 자동 테스트를 함께 활용하는 접근성 프로그램의 이점 — 2026년 12주 디자인 시스템
12주차 디자인 시스템 커버리지는 접근성 전략부터 컴포넌트 아키텍처, UX 의사결정까지 넓은 범위를 다루었습니다. Deque의 접근성 테스트 관련 글은 Axe DevTools for Web, Axe DevTools Extension, Axe Monitor 등의 도구가 로컬, PR, CI/CD… 개발자가 바로 활용할 수 있도록 정리했습니다.


모달 vs. 별도 페이지: UX 의사결정 트리

수수료 부담 주체를 정하는 인터페이스 디자인
output 요소를 활용해 수수료를 별도로 표시하고 체크박스로 입력 금액 위에 수수료를 추가할지 선택하게 했습니다. 체크박스 레이블링은 예상보다 까다로웠는데, 'you pay' 대 'receiver pays' 방식이 어색하게 느껴져 최종적으로 'Add on top'과 금액 입력란 아래 'Recipient receives X USDC' 표시를 조합하는 방식이 의도를 더 자연스럽게 전달했습니다. 두 번째 madlibs 스타일 인터페이스는 동일한 로직에 문장 형태의 폼 패턴을 적용한 실험적 시도로, Sara Soueidan의 커스텀 체크박스 및 라디오 스타일링 기법과 Firefox에서 아직 지원되지 않는 field-sizing CSS 속성을 활용했습니다. fieldset과 legend 요소는 수수료 컨트롤에 의미론적 그룹화를 제공하며, 전체 높이 그라디언트 배경을 사용할 때는 background-attachment: fixed를 권장합니다.
Eleventy로 Heading Anchor 만들기
cheerio를 사용해 HTML 출력물을 파싱하고 .Post :where(h2, h3, h4)[id]:not([data-ha-exclude]) 선택자로 헤딩을 찾아, 시각적으로 숨겨진 접근 가능한 앵커 링크와 CSS Anchor Positioning(anchor-name 및 position-anchor 속성)으로 스타일링된 aria-hidden 플레이스홀더 span을 삽입합니다. 스타일링은 h2, h3, h4 크기에 맞는 세 가지 CSS 규칙만 필요하며, CSS Anchor Positioning을 지원하지 않는 브라우저를 위한 @supports 폴백으로 절대 위치 지정을 사용합니다. CSS Anchor Positioning은 현재 Baseline 2026에 해당합니다. 웹 컴포넌트와의 주요 트레이드오프는 cheerio가 헤드리스로 동작하기 때문에 JavaScript 방식의 정확한 오프셋 기반 폴백을 구현할 수 없다는 점이지만, CSS 폴백은 이 개인 사이트에 충분합니다. 결과적으로 모든 CSS와 JavaScript가 인라인 처리되어 블로그 포스트 전체 용량이 약 25 KB에 불과합니다.
useEffect 함수에 이름을 붙이세요
useEffect의 익명 화살표 함수를 named function expression, 예컨대 useEffect(function connectToInventoryWebSocket() {...}, [warehouseId])으로 교체하면 별도의 도구 없이도 즉각적인 가독성과 디버깅 이점을 얻을 수 있다고 주장합니다. Named effect는 스택 트레이스와 React DevTools 프로파일러 출력에서 'anonymous' 대신 함수 이름으로 표시되어 Sentry 같은 도구에서의 오류 추적이 훨씬 빠릅니다. 가독성 외에도 이름 짓기 자체가 설계 결함 감지기 역할을 합니다. 'and'나 'also' 없이는 이름을 붙이기 어렵다면 해당 effect가 무관한 두 가지 작업을 하고 있을 가능성이 높아 분리가 필요합니다. 마찬가지로 syncDerivedValue 같은 모호한 이름은 derived state나 이벤트 핸들러에 속해야 할 로직이 effect 안에 있다는 신호입니다. 이 기법은 cleanup 함수에도 적용되며 useCallback, useMemo에도 동일하게 효과적입니다. 저자의 실용적 공식: effect가 자체 상태를 관리하고 재사용 가능성이 있다면 custom hook으로 추출하고, 연관 상태 없는 단일 사용이라면 인라인으로 이름을 붙이면 됩니다. React 19의 Actions, use(), Server Components는 실제로 effect가 필요한 경우를 더욱 줄여줍니다.
2026년에 Data Table을 직접 코딩해서는 안 된다
createTableSchema 선언 하나로 컬럼 정의, 필터 필드, 필터 스키마, 시트 필드를 자동 생성하는 단일 진실 소스 테이블 스키마 중심으로 재구축하여, 기존에 다섯 개의 파일이 필요했던 구조를 하나로 통합했습니다. BYOS(Bring Your Own Store) 아키텍처는 공통 StoreAdapter 인터페이스를 구현하는 세 가지 플러그인형 상태 어댑터(Memory, nuqs, zustand)를 도입하여 단 한 줄의 코드 변경으로 상태 레이어를 교체할 수 있게 합니다. 배포는 Tailwind v4로 마이그레이션된 shadcn 레지스트리를 통해 npx shadcn@latest add로 설치 가능한 9개의 블록으로 처리되어 npm 패키지 게시가 불필요합니다. npx skills add로 설치 가능한 agent skill을 통해 AI 코딩 도구가 프로젝트 구조를 이해하고 적절한 블록을 설치하며 자연어 대화로 스키마 생성과 상태 어댑터 연결을 자동으로 수행합니다. Supabase PostgreSQL과 연동된 Drizzle ORM 통합과 SQL injection 테스트 스위트를 포함한 39개의 테스트 파일이 프로덕션 수준의 완성도를 뒷받침합니다.
3월 CSS 8강: CSS Grid 대결
border-radius를 활용한 아바타 클리핑, 그라디언트 텍스트 페이드를 포함한 벤토 스타일 테스티모니얼 그리드 레이아웃입니다. 참가자들이 사용한 주요 기법으로는 CSS Grid template areas, grid-column 및 grid-row span 배치, 배경색 지정을 위한 nth-child 선택자, 카드 내부 레이아웃의 flexbox, 픽셀 정확도를 위한 font-size 조정이 눈에 띕니다. 결과는 Scott이 Chris를 92% 대 81%로, Kyle이 Julia를 96% 대 89%로, Wes가 Adam을 99.68% 대 87%로, Josh가 Kevin을 97%로 제압하며 Kyle, Scott, Wes, Josh가 4강에 진출했습니다.
수동 및 자동 테스트를 함께 활용하는 접근성 프로그램의 이점
3월 CSS 8강: CSS Grid 대결
border-radius를 활용한 아바타 클리핑, 그라디언트 텍스트 페이드를 포함한 벤토 스타일 테스티모니얼 그리드 레이아웃입니다. 참가자들이 사용한 주요 기법으로는 CSS Grid template areas, grid-column 및 grid-row span 배치, 배경색 지정을 위한 nth-child 선택자, 카드 내부 레이아웃의 flexbox, 픽셀 정확도를 위한 font-size 조정이 눈에 띕니다. 결과는 Scott이 Chris를 92% 대 81%로, Kyle이 Julia를 96% 대 89%로, Wes가 Adam을 99.68% 대 87%로, Josh가 Kevin을 97%로 제압하며 Kyle, Scott, Wes, Josh가 4강에 진출했습니다.모달 vs. 별도 페이지: UX 의사결정 트리
수수료 부담 주체를 정하는 인터페이스 디자인
output 요소를 활용해 수수료를 별도로 표시하고 체크박스로 입력 금액 위에 수수료를 추가할지 선택하게 했습니다. 체크박스 레이블링은 예상보다 까다로웠는데, 'you pay' 대 'receiver pays' 방식이 어색하게 느껴져 최종적으로 'Add on top'과 금액 입력란 아래 'Recipient receives X USDC' 표시를 조합하는 방식이 의도를 더 자연스럽게 전달했습니다. 두 번째 madlibs 스타일 인터페이스는 동일한 로직에 문장 형태의 폼 패턴을 적용한 실험적 시도로, Sara Soueidan의 커스텀 체크박스 및 라디오 스타일링 기법과 Firefox에서 아직 지원되지 않는 field-sizing CSS 속성을 활용했습니다. fieldset과 legend 요소는 수수료 컨트롤에 의미론적 그룹화를 제공하며, 전체 높이 그라디언트 배경을 사용할 때는 background-attachment: fixed를 권장합니다.Eleventy로 Heading Anchor 만들기
cheerio를 사용해 HTML 출력물을 파싱하고 .Post :where(h2, h3, h4)[id]:not([data-ha-exclude]) 선택자로 헤딩을 찾아, 시각적으로 숨겨진 접근 가능한 앵커 링크와 CSS Anchor Positioning(anchor-name 및 position-anchor 속성)으로 스타일링된 aria-hidden 플레이스홀더 span을 삽입합니다. 스타일링은 h2, h3, h4 크기에 맞는 세 가지 CSS 규칙만 필요하며, CSS Anchor Positioning을 지원하지 않는 브라우저를 위한 @supports 폴백으로 절대 위치 지정을 사용합니다. CSS Anchor Positioning은 현재 Baseline 2026에 해당합니다. 웹 컴포넌트와의 주요 트레이드오프는 cheerio가 헤드리스로 동작하기 때문에 JavaScript 방식의 정확한 오프셋 기반 폴백을 구현할 수 없다는 점이지만, CSS 폴백은 이 개인 사이트에 충분합니다. 결과적으로 모든 CSS와 JavaScript가 인라인 처리되어 블로그 포스트 전체 용량이 약 25 KB에 불과합니다.useEffect 함수에 이름을 붙이세요
useEffect의 익명 화살표 함수를 named function expression, 예컨대 useEffect(function connectToInventoryWebSocket() {...}, [warehouseId])으로 교체하면 별도의 도구 없이도 즉각적인 가독성과 디버깅 이점을 얻을 수 있다고 주장합니다. Named effect는 스택 트레이스와 React DevTools 프로파일러 출력에서 'anonymous' 대신 함수 이름으로 표시되어 Sentry 같은 도구에서의 오류 추적이 훨씬 빠릅니다. 가독성 외에도 이름 짓기 자체가 설계 결함 감지기 역할을 합니다. 'and'나 'also' 없이는 이름을 붙이기 어렵다면 해당 effect가 무관한 두 가지 작업을 하고 있을 가능성이 높아 분리가 필요합니다. 마찬가지로 syncDerivedValue 같은 모호한 이름은 derived state나 이벤트 핸들러에 속해야 할 로직이 effect 안에 있다는 신호입니다. 이 기법은 cleanup 함수에도 적용되며 useCallback, useMemo에도 동일하게 효과적입니다. 저자의 실용적 공식: effect가 자체 상태를 관리하고 재사용 가능성이 있다면 custom hook으로 추출하고, 연관 상태 없는 단일 사용이라면 인라인으로 이름을 붙이면 됩니다. React 19의 Actions, use(), Server Components는 실제로 effect가 필요한 경우를 더욱 줄여줍니다.2026년에 Data Table을 직접 코딩해서는 안 된다
createTableSchema 선언 하나로 컬럼 정의, 필터 필드, 필터 스키마, 시트 필드를 자동 생성하는 단일 진실 소스 테이블 스키마 중심으로 재구축하여, 기존에 다섯 개의 파일이 필요했던 구조를 하나로 통합했습니다. BYOS(Bring Your Own Store) 아키텍처는 공통 StoreAdapter 인터페이스를 구현하는 세 가지 플러그인형 상태 어댑터(Memory, nuqs, zustand)를 도입하여 단 한 줄의 코드 변경으로 상태 레이어를 교체할 수 있게 합니다. 배포는 Tailwind v4로 마이그레이션된 shadcn 레지스트리를 통해 npx shadcn@latest add로 설치 가능한 9개의 블록으로 처리되어 npm 패키지 게시가 불필요합니다. npx skills add로 설치 가능한 agent skill을 통해 AI 코딩 도구가 프로젝트 구조를 이해하고 적절한 블록을 설치하며 자연어 대화로 스키마 생성과 상태 어댑터 연결을 자동으로 수행합니다. Supabase PostgreSQL과 연동된 Drizzle ORM 통합과 SQL injection 테스트 스위트를 포함한 39개의 테스트 파일이 프로덕션 수준의 완성도를 뒷받침합니다.12주차 디자인 시스템 커버리지는 접근성 전략부터 컴포넌트 아키텍처, UX 의사결정까지 넓은 범위를 다루었습니다. Deque의 접근성 테스트 관련 글은 Axe DevTools for Web, Axe DevTools Extension, Axe Monitor 등의 도구가 로컬, PR, CI/CD 파이프라인에서 프로그래밍적으로 감지 가능한 문제를 조기에 발견할 수 있지만, 안내 지침의 명확성, 인터랙션 순서, 보조 기술 공지의 맥락적 적합성 등 경험적 요소는 평가할 수 없음을 명확히 했습니다. WCAG 2.2 AA 또는 EN 301 549 기준으로 훈련된 평가자의 수동 테스트와 VPAT 증거를 위한 주기적 감사는 여전히 대체 불가합니다. Vitaly Friedman의 모달 vs. 별도 페이지 UX 의사결정 트리는 핵심 트레이드오프를 정리했습니다. 모달은 페이지 컨텍스트를 보존해야 하는 단일 독립 작업에, 복잡한 멀티스텝 워크플로우는 독립 페이지에 적합하며, drawer는 그 중간에 위치합니다. 엔터프라이즈 제품에서도 모달 내 wizard는 명시적으로 권장하지 않습니다.
OpenStatus는 data-table-filters 프로젝트를 하나의 createTableSchema 선언으로 컬럼 정의, 필터 필드, 시트 필드를 자동 생성하는 구조로 재구축하여 다섯 개 파일을 하나로 통합했습니다. BYOS(Bring Your Own Store) 아키텍처는 공통 StoreAdapter 인터페이스를 통해 세 가지 교체 가능한 상태 어댑터(Memory, nuqs, zustand)를 제공하며, shadcn 레지스트리 블록(npx shadcn@latest add)으로 배포됩니다. npx skills add로 설치 가능한 agent skill은 AI 코딩 도구가 자연어 대화를 통해 스키마를 생성하고 어댑터를 연결할 수 있게 합니다. Chen Hui Jing의 Circle CCTP 수수료 인터페이스 폼 디자인 사례 연구는 사용자 입력값을 자동으로 변경하지 않아야 하는 이유를 보여주고, HTML output 요소, fieldset/legend 의미론, madlibs 스타일 인터페이스가 각각 어떤 커뮤니케이션 목표를 달성하는지 보여주었습니다.
- Axe DevTools 자동화는 SDLC 초기에 프로그래밍적으로 감지 가능한 접근성 문제를 발견하지만, WCAG 2.2 AA 적합성 및 VPAT 증거에 필요한 경험적 요소의 수동 평가를 대체할 수 없습니다.
- OpenStatus의 createTableSchema 패턴은 컬럼 정의, 필터 필드, 시트 필드를 단일 선언으로 통합하고, BYOS StoreAdapter 인터페이스로 상태 레이어를 한 줄로 교체할 수 있으며 shadcn 레지스트리 블록으로 배포됩니다.
- 모달은 페이지 컨텍스트를 보존하는 단일 독립 작업에 적합하고, 복잡한 멀티스텝 워크플로우와 빈번한 상호 참조는 독립 페이지에 맞습니다. 엔터프라이즈 제품에서도 모달 내 wizard는 명시적으로 권장되지 않습니다.