CS 퀴즈 문항 풀 대폭 확장 + 신규 5분야 + 'ALL'(전체 랜덤) 필터
요약CS 퀴즈(/quiz) 문항을 150→350(5분야×30 → 10분야×30+확장)으로 대폭 확장하고 분야 'ALL'(전체 랜덤) 필터를 추가했다. Wave A(인프라): QuizCategory enum 신규 5종 + Palette가 globals.css에 신규 5분야 CSS 변수(WCAG AA 직접 검증) 추가 + category-meta 아이콘/var 매핑. Wave B+C(콘텐츠): 신규 5분야 각 20문항 + 기존 5분야 각 30→50문항(HARD 불균형 보강), 전역 id 유니크 350, 병렬 Curator 10에이전트 산출. Wave D('ALL' 필터): getQuestionsByFilter/getRandomQuestions가 category: 'ALL' 수용, QuizStart PillRadioGroup 'ALL' prepend(신규 토큰 0). Wave E(테스트): +22 tests, 전역 1555 PASS. 교훈: 파일당 1에이전트 병렬화, 작은따옴표 내 영문 아포스트로피 구문 에러, within() 스코프 조회, 메타 필터 옵션 토큰 0 패턴. 프론트 전용, merge≠라이브.
목표
- CS 퀴즈(
/quiz) 문항을 150 → 350개로 대폭 확장한다 (5분야 × 30 → 10분야, 기존 5분야도 각 30→50문항 보강). - 신규 5분야(컴퓨터 구조·디자인 패턴·웹·보안·AI)를 추가하고 각 분야 CSS 토큰·아이콘을 WCAG AA 기준으로 정립한다.
- 분야 선택에 'ALL'(전체 랜덤) 필터를 추가해 사용자가 모든 분야를 섞어 퀴즈를 풀 수 있게 한다.
- 프론트 전용, 순수 데이터/UI 확장 — merge ≠ 라이브(재배포 후 라이브 검증은
quiz-ui-verification런북 이월에 합류).
배경
Sprint 215부터 구축된 CS 퀴즈는 Sprint 221~224에서 UI·접근성·UX가 정석화되었으나, 문항 풀은 여전히 5분야 × 30문항 = 150개로 제한적이었다. 사용자가 한 분야를 반복하면 금방 소진되고, 분야를 고정하지 않고 전체를 섞어 연습하는 시나리오도 불가했다.
Sprint 227은 이 두 갭을 동시에 해소한다:
- 분야 확장: 기존 네트워크·운영체제·데이터베이스·알고리즘·자료구조 5분야에 컴퓨터 구조·디자인 패턴·웹·보안·AI 5분야를 추가.
- 'ALL' 필터: 분야 선택 PillRadioGroup에 'ALL'(전체 랜덤) 옵션을 추가해 전 분야 350문항 풀에서 무작위 출제.
결정
D1. 신규 5분야 enum·CSS 토큰·아이콘 (Wave A)
QuizCategory enum에 5종 추가:
COMPUTER_ARCHITECTURE/DESIGN_PATTERN/WEB/SECURITY/AI
Palette가 globals.css에 신규 5분야 --quiz-cat-*-color / --quiz-cat-*-bg CSS 변수 20줄(라이트+다크)을 추가했다. WCAG AA 4.5:1+ 대비비를 직접 검증:
| 분야 | 라이트(전경) | 대비비 | 다크(전경) | 기존 5 hue와 구분 |
|---|---|---|---|---|
| arch | #B45309 | 4.81 | #FBBF24 | 앰버 톤 |
| dp | #BE185D | 5.78 | #F472B6 | 핑크 톤 |
| web | #4338CA | 7.56 | #818CF8 | 인디고 톤 |
| sec | #B91C1C | 6.19 | #F87171 | 레드 톤 |
| ai | #4D7C0F | 4.78 | #A3E635 | 라임 톤 |
category-meta.ts에 신규 5분야 lucide 아이콘(CircuitBoard / Shapes / Globe / ShieldCheck / BrainCircuit)과 var 슬러그 매핑 추가.
i18n categories 객체에 신규 5키(ko+en) + categories.ALL 키 추가.
D2. 대규모 콘텐츠 병렬 생성 (Wave B+C)
Curator 10에이전트를 병렬 구동해 파일당 1에이전트 방식으로 문항을 생성했다:
- 신규 5분야 각 20문항 (7E/7M/6H):
computer-architecture.ts/design-pattern.ts/web.ts/security.ts/ai.ts - 기존 5분야 각 30→50문항 (+20): 특히 HARD 불균형 보강(network HARD 4→17, os 5→17, database 7→17, 각 16E/17M/17H 목표)
index.ts ALL_QUESTIONS에 5분야 합산 → QUIZ_CATEGORIES 10분야, 전역 id 유니크 350개 달성.
통합 시 발견·수정: database.ts·os.ts 영문 텍스트에서 작은따옴표 문자열 내 미이스케이프 아포스트로피(Brewer's, process's) 2건 → 쌍따옴표로 전환해 구문 에러 해소.
D3. 'ALL' 필터 추가 (Wave D)
index.ts getQuestionsByFilter / getRandomQuestions가 category: QuizCategory | 'ALL'을 수용한다:
'ALL':ALL_QUESTIONS전체 풀에서 출제 (기존 난이도'ALL'패턴 미러링)- 기존 분야별 필터링 로직 무변경
QuizStart 분야 PillRadioGroup에 'ALL' 옵션을 prepend:
Shuffle아이콘 + primary 톤- 신규 디자인 토큰 0 —
getOptionStyle은'ALL'에undefined반환(기존 분야 카테고리 메타에 없는 옵션이므로 가드 처리) - 기본 선택값
'ALL'로 변경
page.tsx Session.category / start 파라미터에 'ALL' 전파. 저장 키는 ALL::difficulty 자동 생성. stats 집계는 'ALL' 키 무시(QUIZ_CATEGORY_META own-key 검증, 메타 모드).
D4. 테스트 전면 갱신 (Wave E)
| 테스트 파일 | 변경 내용 |
|---|---|
QuizStart.test | 전면 갱신 — 분야·난이도 두 '전체' 라벨 중복 → within() radiogroup 스코프 조회, 기본 분야 'ALL' 반영, ALL 분야 신규 4테스트 |
index.test | +5 — ALL 필터 동작 검증 |
data-integrity.test | 신규 +12 — 350문항 유니크 id·카테고리·bilingual 무결성 |
category-meta.test | 신규 5분야 var 슬러그 검증 |
page.test | 키 갱신(ALL 기본 선택 반영) |
전역: 1533 → 1555 tests (+22).
구현
총 atomic commit (start 66820e0):
| 커밋 | 에이전트 | 내용 |
|---|---|---|
229da66 | Palette + Herald | Wave A — QuizCategory +5, globals.css 20줄, category-meta 아이콘/var, i18n 신규 5키+ALL |
f8660d1 | Curator×10 + Herald | Wave B+C — 신규 5분야 각 20문항, 기존 5분야 각 +20(HARD 보강), index.ts ALL_QUESTIONS 통합, 아포스트로피 2건 수정 |
09dc639 | Herald | Wave D — getQuestionsByFilter/getRandomQuestions 'ALL' 수용, QuizStart 'ALL' prepend, page.tsx 전파, stats 'ALL' 무시 |
2912955 | Herald + Librarian | Wave E — 테스트 전면 갱신 +22, data-integrity.test 신규, ADR sprint-227 KR+EN, README 164→165 |
검증
- tsc: 오류 0 (아포스트로피 수정 포함)
- next lint (rtk proxy 실측): 0 errors / 487 warnings (전부 기존 인라인 토큰
var()경고, 신규 0) - jest: 152 suites / 1555 PASS (+22, 전 실패 0)
- 글로벌 커버리지: lines 88.03% / branches 79.37% (게이트 83/71 통과)
- quiz 컴포넌트·데이터: lines 100% / branches 98.59% (data-integrity
/* istanbul ignore */분기 제외) - next build: ✓
/[locale]/quiz84.8kB (Sprint 224 40.2kB → 증가: 350문항 bilingual 데이터가 클라이언트 번들에 포함되는 기존 아키텍처 특성, 하단 교훈 ⑤ 참조) - ADR 게이트: index count (sprint 165) / adr-en coverage (KR/EN 1:1) / adr-links 0 broken / doc-refs no broken
Critic 교차 리뷰
- 도구: Codex codex-cli 0.130.0,
codex review --base 66820e0 -c model=gpt-5.5 - 라운드: 2
R1 — [P2] 1건: 프론트 기본 분야 'ALL' + 신규 5분야가 백엔드 quiz-record DTO allowlist(기존 5분야)에서 거부 → 로그인 사용자 finish()의 saveResult(best-effort, 에러 swallow)가 조용히 실패해 best 기록 미저장·merge-up 누락. "these sessions appear to complete normally but their best records are never saved or merged up." → fcb1800에서 identity entity enum +5 / identity·gateway DTO allowlist = 10분야 + 'ALL' / 회귀 spec(gateway+12·identity+13)로 해소. DB 컬럼 varchar(30)이라 마이그레이션 불필요.
R2 — CLEAN (P-finding 0): "The changes type-check across the frontend, gateway, and identity service, and the updated category/ALL flow appears consistently propagated through data, UI, and persistence DTOs. I did not find a discrete introduced bug that would warrant an inline finding." (Codex가 frontend·gateway·identity tsc를 직접 실행해 확인.)
종합 판정: ✅ 머지 가능 — R1 P2(백엔드 allowlist 누락) 수정 후 R2 CLEAN. 전역 1555 PASS + 백엔드 회귀 spec, 커버리지·ADR 게이트 전 통과.