swwa-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +50 -0
  3. package/assets/alt-text-ko.json +7 -0
  4. package/assets/axe-rule-map.json +196 -0
  5. package/assets/certification.json +47 -0
  6. package/assets/kwcag22-checklist.md +123 -0
  7. package/assets/kwcag22.json +1688 -0
  8. package/assets/link-text-ko.json +8 -0
  9. package/assets/mobile-app-2.0.md +38 -0
  10. package/assets/sources.json +68 -0
  11. package/assets/wcag22.json +780 -0
  12. package/bin/swwa-mcp.mjs +15 -0
  13. package/dist/color/contrast.js +175 -0
  14. package/dist/color/contrast.js.map +1 -0
  15. package/dist/data/axe-map.js +32 -0
  16. package/dist/data/axe-map.js.map +1 -0
  17. package/dist/data/certification.js +54 -0
  18. package/dist/data/certification.js.map +1 -0
  19. package/dist/data/kwcag22.js +91 -0
  20. package/dist/data/kwcag22.js.map +1 -0
  21. package/dist/data/loader.js +18 -0
  22. package/dist/data/loader.js.map +1 -0
  23. package/dist/data/sources.js +44 -0
  24. package/dist/data/sources.js.map +1 -0
  25. package/dist/data/wcag22.js +44 -0
  26. package/dist/data/wcag22.js.map +1 -0
  27. package/dist/data/wordlists.js +40 -0
  28. package/dist/data/wordlists.js.map +1 -0
  29. package/dist/engine/browser-detect.js +44 -0
  30. package/dist/engine/browser-detect.js.map +1 -0
  31. package/dist/engine/browser.js +114 -0
  32. package/dist/engine/browser.js.map +1 -0
  33. package/dist/engine/static-worker.js +18 -0
  34. package/dist/engine/static-worker.js.map +1 -0
  35. package/dist/engine/static.js +139 -0
  36. package/dist/engine/static.js.map +1 -0
  37. package/dist/engine/url-guard.js +37 -0
  38. package/dist/engine/url-guard.js.map +1 -0
  39. package/dist/index.js +23 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/messages.js +176 -0
  42. package/dist/messages.js.map +1 -0
  43. package/dist/normalize/axe.js +72 -0
  44. package/dist/normalize/axe.js.map +1 -0
  45. package/dist/normalize/checkpoints.js +47 -0
  46. package/dist/normalize/checkpoints.js.map +1 -0
  47. package/dist/normalize/finding.js +24 -0
  48. package/dist/normalize/finding.js.map +1 -0
  49. package/dist/normalize/locale.js +20 -0
  50. package/dist/normalize/locale.js.map +1 -0
  51. package/dist/prompts/audit-report.js +45 -0
  52. package/dist/prompts/audit-report.js.map +1 -0
  53. package/dist/prompts/review-markup.js +35 -0
  54. package/dist/prompts/review-markup.js.map +1 -0
  55. package/dist/report/cert.js +72 -0
  56. package/dist/report/cert.js.map +1 -0
  57. package/dist/report/format.js +36 -0
  58. package/dist/report/format.js.map +1 -0
  59. package/dist/report/summarize.js +61 -0
  60. package/dist/report/summarize.js.map +1 -0
  61. package/dist/report/types.js +2 -0
  62. package/dist/report/types.js.map +1 -0
  63. package/dist/resources/index.js +69 -0
  64. package/dist/resources/index.js.map +1 -0
  65. package/dist/rules/b/b-focus-order.js +33 -0
  66. package/dist/rules/b/b-focus-order.js.map +1 -0
  67. package/dist/rules/b/b-focus-visible.js +71 -0
  68. package/dist/rules/b/b-focus-visible.js.map +1 -0
  69. package/dist/rules/b/b-keyboard-reachable.js +82 -0
  70. package/dist/rules/b/b-keyboard-reachable.js.map +1 -0
  71. package/dist/rules/b/b-motion-runtime.js +50 -0
  72. package/dist/rules/b/b-motion-runtime.js.map +1 -0
  73. package/dist/rules/b/b-skip-link-works.js +58 -0
  74. package/dist/rules/b/b-skip-link-works.js.map +1 -0
  75. package/dist/rules/b/b-target-size-6mm.js +54 -0
  76. package/dist/rules/b/b-target-size-6mm.js.map +1 -0
  77. package/dist/rules/b/index.js +7 -0
  78. package/dist/rules/b/index.js.map +1 -0
  79. package/dist/rules/k/index.js +33 -0
  80. package/dist/rules/k/index.js.map +1 -0
  81. package/dist/rules/k/k-accesskey.js +20 -0
  82. package/dist/rules/k/k-accesskey.js.map +1 -0
  83. package/dist/rules/k/k-alt-meaningless.js +35 -0
  84. package/dist/rules/k/k-alt-meaningless.js.map +1 -0
  85. package/dist/rules/k/k-autocomplete-missing.js +36 -0
  86. package/dist/rules/k/k-autocomplete-missing.js.map +1 -0
  87. package/dist/rules/k/k-autoplay-media.js +30 -0
  88. package/dist/rules/k/k-autoplay-media.js.map +1 -0
  89. package/dist/rules/k/k-captcha-detect.js +24 -0
  90. package/dist/rules/k/k-captcha-detect.js.map +1 -0
  91. package/dist/rules/k/k-carousel-no-pause.js +33 -0
  92. package/dist/rules/k/k-carousel-no-pause.js.map +1 -0
  93. package/dist/rules/k/k-device-motion.js +22 -0
  94. package/dist/rules/k/k-device-motion.js.map +1 -0
  95. package/dist/rules/k/k-down-event-action.js +19 -0
  96. package/dist/rules/k/k-down-event-action.js.map +1 -0
  97. package/dist/rules/k/k-error-association.js +31 -0
  98. package/dist/rules/k/k-error-association.js.map +1 -0
  99. package/dist/rules/k/k-flash-animation.js +57 -0
  100. package/dist/rules/k/k-flash-animation.js.map +1 -0
  101. package/dist/rules/k/k-gesture-listener.js +30 -0
  102. package/dist/rules/k/k-gesture-listener.js.map +1 -0
  103. package/dist/rules/k/k-iframe-title.js +23 -0
  104. package/dist/rules/k/k-iframe-title.js.map +1 -0
  105. package/dist/rules/k/k-lang-ko-expected.js +29 -0
  106. package/dist/rules/k/k-lang-ko-expected.js.map +1 -0
  107. package/dist/rules/k/k-link-same-text-diff-href.js +41 -0
  108. package/dist/rules/k/k-link-same-text-diff-href.js.map +1 -0
  109. package/dist/rules/k/k-link-text-generic.js +29 -0
  110. package/dist/rules/k/k-link-text-generic.js.map +1 -0
  111. package/dist/rules/k/k-media-track.js +22 -0
  112. package/dist/rules/k/k-media-track.js.map +1 -0
  113. package/dist/rules/k/k-mouse-only-handler.js +27 -0
  114. package/dist/rules/k/k-mouse-only-handler.js.map +1 -0
  115. package/dist/rules/k/k-new-window-notice.js +27 -0
  116. package/dist/rules/k/k-new-window-notice.js.map +1 -0
  117. package/dist/rules/k/k-onload-popup.js +30 -0
  118. package/dist/rules/k/k-onload-popup.js.map +1 -0
  119. package/dist/rules/k/k-outline-none.js +55 -0
  120. package/dist/rules/k/k-outline-none.js.map +1 -0
  121. package/dist/rules/k/k-parse-errors.js +38 -0
  122. package/dist/rules/k/k-parse-errors.js.map +1 -0
  123. package/dist/rules/k/k-placeholder-only-label.js +32 -0
  124. package/dist/rules/k/k-placeholder-only-label.js.map +1 -0
  125. package/dist/rules/k/k-select-onchange.js +19 -0
  126. package/dist/rules/k/k-select-onchange.js.map +1 -0
  127. package/dist/rules/k/k-sensory-instruction.js +32 -0
  128. package/dist/rules/k/k-sensory-instruction.js.map +1 -0
  129. package/dist/rules/k/k-session-timeout-hint.js +29 -0
  130. package/dist/rules/k/k-session-timeout-hint.js.map +1 -0
  131. package/dist/rules/k/k-skip-link-first.js +23 -0
  132. package/dist/rules/k/k-skip-link-first.js.map +1 -0
  133. package/dist/rules/k/k-skip-target-exists.js +28 -0
  134. package/dist/rules/k/k-skip-target-exists.js.map +1 -0
  135. package/dist/rules/k/k-tabindex-positive.js +23 -0
  136. package/dist/rules/k/k-tabindex-positive.js.map +1 -0
  137. package/dist/rules/k/k-table-caption.js +26 -0
  138. package/dist/rules/k/k-table-caption.js.map +1 -0
  139. package/dist/rules/k/k-table-th-missing.js +28 -0
  140. package/dist/rules/k/k-table-th-missing.js.map +1 -0
  141. package/dist/rules/k/k-title-generic.js +35 -0
  142. package/dist/rules/k/k-title-generic.js.map +1 -0
  143. package/dist/rules/registry.js +62 -0
  144. package/dist/rules/registry.js.map +1 -0
  145. package/dist/rules/types.js +2 -0
  146. package/dist/rules/types.js.map +1 -0
  147. package/dist/rules/util/browser-dom.js +50 -0
  148. package/dist/rules/util/browser-dom.js.map +1 -0
  149. package/dist/rules/util/focusable.js +29 -0
  150. package/dist/rules/util/focusable.js.map +1 -0
  151. package/dist/rules/util/selector.js +19 -0
  152. package/dist/rules/util/selector.js.map +1 -0
  153. package/dist/rules/util/text.js +13 -0
  154. package/dist/rules/util/text.js.map +1 -0
  155. package/dist/schema-dialect.js +41 -0
  156. package/dist/schema-dialect.js.map +1 -0
  157. package/dist/server.js +36 -0
  158. package/dist/server.js.map +1 -0
  159. package/dist/tools/audit-url.js +109 -0
  160. package/dist/tools/audit-url.js.map +1 -0
  161. package/dist/tools/browser-status.js +29 -0
  162. package/dist/tools/browser-status.js.map +1 -0
  163. package/dist/tools/cert-readiness.js +76 -0
  164. package/dist/tools/cert-readiness.js.map +1 -0
  165. package/dist/tools/check-contrast.js +58 -0
  166. package/dist/tools/check-contrast.js.map +1 -0
  167. package/dist/tools/check-html.js +88 -0
  168. package/dist/tools/check-html.js.map +1 -0
  169. package/dist/tools/checklist.js +94 -0
  170. package/dist/tools/checklist.js.map +1 -0
  171. package/dist/tools/lookup.js +70 -0
  172. package/dist/tools/lookup.js.map +1 -0
  173. package/dist/tools/report-schema.js +49 -0
  174. package/dist/tools/report-schema.js.map +1 -0
  175. package/package.json +76 -0
@@ -0,0 +1,1688 @@
1
+ {
2
+ "version": "2.2",
3
+ "dataVersion": "0.1.0",
4
+ "updatedAt": "2026-09-04",
5
+ "sourceIds": [
6
+ "kwcag22-a11ykr",
7
+ "kwcag22-websoul",
8
+ "rra-kcs"
9
+ ],
10
+ "checkpoints": [
11
+ {
12
+ "id": "5.1.1",
13
+ "alias": "1.1.1",
14
+ "principle": {
15
+ "no": 5,
16
+ "alias": 1,
17
+ "name": "인식의 용이성"
18
+ },
19
+ "guideline": {
20
+ "no": "5.1",
21
+ "alias": "1.1",
22
+ "name": "대체 텍스트"
23
+ },
24
+ "name_ko": "적절한 대체 텍스트 제공",
25
+ "name_en": null,
26
+ "requirement_ko": "텍스트 아닌 콘텐츠는 그 의미나 용도를 이해할 수 있도록 대체 텍스트를 제공해야 한다.",
27
+ "summary_ko": "이미지·아이콘 등 텍스트가 아닌 콘텐츠에 그 의미를 전달하는 대체 텍스트를 제공한다.",
28
+ "wcag": [
29
+ {
30
+ "sc": "1.1.1",
31
+ "level": "A"
32
+ }
33
+ ],
34
+ "automation": "assist",
35
+ "axeRules": [
36
+ "image-alt",
37
+ "input-image-alt",
38
+ "area-alt",
39
+ "object-alt",
40
+ "svg-img-alt",
41
+ "role-img-alt"
42
+ ],
43
+ "kRules": [
44
+ "k-alt-meaningless"
45
+ ],
46
+ "bRules": [],
47
+ "testMethod_ko": [
48
+ "이미지의 alt 속성 유무와 내용을 확인한다.",
49
+ "장식용 이미지는 alt=\"\"로 처리했는지 확인한다."
50
+ ],
51
+ "commonErrors_ko": [
52
+ "alt 속성 누락",
53
+ "파일명을 그대로 alt로 사용(img1.png)",
54
+ "\"이미지\"·\"사진\" 같은 무의미한 alt"
55
+ ],
56
+ "passExamples_ko": [
57
+ "alt=\"로그인\" 버튼 아이콘",
58
+ "장식용 배경 이미지에 alt=\"\""
59
+ ],
60
+ "components": [
61
+ "image"
62
+ ],
63
+ "newIn22": false,
64
+ "sources": [
65
+ "kwcag22-a11ykr",
66
+ "kwcag22-websoul"
67
+ ]
68
+ },
69
+ {
70
+ "id": "5.2.1",
71
+ "alias": "1.2.1",
72
+ "principle": {
73
+ "no": 5,
74
+ "alias": 1,
75
+ "name": "인식의 용이성"
76
+ },
77
+ "guideline": {
78
+ "no": "5.2",
79
+ "alias": "1.2",
80
+ "name": "멀티미디어 대체수단"
81
+ },
82
+ "name_ko": "자막 제공",
83
+ "name_en": null,
84
+ "requirement_ko": "멀티미디어 콘텐츠에는 자막, 원고 또는 수어를 제공해야 한다.",
85
+ "summary_ko": "오디오·비디오 콘텐츠에 자막·대본·수어 등 대체 수단을 제공한다.",
86
+ "wcag": [
87
+ {
88
+ "sc": "1.2.1",
89
+ "level": "A"
90
+ },
91
+ {
92
+ "sc": "1.2.2",
93
+ "level": "A"
94
+ },
95
+ {
96
+ "sc": "1.2.3",
97
+ "level": "A"
98
+ }
99
+ ],
100
+ "automation": "assist",
101
+ "axeRules": [
102
+ "video-caption"
103
+ ],
104
+ "kRules": [
105
+ "k-media-track"
106
+ ],
107
+ "bRules": [],
108
+ "testMethod_ko": [
109
+ "video/audio 요소에 자막 트랙(track[kind=captions])이 있는지 확인한다.",
110
+ "자막 내용이 음성과 일치하는지 확인한다."
111
+ ],
112
+ "commonErrors_ko": [
113
+ "자막 트랙 누락",
114
+ "자동 생성 자막의 오탈자 방치"
115
+ ],
116
+ "passExamples_ko": [
117
+ "강의 영상에 한국어 자막 트랙 제공"
118
+ ],
119
+ "components": [
120
+ "media"
121
+ ],
122
+ "newIn22": false,
123
+ "sources": [
124
+ "kwcag22-a11ykr",
125
+ "kwcag22-websoul"
126
+ ]
127
+ },
128
+ {
129
+ "id": "5.3.1",
130
+ "alias": "1.3.1",
131
+ "principle": {
132
+ "no": 5,
133
+ "alias": 1,
134
+ "name": "인식의 용이성"
135
+ },
136
+ "guideline": {
137
+ "no": "5.3",
138
+ "alias": "1.3",
139
+ "name": "적응성"
140
+ },
141
+ "name_ko": "표의 구성",
142
+ "name_en": null,
143
+ "requirement_ko": "표는 이해하기 쉽게 구성해야 한다.",
144
+ "summary_ko": "표는 caption과 th/td 관계로 이해하기 쉽게 구성한다.",
145
+ "wcag": [
146
+ {
147
+ "sc": "1.3.1",
148
+ "level": "A"
149
+ }
150
+ ],
151
+ "automation": "assist",
152
+ "axeRules": [
153
+ "td-headers-attr",
154
+ "th-has-data-cells",
155
+ "scope-attr-valid",
156
+ "table-fake-caption",
157
+ "table-duplicate-name"
158
+ ],
159
+ "kRules": [
160
+ "k-table-caption",
161
+ "k-table-th-missing"
162
+ ],
163
+ "bRules": [],
164
+ "testMethod_ko": [
165
+ "데이터 표에 caption·th·scope/headers 속성이 있는지 확인한다."
166
+ ],
167
+ "commonErrors_ko": [
168
+ "레이아웃 목적으로 표를 사용",
169
+ "th 없이 td만 사용",
170
+ "caption 누락"
171
+ ],
172
+ "passExamples_ko": [
173
+ "표에 caption과 th scope=\"col\" 제공"
174
+ ],
175
+ "components": [
176
+ "table"
177
+ ],
178
+ "newIn22": false,
179
+ "sources": [
180
+ "kwcag22-a11ykr",
181
+ "kwcag22-websoul"
182
+ ]
183
+ },
184
+ {
185
+ "id": "5.3.2",
186
+ "alias": "1.3.2",
187
+ "principle": {
188
+ "no": 5,
189
+ "alias": 1,
190
+ "name": "인식의 용이성"
191
+ },
192
+ "guideline": {
193
+ "no": "5.3",
194
+ "alias": "1.3",
195
+ "name": "적응성"
196
+ },
197
+ "name_ko": "콘텐츠의 선형구조",
198
+ "name_en": null,
199
+ "requirement_ko": "콘텐츠는 논리적인 순서로 제공해야 한다.",
200
+ "summary_ko": "콘텐츠는 시각적 배치와 무관하게 논리적인 읽기 순서를 갖는다.",
201
+ "wcag": [
202
+ {
203
+ "sc": "1.3.2",
204
+ "level": "A"
205
+ }
206
+ ],
207
+ "automation": "assist",
208
+ "axeRules": [
209
+ "heading-order"
210
+ ],
211
+ "kRules": [
212
+ "k-tabindex-positive"
213
+ ],
214
+ "bRules": [],
215
+ "testMethod_ko": [
216
+ "CSS를 제거하고 DOM 순서로 읽었을 때 의미가 통하는지 확인한다.",
217
+ "제목 레벨(h1~h6)이 순서대로 사용됐는지 확인한다."
218
+ ],
219
+ "commonErrors_ko": [
220
+ "tabindex 양수값으로 포커스 순서를 임의 조정",
221
+ "제목 레벨 건너뛰기(h2 다음 h4)"
222
+ ],
223
+ "passExamples_ko": [
224
+ "h1→h2→h3 순서대로 제목 사용"
225
+ ],
226
+ "components": [
227
+ "navigation"
228
+ ],
229
+ "newIn22": false,
230
+ "sources": [
231
+ "kwcag22-a11ykr",
232
+ "kwcag22-websoul"
233
+ ]
234
+ },
235
+ {
236
+ "id": "5.3.3",
237
+ "alias": "1.3.3",
238
+ "principle": {
239
+ "no": 5,
240
+ "alias": 1,
241
+ "name": "인식의 용이성"
242
+ },
243
+ "guideline": {
244
+ "no": "5.3",
245
+ "alias": "1.3",
246
+ "name": "적응성"
247
+ },
248
+ "name_ko": "명확한 지시사항 제공",
249
+ "name_en": null,
250
+ "requirement_ko": "지시사항은 모양, 크기, 위치, 방향, 색, 소리 등에 관계없이 인식될 수 있어야 한다.",
251
+ "summary_ko": "\"오른쪽 빨간 버튼\"처럼 감각적 특성에만 의존한 지시를 피한다.",
252
+ "wcag": [
253
+ {
254
+ "sc": "1.3.3",
255
+ "level": "A"
256
+ }
257
+ ],
258
+ "automation": "manual",
259
+ "axeRules": [],
260
+ "kRules": [
261
+ "k-sensory-instruction"
262
+ ],
263
+ "bRules": [],
264
+ "testMethod_ko": [
265
+ "안내 문구가 모양·위치·색·소리만으로 대상을 지칭하는지 검토한다."
266
+ ],
267
+ "commonErrors_ko": [
268
+ "\"오른쪽 초록 버튼을 누르세요\"만 안내",
269
+ "\"위 그림 참고\"만 안내"
270
+ ],
271
+ "passExamples_ko": [
272
+ "\"저장(오른쪽 초록 버튼)을 누르세요\"처럼 텍스트 라벨 병기"
273
+ ],
274
+ "components": [
275
+ "form"
276
+ ],
277
+ "newIn22": false,
278
+ "sources": [
279
+ "kwcag22-a11ykr",
280
+ "kwcag22-websoul"
281
+ ]
282
+ },
283
+ {
284
+ "id": "5.4.1",
285
+ "alias": "1.4.1",
286
+ "principle": {
287
+ "no": 5,
288
+ "alias": 1,
289
+ "name": "인식의 용이성"
290
+ },
291
+ "guideline": {
292
+ "no": "5.4",
293
+ "alias": "1.4",
294
+ "name": "명료성"
295
+ },
296
+ "name_ko": "색에 무관한 콘텐츠 인식",
297
+ "name_en": null,
298
+ "requirement_ko": "콘텐츠는 색에 관계없이 인식될 수 있어야 한다.",
299
+ "summary_ko": "색만으로 의미를 구분하지 않고 텍스트·아이콘·패턴을 함께 제공한다.",
300
+ "wcag": [
301
+ {
302
+ "sc": "1.4.1",
303
+ "level": "A"
304
+ }
305
+ ],
306
+ "automation": "manual",
307
+ "axeRules": [
308
+ "link-in-text-block"
309
+ ],
310
+ "kRules": [],
311
+ "bRules": [],
312
+ "testMethod_ko": [
313
+ "필수 입력·오류 표시가 색 외의 방법(별표·아이콘·텍스트)으로도 구별되는지 확인한다."
314
+ ],
315
+ "commonErrors_ko": [
316
+ "빨간 테두리만으로 오류 표시",
317
+ "범례를 색으로만 구분한 차트"
318
+ ],
319
+ "passExamples_ko": [
320
+ "오류 필드에 빨간 테두리 + \"필수\" 텍스트"
321
+ ],
322
+ "components": [
323
+ "form"
324
+ ],
325
+ "newIn22": false,
326
+ "sources": [
327
+ "kwcag22-a11ykr",
328
+ "kwcag22-websoul"
329
+ ]
330
+ },
331
+ {
332
+ "id": "5.4.2",
333
+ "alias": "1.4.2",
334
+ "principle": {
335
+ "no": 5,
336
+ "alias": 1,
337
+ "name": "인식의 용이성"
338
+ },
339
+ "guideline": {
340
+ "no": "5.4",
341
+ "alias": "1.4",
342
+ "name": "명료성"
343
+ },
344
+ "name_ko": "자동 재생 금지",
345
+ "name_en": null,
346
+ "requirement_ko": "자동으로 소리가 재생되지 않아야 한다.",
347
+ "summary_ko": "사용자 동의 없이 소리가 자동 재생되지 않아야 한다.",
348
+ "wcag": [
349
+ {
350
+ "sc": "1.4.2",
351
+ "level": "A"
352
+ }
353
+ ],
354
+ "automation": "auto",
355
+ "axeRules": [
356
+ "no-autoplay-audio"
357
+ ],
358
+ "kRules": [
359
+ "k-autoplay-media"
360
+ ],
361
+ "bRules": [],
362
+ "testMethod_ko": [
363
+ "페이지 로드 시 autoplay 오디오/비디오가 음소거 없이 재생되는지 확인한다."
364
+ ],
365
+ "commonErrors_ko": [
366
+ "배경음악 autoplay",
367
+ "동영상 autoplay + 음소거 해제 상태"
368
+ ],
369
+ "passExamples_ko": [
370
+ "autoplay 비디오에 muted 속성 적용 또는 자동재생 없음"
371
+ ],
372
+ "components": [
373
+ "media"
374
+ ],
375
+ "newIn22": false,
376
+ "sources": [
377
+ "kwcag22-a11ykr",
378
+ "kwcag22-websoul"
379
+ ]
380
+ },
381
+ {
382
+ "id": "5.4.3",
383
+ "alias": "1.4.3",
384
+ "principle": {
385
+ "no": 5,
386
+ "alias": 1,
387
+ "name": "인식의 용이성"
388
+ },
389
+ "guideline": {
390
+ "no": "5.4",
391
+ "alias": "1.4",
392
+ "name": "명료성"
393
+ },
394
+ "name_ko": "텍스트 콘텐츠의 명도 대비",
395
+ "name_en": null,
396
+ "requirement_ko": "텍스트 콘텐츠와 배경 간의 명도 대비는 4.5 대 1 이상이어야 한다.",
397
+ "summary_ko": "텍스트와 배경의 명도 대비가 4.5:1(큰 글자 3:1) 이상이어야 한다.",
398
+ "wcag": [
399
+ {
400
+ "sc": "1.4.3",
401
+ "level": "AA"
402
+ }
403
+ ],
404
+ "automation": "auto",
405
+ "axeRules": [
406
+ "color-contrast"
407
+ ],
408
+ "kRules": [],
409
+ "bRules": [],
410
+ "testMethod_ko": [
411
+ "`check_contrast` 도구로 전경·배경 색상 쌍의 대비를 계산한다.",
412
+ "브라우저 감사로 렌더링된 실제 색상을 측정한다."
413
+ ],
414
+ "commonErrors_ko": [
415
+ "연한 회색 텍스트/배경 조합",
416
+ "placeholder 텍스트의 낮은 대비"
417
+ ],
418
+ "passExamples_ko": [
419
+ "본문 텍스트 #333 on #fff(대비 12.6:1)"
420
+ ],
421
+ "components": [],
422
+ "newIn22": false,
423
+ "sources": [
424
+ "kwcag22-a11ykr",
425
+ "kwcag22-websoul"
426
+ ]
427
+ },
428
+ {
429
+ "id": "5.4.4",
430
+ "alias": "1.4.4",
431
+ "principle": {
432
+ "no": 5,
433
+ "alias": 1,
434
+ "name": "인식의 용이성"
435
+ },
436
+ "guideline": {
437
+ "no": "5.4",
438
+ "alias": "1.4",
439
+ "name": "명료성"
440
+ },
441
+ "name_ko": "콘텐츠 간의 구분",
442
+ "name_en": null,
443
+ "requirement_ko": "이웃한 콘텐츠는 구별될 수 있어야 한다.",
444
+ "summary_ko": "이웃한 콘텐츠(버튼·카드 등)가 테두리·여백·배경 등으로 구별되어야 한다.",
445
+ "wcag": [
446
+ {
447
+ "sc": "1.4.11",
448
+ "level": "A"
449
+ }
450
+ ],
451
+ "automation": "manual",
452
+ "axeRules": [],
453
+ "kRules": [],
454
+ "bRules": [],
455
+ "testMethod_ko": [
456
+ "인접 요소 사이에 시각적 경계(테두리·여백·배경색)가 있는지 확인한다."
457
+ ],
458
+ "commonErrors_ko": [
459
+ "버튼들이 여백 없이 붙어 있음"
460
+ ],
461
+ "passExamples_ko": [
462
+ "카드 사이 여백과 그림자로 구분"
463
+ ],
464
+ "components": [
465
+ "widget"
466
+ ],
467
+ "newIn22": false,
468
+ "sources": [
469
+ "kwcag22-a11ykr",
470
+ "kwcag22-websoul"
471
+ ]
472
+ },
473
+ {
474
+ "id": "6.1.1",
475
+ "alias": "2.1.1",
476
+ "principle": {
477
+ "no": 6,
478
+ "alias": 2,
479
+ "name": "운용의 용이성"
480
+ },
481
+ "guideline": {
482
+ "no": "6.1",
483
+ "alias": "2.1",
484
+ "name": "입력장치 접근성"
485
+ },
486
+ "name_ko": "키보드 사용 보장",
487
+ "name_en": null,
488
+ "requirement_ko": "모든 기능은 키보드만으로도 사용할 수 있어야 한다.",
489
+ "summary_ko": "모든 기능을 키보드만으로 사용할 수 있어야 한다(마우스 전용 기능 금지).",
490
+ "wcag": [
491
+ {
492
+ "sc": "2.1.1",
493
+ "level": "A"
494
+ }
495
+ ],
496
+ "automation": "assist",
497
+ "axeRules": [
498
+ "scrollable-region-focusable",
499
+ "nested-interactive",
500
+ "server-side-image-map"
501
+ ],
502
+ "kRules": [
503
+ "k-mouse-only-handler"
504
+ ],
505
+ "bRules": [
506
+ "b-keyboard-reachable"
507
+ ],
508
+ "testMethod_ko": [
509
+ "Tab/Enter/Space만으로 모든 기능을 조작해본다.",
510
+ "onclick만 있고 키보드 핸들러가 없는 요소가 있는지 확인한다."
511
+ ],
512
+ "commonErrors_ko": [
513
+ "div/span에 onclick만 부여하고 tabindex·키보드 핸들러 없음"
514
+ ],
515
+ "passExamples_ko": [
516
+ "button 요소 사용 또는 div+tabindex+keydown 핸들러"
517
+ ],
518
+ "components": [
519
+ "widget"
520
+ ],
521
+ "newIn22": false,
522
+ "sources": [
523
+ "kwcag22-a11ykr",
524
+ "kwcag22-websoul"
525
+ ]
526
+ },
527
+ {
528
+ "id": "6.1.2",
529
+ "alias": "2.1.2",
530
+ "principle": {
531
+ "no": 6,
532
+ "alias": 2,
533
+ "name": "운용의 용이성"
534
+ },
535
+ "guideline": {
536
+ "no": "6.1",
537
+ "alias": "2.1",
538
+ "name": "입력장치 접근성"
539
+ },
540
+ "name_ko": "초점 이동과 표시",
541
+ "name_en": null,
542
+ "requirement_ko": "키보드에 의한 초점은 논리적으로 이동해야 하며, 시각적으로 구별할 수 있어야 한다.",
543
+ "summary_ko": "키보드 초점이 논리적 순서로 이동하고 시각적으로 뚜렷하게 표시되어야 한다.",
544
+ "wcag": [
545
+ {
546
+ "sc": "2.4.3",
547
+ "level": "A"
548
+ },
549
+ {
550
+ "sc": "2.4.7",
551
+ "level": "A"
552
+ }
553
+ ],
554
+ "automation": "assist",
555
+ "axeRules": [],
556
+ "kRules": [
557
+ "k-outline-none"
558
+ ],
559
+ "bRules": [
560
+ "b-focus-visible",
561
+ "b-focus-order"
562
+ ],
563
+ "testMethod_ko": [
564
+ "Tab으로 순회하며 DOM 순서와 일치하는지, 초점 스타일이 보이는지 확인한다."
565
+ ],
566
+ "commonErrors_ko": [
567
+ "outline: none만 제거하고 대체 스타일 없음",
568
+ "tabindex 양수값 남용으로 순서 역행"
569
+ ],
570
+ "passExamples_ko": [
571
+ ":focus-visible에 outline과 대비되는 테두리 제공"
572
+ ],
573
+ "components": [
574
+ "widget"
575
+ ],
576
+ "newIn22": false,
577
+ "sources": [
578
+ "kwcag22-a11ykr",
579
+ "kwcag22-websoul"
580
+ ]
581
+ },
582
+ {
583
+ "id": "6.1.3",
584
+ "alias": "2.1.3",
585
+ "principle": {
586
+ "no": 6,
587
+ "alias": 2,
588
+ "name": "운용의 용이성"
589
+ },
590
+ "guideline": {
591
+ "no": "6.1",
592
+ "alias": "2.1",
593
+ "name": "입력장치 접근성"
594
+ },
595
+ "name_ko": "조작 가능",
596
+ "name_en": null,
597
+ "requirement_ko": "사용자 입력 및 컨트롤은 조작 가능하도록 제공되어야 한다.",
598
+ "summary_ko": "터치 등 입력 컨트롤은 실수로 조작되지 않을 크기·방식으로 제공한다.",
599
+ "wcag": [
600
+ {
601
+ "sc": "2.5.5",
602
+ "level": "A"
603
+ },
604
+ {
605
+ "sc": "2.5.8",
606
+ "level": "AA"
607
+ }
608
+ ],
609
+ "automation": "assist",
610
+ "axeRules": [
611
+ "target-size"
612
+ ],
613
+ "kRules": [],
614
+ "bRules": [
615
+ "b-target-size-6mm"
616
+ ],
617
+ "testMethod_ko": [
618
+ "대화형 요소의 클릭 가능 영역 크기(약 24px 이상)를 측정한다."
619
+ ],
620
+ "commonErrors_ko": [
621
+ "아이콘 버튼이 16px 이하로 작음",
622
+ "버튼 간 간격 없이 밀집"
623
+ ],
624
+ "passExamples_ko": [
625
+ "버튼 최소 24×24px, 인접 버튼 간 여백 확보"
626
+ ],
627
+ "components": [
628
+ "widget"
629
+ ],
630
+ "newIn22": false,
631
+ "sources": [
632
+ "kwcag22-a11ykr",
633
+ "kwcag22-websoul"
634
+ ]
635
+ },
636
+ {
637
+ "id": "6.1.4",
638
+ "alias": "2.1.4",
639
+ "principle": {
640
+ "no": 6,
641
+ "alias": 2,
642
+ "name": "운용의 용이성"
643
+ },
644
+ "guideline": {
645
+ "no": "6.1",
646
+ "alias": "2.1",
647
+ "name": "입력장치 접근성"
648
+ },
649
+ "name_ko": "문자 단축키",
650
+ "name_en": null,
651
+ "requirement_ko": "문자 단축키는 오동작으로 인한 오류를 방지하여야 한다.",
652
+ "summary_ko": "문자 하나로 된 단축키는 오동작을 막는 장치(끄기·재구성·초점 시에만 동작)를 둔다.",
653
+ "wcag": [
654
+ {
655
+ "sc": "2.1.4",
656
+ "level": "A"
657
+ }
658
+ ],
659
+ "automation": "manual",
660
+ "axeRules": [],
661
+ "kRules": [
662
+ "k-accesskey"
663
+ ],
664
+ "bRules": [],
665
+ "testMethod_ko": [
666
+ "accesskey나 단일 문자 단축키가 있는지, 끄거나 재설정할 수 있는지 확인한다."
667
+ ],
668
+ "commonErrors_ko": [
669
+ "accesskey를 다른 브라우저 단축키와 충돌하게 지정"
670
+ ],
671
+ "passExamples_ko": [
672
+ "단축키 설정 화면에서 켜기/끄기 제공"
673
+ ],
674
+ "components": [],
675
+ "newIn22": true,
676
+ "sources": [
677
+ "kwcag22-a11ykr",
678
+ "kwcag22-websoul"
679
+ ]
680
+ },
681
+ {
682
+ "id": "6.2.1",
683
+ "alias": "2.2.1",
684
+ "principle": {
685
+ "no": 6,
686
+ "alias": 2,
687
+ "name": "운용의 용이성"
688
+ },
689
+ "guideline": {
690
+ "no": "6.2",
691
+ "alias": "2.2",
692
+ "name": "충분한 시간 제공"
693
+ },
694
+ "name_ko": "응답시간 조절",
695
+ "name_en": null,
696
+ "requirement_ko": "시간제한이 있는 콘텐츠는 응답시간을 조절할 수 있어야 한다.",
697
+ "summary_ko": "시간제한이 있는 콘텐츠는 연장·해제할 수 있는 수단을 제공한다.",
698
+ "wcag": [
699
+ {
700
+ "sc": "2.2.1",
701
+ "level": "A"
702
+ }
703
+ ],
704
+ "automation": "assist",
705
+ "axeRules": [
706
+ "meta-refresh"
707
+ ],
708
+ "kRules": [
709
+ "k-session-timeout-hint"
710
+ ],
711
+ "bRules": [],
712
+ "testMethod_ko": [
713
+ "세션 타임아웃·자동 새로고침(meta refresh) 여부와 연장 옵션을 확인한다."
714
+ ],
715
+ "commonErrors_ko": [
716
+ "안내 없이 일정 시간 후 자동 로그아웃"
717
+ ],
718
+ "passExamples_ko": [
719
+ "만료 전 경고와 연장 버튼 제공"
720
+ ],
721
+ "components": [
722
+ "auth"
723
+ ],
724
+ "newIn22": false,
725
+ "sources": [
726
+ "kwcag22-a11ykr",
727
+ "kwcag22-websoul"
728
+ ]
729
+ },
730
+ {
731
+ "id": "6.2.2",
732
+ "alias": "2.2.2",
733
+ "principle": {
734
+ "no": 6,
735
+ "alias": 2,
736
+ "name": "운용의 용이성"
737
+ },
738
+ "guideline": {
739
+ "no": "6.2",
740
+ "alias": "2.2",
741
+ "name": "충분한 시간 제공"
742
+ },
743
+ "name_ko": "정지 기능 제공",
744
+ "name_en": null,
745
+ "requirement_ko": "자동으로 변경되는 콘텐츠는 움직임을 제어할 수 있어야 한다.",
746
+ "summary_ko": "자동으로 움직이거나 갱신되는 콘텐츠는 정지·일시정지할 수 있어야 한다.",
747
+ "wcag": [
748
+ {
749
+ "sc": "2.2.2",
750
+ "level": "A"
751
+ }
752
+ ],
753
+ "automation": "assist",
754
+ "axeRules": [
755
+ "blink",
756
+ "marquee"
757
+ ],
758
+ "kRules": [
759
+ "k-carousel-no-pause"
760
+ ],
761
+ "bRules": [
762
+ "b-motion-runtime"
763
+ ],
764
+ "testMethod_ko": [
765
+ "캐러셀·슬라이더·자동 갱신 영역에 정지 버튼이 있는지 확인한다."
766
+ ],
767
+ "commonErrors_ko": [
768
+ "자동 슬라이드 배너에 정지 버튼 없음"
769
+ ],
770
+ "passExamples_ko": [
771
+ "캐러셀에 일시정지 버튼 제공"
772
+ ],
773
+ "components": [
774
+ "carousel"
775
+ ],
776
+ "newIn22": false,
777
+ "sources": [
778
+ "kwcag22-a11ykr",
779
+ "kwcag22-websoul"
780
+ ]
781
+ },
782
+ {
783
+ "id": "6.3.1",
784
+ "alias": "2.3.1",
785
+ "principle": {
786
+ "no": 6,
787
+ "alias": 2,
788
+ "name": "운용의 용이성"
789
+ },
790
+ "guideline": {
791
+ "no": "6.3",
792
+ "alias": "2.3",
793
+ "name": "광과민성 발작 예방"
794
+ },
795
+ "name_ko": "깜빡임과 번쩍임 사용 제한",
796
+ "name_en": null,
797
+ "requirement_ko": "초당 3~50회 주기로 깜빡이거나 번쩍이는 콘텐츠를 제공하지 않아야 한다.",
798
+ "summary_ko": "초당 3~50회 주기로 깜빡이는 콘텐츠를 제공하지 않는다(광과민성 발작 예방).",
799
+ "wcag": [
800
+ {
801
+ "sc": "2.3.1",
802
+ "level": "A"
803
+ }
804
+ ],
805
+ "automation": "manual",
806
+ "axeRules": [],
807
+ "kRules": [
808
+ "k-flash-animation"
809
+ ],
810
+ "bRules": [],
811
+ "testMethod_ko": [
812
+ "애니메이션 주기를 측정해 초당 3~50회 범위에 해당하는지 확인한다."
813
+ ],
814
+ "commonErrors_ko": [
815
+ "빠르게 점멸하는 배너 애니메이션"
816
+ ],
817
+ "passExamples_ko": [
818
+ "점멸 없는 부드러운 페이드 애니메이션 사용"
819
+ ],
820
+ "components": [],
821
+ "newIn22": false,
822
+ "sources": [
823
+ "kwcag22-a11ykr",
824
+ "kwcag22-websoul"
825
+ ]
826
+ },
827
+ {
828
+ "id": "6.4.1",
829
+ "alias": "2.4.1",
830
+ "principle": {
831
+ "no": 6,
832
+ "alias": 2,
833
+ "name": "운용의 용이성"
834
+ },
835
+ "guideline": {
836
+ "no": "6.4",
837
+ "alias": "2.4",
838
+ "name": "쉬운 내비게이션"
839
+ },
840
+ "name_ko": "반복 영역 건너뛰기",
841
+ "name_en": null,
842
+ "requirement_ko": "콘텐츠의 반복되는 영역은 건너뛸 수 있어야 한다.",
843
+ "summary_ko": "반복되는 내비게이션 등을 건너뛸 수 있는 바로가기 링크를 제공한다.",
844
+ "wcag": [
845
+ {
846
+ "sc": "2.4.1",
847
+ "level": "A"
848
+ }
849
+ ],
850
+ "automation": "auto",
851
+ "axeRules": [
852
+ "bypass",
853
+ "skip-link"
854
+ ],
855
+ "kRules": [
856
+ "k-skip-link-first",
857
+ "k-skip-target-exists"
858
+ ],
859
+ "bRules": [
860
+ "b-skip-link-works"
861
+ ],
862
+ "testMethod_ko": [
863
+ "문서의 첫 포커스가 본문 바로가기 링크인지, 대상이 실제로 존재하는지 확인한다."
864
+ ],
865
+ "commonErrors_ko": [
866
+ "바로가기 링크 없음",
867
+ "링크는 있으나 대상 앵커가 없음"
868
+ ],
869
+ "passExamples_ko": [
870
+ "\"본문 바로가기\" 링크가 페이지 첫 요소로 존재"
871
+ ],
872
+ "components": [
873
+ "navigation"
874
+ ],
875
+ "newIn22": false,
876
+ "sources": [
877
+ "kwcag22-a11ykr",
878
+ "kwcag22-websoul"
879
+ ]
880
+ },
881
+ {
882
+ "id": "6.4.2",
883
+ "alias": "2.4.2",
884
+ "principle": {
885
+ "no": 6,
886
+ "alias": 2,
887
+ "name": "운용의 용이성"
888
+ },
889
+ "guideline": {
890
+ "no": "6.4",
891
+ "alias": "2.4",
892
+ "name": "쉬운 내비게이션"
893
+ },
894
+ "name_ko": "제목 제공",
895
+ "name_en": null,
896
+ "requirement_ko": "페이지, 프레임, 콘텐츠 블록에는 적절한 제목을 제공해야 한다.",
897
+ "summary_ko": "페이지·프레임·콘텐츠 블록에 적절한 제목을 제공한다.",
898
+ "wcag": [
899
+ {
900
+ "sc": "2.4.2",
901
+ "level": "A"
902
+ },
903
+ {
904
+ "sc": "2.4.6",
905
+ "level": "A"
906
+ }
907
+ ],
908
+ "automation": "auto",
909
+ "axeRules": [
910
+ "document-title",
911
+ "frame-title",
912
+ "frame-title-unique",
913
+ "page-has-heading-one",
914
+ "empty-heading"
915
+ ],
916
+ "kRules": [
917
+ "k-title-generic",
918
+ "k-iframe-title"
919
+ ],
920
+ "bRules": [],
921
+ "testMethod_ko": [
922
+ "<title>과 iframe title, 대표 h1이 있는지 확인한다."
923
+ ],
924
+ "commonErrors_ko": [
925
+ "<title>이 비어있거나 사이트명만 있음",
926
+ "iframe title 누락"
927
+ ],
928
+ "passExamples_ko": [
929
+ "<title>페이지 목적 - 사이트명</title>"
930
+ ],
931
+ "components": [
932
+ "iframe"
933
+ ],
934
+ "newIn22": false,
935
+ "sources": [
936
+ "kwcag22-a11ykr",
937
+ "kwcag22-websoul"
938
+ ]
939
+ },
940
+ {
941
+ "id": "6.4.3",
942
+ "alias": "2.4.3",
943
+ "principle": {
944
+ "no": 6,
945
+ "alias": 2,
946
+ "name": "운용의 용이성"
947
+ },
948
+ "guideline": {
949
+ "no": "6.4",
950
+ "alias": "2.4",
951
+ "name": "쉬운 내비게이션"
952
+ },
953
+ "name_ko": "적절한 링크 텍스트",
954
+ "name_en": null,
955
+ "requirement_ko": "링크 텍스트는 용도나 목적을 이해할 수 있도록 제공해야 한다.",
956
+ "summary_ko": "링크 텍스트만으로 용도나 목적을 알 수 있어야 한다.",
957
+ "wcag": [
958
+ {
959
+ "sc": "2.4.4",
960
+ "level": "A"
961
+ }
962
+ ],
963
+ "automation": "assist",
964
+ "axeRules": [
965
+ "link-name"
966
+ ],
967
+ "kRules": [
968
+ "k-link-text-generic",
969
+ "k-link-same-text-diff-href"
970
+ ],
971
+ "bRules": [],
972
+ "testMethod_ko": [
973
+ "\"더보기\"·\"클릭\" 같은 일반 텍스트 링크가 있는지, 주변 문맥으로 보완되는지 확인한다."
974
+ ],
975
+ "commonErrors_ko": [
976
+ "\"더보기\", \"자세히\" 텍스트만 있는 링크 다수"
977
+ ],
978
+ "passExamples_ko": [
979
+ "\"2026년 예산안 더보기\"처럼 목적을 포함한 링크 텍스트"
980
+ ],
981
+ "components": [
982
+ "link"
983
+ ],
984
+ "newIn22": false,
985
+ "sources": [
986
+ "kwcag22-a11ykr",
987
+ "kwcag22-websoul"
988
+ ]
989
+ },
990
+ {
991
+ "id": "6.4.4",
992
+ "alias": "2.4.4",
993
+ "principle": {
994
+ "no": 6,
995
+ "alias": 2,
996
+ "name": "운용의 용이성"
997
+ },
998
+ "guideline": {
999
+ "no": "6.4",
1000
+ "alias": "2.4",
1001
+ "name": "쉬운 내비게이션"
1002
+ },
1003
+ "name_ko": "고정된 참조 위치 정보",
1004
+ "name_en": null,
1005
+ "requirement_ko": "전자출판문서 형식의 웹 페이지는 각 페이지로 이동할 수 있는 기능이 있어야 하고, 서식이나 플랫폼에 상관없이 참조 위치 정보를 일관되게 제공·유지해야 한다.",
1006
+ "summary_ko": "전자출판(EPUB) 형식 웹 페이지는 페이지 이동·참조 위치 정보를 일관되게 제공한다.",
1007
+ "wcag": [],
1008
+ "automation": "na",
1009
+ "axeRules": [],
1010
+ "kRules": [],
1011
+ "bRules": [],
1012
+ "testMethod_ko": [
1013
+ "전자출판 콘텐츠인 경우 페이지 번호·목차 이동 기능을 확인한다(해당 시에만 적용)."
1014
+ ],
1015
+ "commonErrors_ko": [
1016
+ "전자출판 뷰어에 페이지 이동 기능 없음"
1017
+ ],
1018
+ "passExamples_ko": [
1019
+ "EPUB 뷰어에 페이지 번호 이동 UI 제공"
1020
+ ],
1021
+ "components": [],
1022
+ "newIn22": true,
1023
+ "sources": [
1024
+ "kwcag22-a11ykr",
1025
+ "kwcag22-websoul"
1026
+ ]
1027
+ },
1028
+ {
1029
+ "id": "6.5.1",
1030
+ "alias": "2.5.1",
1031
+ "principle": {
1032
+ "no": 6,
1033
+ "alias": 2,
1034
+ "name": "운용의 용이성"
1035
+ },
1036
+ "guideline": {
1037
+ "no": "6.5",
1038
+ "alias": "2.5",
1039
+ "name": "입력 방식"
1040
+ },
1041
+ "name_ko": "단일 포인터 입력 지원",
1042
+ "name_en": null,
1043
+ "requirement_ko": "다중 포인터 또는 경로기반 동작을 통한 입력은 단일 포인터 입력으로도 조작할 수 있어야 한다.",
1044
+ "summary_ko": "다중 터치·경로기반 동작(스와이프 등)은 단일 탭으로도 조작할 수 있어야 한다.",
1045
+ "wcag": [
1046
+ {
1047
+ "sc": "2.5.1",
1048
+ "level": "A"
1049
+ }
1050
+ ],
1051
+ "automation": "manual",
1052
+ "axeRules": [],
1053
+ "kRules": [
1054
+ "k-gesture-listener"
1055
+ ],
1056
+ "bRules": [],
1057
+ "testMethod_ko": [
1058
+ "스와이프·핀치 등 제스처 전용 기능에 탭·버튼 대안이 있는지 확인한다."
1059
+ ],
1060
+ "commonErrors_ko": [
1061
+ "스와이프로만 삭제 가능하고 버튼 대안 없음"
1062
+ ],
1063
+ "passExamples_ko": [
1064
+ "스와이프 삭제 + 별도 삭제 버튼 제공"
1065
+ ],
1066
+ "components": [
1067
+ "widget"
1068
+ ],
1069
+ "newIn22": true,
1070
+ "sources": [
1071
+ "kwcag22-a11ykr",
1072
+ "kwcag22-websoul"
1073
+ ]
1074
+ },
1075
+ {
1076
+ "id": "6.5.2",
1077
+ "alias": "2.5.2",
1078
+ "principle": {
1079
+ "no": 6,
1080
+ "alias": 2,
1081
+ "name": "운용의 용이성"
1082
+ },
1083
+ "guideline": {
1084
+ "no": "6.5",
1085
+ "alias": "2.5",
1086
+ "name": "입력 방식"
1087
+ },
1088
+ "name_ko": "포인터 입력 취소",
1089
+ "name_en": null,
1090
+ "requirement_ko": "단일 포인터 입력으로 실행되는 기능은 취소할 수 있어야 한다.",
1091
+ "summary_ko": "단일 포인터로 실행되는 기능은 완료 전 취소할 수 있어야 한다(mousedown 즉시 실행 금지).",
1092
+ "wcag": [
1093
+ {
1094
+ "sc": "2.5.2",
1095
+ "level": "A"
1096
+ }
1097
+ ],
1098
+ "automation": "assist",
1099
+ "axeRules": [],
1100
+ "kRules": [
1101
+ "k-down-event-action"
1102
+ ],
1103
+ "bRules": [],
1104
+ "testMethod_ko": [
1105
+ "버튼 동작이 mousedown/pointerdown 시점이 아니라 클릭 완료(mouseup) 시점에 실행되는지 확인한다."
1106
+ ],
1107
+ "commonErrors_ko": [
1108
+ "mousedown에서 즉시 삭제 등 실행"
1109
+ ],
1110
+ "passExamples_ko": [
1111
+ "click 이벤트(포인터를 뗄 때)에서 실행"
1112
+ ],
1113
+ "components": [
1114
+ "widget"
1115
+ ],
1116
+ "newIn22": true,
1117
+ "sources": [
1118
+ "kwcag22-a11ykr",
1119
+ "kwcag22-websoul"
1120
+ ]
1121
+ },
1122
+ {
1123
+ "id": "6.5.3",
1124
+ "alias": "2.5.3",
1125
+ "principle": {
1126
+ "no": 6,
1127
+ "alias": 2,
1128
+ "name": "운용의 용이성"
1129
+ },
1130
+ "guideline": {
1131
+ "no": "6.5",
1132
+ "alias": "2.5",
1133
+ "name": "입력 방식"
1134
+ },
1135
+ "name_ko": "레이블과 네임",
1136
+ "name_en": null,
1137
+ "requirement_ko": "텍스트 또는 텍스트 이미지가 포함된 레이블이 있는 사용자 인터페이스 구성요소는 네임에 시각적으로 표시되는 해당 텍스트를 포함해야 한다.",
1138
+ "summary_ko": "화면에 보이는 레이블 텍스트가 접근성 이름(name)에도 포함되어야 한다.",
1139
+ "wcag": [
1140
+ {
1141
+ "sc": "2.5.3",
1142
+ "level": "A"
1143
+ }
1144
+ ],
1145
+ "automation": "assist",
1146
+ "axeRules": [
1147
+ "label-content-name-mismatch"
1148
+ ],
1149
+ "kRules": [],
1150
+ "bRules": [],
1151
+ "testMethod_ko": [
1152
+ "버튼·링크의 시각적 텍스트와 accessible name(aria-label 등)이 일치하는지 확인한다."
1153
+ ],
1154
+ "commonErrors_ko": [
1155
+ "시각적으로 \"검색\"인데 aria-label=\"submit\""
1156
+ ],
1157
+ "passExamples_ko": [
1158
+ "시각 텍스트와 aria-label이 같은 문구 포함"
1159
+ ],
1160
+ "components": [
1161
+ "form",
1162
+ "widget"
1163
+ ],
1164
+ "newIn22": true,
1165
+ "sources": [
1166
+ "kwcag22-a11ykr",
1167
+ "kwcag22-websoul"
1168
+ ]
1169
+ },
1170
+ {
1171
+ "id": "6.5.4",
1172
+ "alias": "2.5.4",
1173
+ "principle": {
1174
+ "no": 6,
1175
+ "alias": 2,
1176
+ "name": "운용의 용이성"
1177
+ },
1178
+ "guideline": {
1179
+ "no": "6.5",
1180
+ "alias": "2.5",
1181
+ "name": "입력 방식"
1182
+ },
1183
+ "name_ko": "동작기반 작동",
1184
+ "name_en": null,
1185
+ "requirement_ko": "동작기반으로 작동하는 기능은 사용자 인터페이스 구성요소로 조작할 수 있고, 동작기반 기능을 비활성화할 수 있어야 한다.",
1186
+ "summary_ko": "기기를 흔들거나 기울이는 동작으로 작동하는 기능은 UI 컨트롤로도 조작 가능해야 하고 끌 수 있어야 한다.",
1187
+ "wcag": [
1188
+ {
1189
+ "sc": "2.5.4",
1190
+ "level": "A"
1191
+ }
1192
+ ],
1193
+ "automation": "manual",
1194
+ "axeRules": [],
1195
+ "kRules": [
1196
+ "k-device-motion"
1197
+ ],
1198
+ "bRules": [],
1199
+ "testMethod_ko": [
1200
+ "devicemotion/deviceorientation 이벤트 사용 여부와 UI 대안·끄기 옵션을 확인한다."
1201
+ ],
1202
+ "commonErrors_ko": [
1203
+ "흔들기로만 실행 취소, 버튼 대안 없음"
1204
+ ],
1205
+ "passExamples_ko": [
1206
+ "흔들기 기능에 \"실행 취소\" 버튼 병행 제공"
1207
+ ],
1208
+ "components": [],
1209
+ "newIn22": true,
1210
+ "sources": [
1211
+ "kwcag22-a11ykr",
1212
+ "kwcag22-websoul"
1213
+ ]
1214
+ },
1215
+ {
1216
+ "id": "7.1.1",
1217
+ "alias": "3.1.1",
1218
+ "principle": {
1219
+ "no": 7,
1220
+ "alias": 3,
1221
+ "name": "이해의 용이성"
1222
+ },
1223
+ "guideline": {
1224
+ "no": "7.1",
1225
+ "alias": "3.1",
1226
+ "name": "가독성"
1227
+ },
1228
+ "name_ko": "기본 언어 표시",
1229
+ "name_en": null,
1230
+ "requirement_ko": "주로 사용하는 언어를 명시해야 한다.",
1231
+ "summary_ko": "페이지의 주요 언어를 html lang 속성으로 명시한다.",
1232
+ "wcag": [
1233
+ {
1234
+ "sc": "3.1.1",
1235
+ "level": "A"
1236
+ }
1237
+ ],
1238
+ "automation": "auto",
1239
+ "axeRules": [
1240
+ "html-has-lang",
1241
+ "html-lang-valid",
1242
+ "html-xml-lang-mismatch",
1243
+ "valid-lang"
1244
+ ],
1245
+ "kRules": [
1246
+ "k-lang-ko-expected"
1247
+ ],
1248
+ "bRules": [],
1249
+ "testMethod_ko": [
1250
+ "<html lang> 값이 실제 콘텐츠 언어와 일치하는지 확인한다."
1251
+ ],
1252
+ "commonErrors_ko": [
1253
+ "lang 속성 누락",
1254
+ "본문은 한국어인데 lang=\"en\""
1255
+ ],
1256
+ "passExamples_ko": [
1257
+ "<html lang=\"ko\">"
1258
+ ],
1259
+ "components": [],
1260
+ "newIn22": false,
1261
+ "sources": [
1262
+ "kwcag22-a11ykr",
1263
+ "kwcag22-websoul"
1264
+ ]
1265
+ },
1266
+ {
1267
+ "id": "7.2.1",
1268
+ "alias": "3.2.1",
1269
+ "principle": {
1270
+ "no": 7,
1271
+ "alias": 3,
1272
+ "name": "이해의 용이성"
1273
+ },
1274
+ "guideline": {
1275
+ "no": "7.2",
1276
+ "alias": "3.2",
1277
+ "name": "예측 가능성"
1278
+ },
1279
+ "name_ko": "사용자 요구에 따른 실행",
1280
+ "name_en": null,
1281
+ "requirement_ko": "사용자가 의도하지 않은 기능(새 창, 초점에 의한 맥락 변화 등)은 실행되지 않아야 한다.",
1282
+ "summary_ko": "사용자가 의도하지 않은 새 창 열기·맥락 변화가 자동으로 실행되지 않아야 한다.",
1283
+ "wcag": [
1284
+ {
1285
+ "sc": "3.2.1",
1286
+ "level": "A"
1287
+ },
1288
+ {
1289
+ "sc": "3.2.2",
1290
+ "level": "A"
1291
+ }
1292
+ ],
1293
+ "automation": "assist",
1294
+ "axeRules": [],
1295
+ "kRules": [
1296
+ "k-new-window-notice",
1297
+ "k-select-onchange",
1298
+ "k-onload-popup"
1299
+ ],
1300
+ "bRules": [],
1301
+ "testMethod_ko": [
1302
+ "target=_blank 링크에 안내가 있는지, select 변경만으로 페이지 이동이 일어나는지 확인한다."
1303
+ ],
1304
+ "commonErrors_ko": [
1305
+ "\"새 창\" 안내 없이 target=_blank",
1306
+ "select onchange로 자동 이동"
1307
+ ],
1308
+ "passExamples_ko": [
1309
+ "새 창 링크 텍스트에 \"(새 창)\" 명시"
1310
+ ],
1311
+ "components": [
1312
+ "link"
1313
+ ],
1314
+ "newIn22": false,
1315
+ "sources": [
1316
+ "kwcag22-a11ykr",
1317
+ "kwcag22-websoul"
1318
+ ]
1319
+ },
1320
+ {
1321
+ "id": "7.2.2",
1322
+ "alias": "3.2.2",
1323
+ "principle": {
1324
+ "no": 7,
1325
+ "alias": 3,
1326
+ "name": "이해의 용이성"
1327
+ },
1328
+ "guideline": {
1329
+ "no": "7.2",
1330
+ "alias": "3.2",
1331
+ "name": "예측 가능성"
1332
+ },
1333
+ "name_ko": "찾기 쉬운 도움 정보",
1334
+ "name_en": null,
1335
+ "requirement_ko": "도움 정보가 제공되는 경우, 각 페이지에서 동일한 상대적인 순서로 접근할 수 있어야 한다.",
1336
+ "summary_ko": "도움말·문의 등 도움 정보는 여러 페이지에서 상대적으로 동일한 위치·순서로 제공한다.",
1337
+ "wcag": [
1338
+ {
1339
+ "sc": "3.2.6",
1340
+ "level": "A"
1341
+ }
1342
+ ],
1343
+ "automation": "manual",
1344
+ "axeRules": [],
1345
+ "kRules": [],
1346
+ "bRules": [],
1347
+ "testMethod_ko": [
1348
+ "여러 페이지의 도움말 링크 위치·탭 순서가 일관되는지 비교한다(수동)."
1349
+ ],
1350
+ "commonErrors_ko": [
1351
+ "페이지마다 고객센터 링크 위치가 다름"
1352
+ ],
1353
+ "passExamples_ko": [
1354
+ "모든 페이지 푸터 동일 위치에 도움말 링크"
1355
+ ],
1356
+ "components": [
1357
+ "navigation"
1358
+ ],
1359
+ "newIn22": true,
1360
+ "sources": [
1361
+ "kwcag22-a11ykr",
1362
+ "kwcag22-websoul"
1363
+ ]
1364
+ },
1365
+ {
1366
+ "id": "7.3.1",
1367
+ "alias": "3.3.1",
1368
+ "principle": {
1369
+ "no": 7,
1370
+ "alias": 3,
1371
+ "name": "이해의 용이성"
1372
+ },
1373
+ "guideline": {
1374
+ "no": "7.3",
1375
+ "alias": "3.3",
1376
+ "name": "입력 도움"
1377
+ },
1378
+ "name_ko": "오류 정정",
1379
+ "name_en": null,
1380
+ "requirement_ko": "입력 오류를 정정할 수 있는 방법을 제공해야 한다.",
1381
+ "summary_ko": "입력 오류가 발생하면 원인과 정정 방법을 안내한다.",
1382
+ "wcag": [
1383
+ {
1384
+ "sc": "3.3.1",
1385
+ "level": "A"
1386
+ },
1387
+ {
1388
+ "sc": "3.3.3",
1389
+ "level": "A"
1390
+ }
1391
+ ],
1392
+ "automation": "assist",
1393
+ "axeRules": [],
1394
+ "kRules": [
1395
+ "k-error-association"
1396
+ ],
1397
+ "bRules": [],
1398
+ "testMethod_ko": [
1399
+ "폼 제출 오류 시 어떤 필드가 왜 잘못됐는지 안내되는지 확인한다."
1400
+ ],
1401
+ "commonErrors_ko": [
1402
+ "\"오류가 발생했습니다\"만 표시하고 원인 미제공"
1403
+ ],
1404
+ "passExamples_ko": [
1405
+ "\"휴대전화 번호는 숫자 11자리로 입력하세요\"처럼 구체적 안내"
1406
+ ],
1407
+ "components": [
1408
+ "form"
1409
+ ],
1410
+ "newIn22": false,
1411
+ "sources": [
1412
+ "kwcag22-a11ykr",
1413
+ "kwcag22-websoul"
1414
+ ]
1415
+ },
1416
+ {
1417
+ "id": "7.3.2",
1418
+ "alias": "3.3.2",
1419
+ "principle": {
1420
+ "no": 7,
1421
+ "alias": 3,
1422
+ "name": "이해의 용이성"
1423
+ },
1424
+ "guideline": {
1425
+ "no": "7.3",
1426
+ "alias": "3.3",
1427
+ "name": "입력 도움"
1428
+ },
1429
+ "name_ko": "레이블 제공",
1430
+ "name_en": null,
1431
+ "requirement_ko": "사용자 입력에는 대응하는 레이블을 제공해야 한다.",
1432
+ "summary_ko": "입력 필드에는 대응하는 레이블(label)을 제공한다.",
1433
+ "wcag": [
1434
+ {
1435
+ "sc": "3.3.2",
1436
+ "level": "A"
1437
+ },
1438
+ {
1439
+ "sc": "1.3.1",
1440
+ "level": "A"
1441
+ },
1442
+ {
1443
+ "sc": "4.1.2",
1444
+ "level": "A"
1445
+ }
1446
+ ],
1447
+ "automation": "auto",
1448
+ "axeRules": [
1449
+ "label",
1450
+ "label-title-only",
1451
+ "select-name",
1452
+ "form-field-multiple-labels"
1453
+ ],
1454
+ "kRules": [
1455
+ "k-placeholder-only-label"
1456
+ ],
1457
+ "bRules": [],
1458
+ "testMethod_ko": [
1459
+ "input에 연결된 <label>이나 aria-label이 있는지 확인한다(placeholder만으로는 부족)."
1460
+ ],
1461
+ "commonErrors_ko": [
1462
+ "placeholder만 있고 label 없음"
1463
+ ],
1464
+ "passExamples_ko": [
1465
+ "<label for=\"email\">이메일</label>"
1466
+ ],
1467
+ "components": [
1468
+ "form"
1469
+ ],
1470
+ "newIn22": false,
1471
+ "sources": [
1472
+ "kwcag22-a11ykr",
1473
+ "kwcag22-websoul"
1474
+ ]
1475
+ },
1476
+ {
1477
+ "id": "7.3.3",
1478
+ "alias": "3.3.3",
1479
+ "principle": {
1480
+ "no": 7,
1481
+ "alias": 3,
1482
+ "name": "이해의 용이성"
1483
+ },
1484
+ "guideline": {
1485
+ "no": "7.3",
1486
+ "alias": "3.3",
1487
+ "name": "입력 도움"
1488
+ },
1489
+ "name_ko": "접근 가능한 인증",
1490
+ "name_en": null,
1491
+ "requirement_ko": "인증 과정은 인지 기능 테스트에만 의존해서는 안 된다.",
1492
+ "summary_ko": "인증 과정이 퍼즐 풀이 등 인지 기능 테스트에만 의존하지 않아야 한다(대안 제공).",
1493
+ "wcag": [
1494
+ {
1495
+ "sc": "3.3.8",
1496
+ "level": "A"
1497
+ }
1498
+ ],
1499
+ "automation": "assist",
1500
+ "axeRules": [],
1501
+ "kRules": [
1502
+ "k-captcha-detect"
1503
+ ],
1504
+ "bRules": [],
1505
+ "testMethod_ko": [
1506
+ "캡차 등 인증 수단에 오디오·대체 인증 등 대안이 있는지 확인한다."
1507
+ ],
1508
+ "commonErrors_ko": [
1509
+ "이미지 캡차만 제공하고 대안 없음"
1510
+ ],
1511
+ "passExamples_ko": [
1512
+ "캡차 + 이메일 인증 등 대체 수단 제공"
1513
+ ],
1514
+ "components": [
1515
+ "auth"
1516
+ ],
1517
+ "newIn22": true,
1518
+ "sources": [
1519
+ "kwcag22-a11ykr",
1520
+ "kwcag22-websoul"
1521
+ ]
1522
+ },
1523
+ {
1524
+ "id": "7.3.4",
1525
+ "alias": "3.3.4",
1526
+ "principle": {
1527
+ "no": 7,
1528
+ "alias": 3,
1529
+ "name": "이해의 용이성"
1530
+ },
1531
+ "guideline": {
1532
+ "no": "7.3",
1533
+ "alias": "3.3",
1534
+ "name": "입력 도움"
1535
+ },
1536
+ "name_ko": "반복 입력 정보",
1537
+ "name_en": null,
1538
+ "requirement_ko": "반복되는 입력 정보는 자동 입력 또는 선택 입력할 수 있어야 한다.",
1539
+ "summary_ko": "같은 세션에서 반복 입력해야 하는 정보는 자동완성·재사용할 수 있어야 한다.",
1540
+ "wcag": [
1541
+ {
1542
+ "sc": "3.3.7",
1543
+ "level": "A"
1544
+ }
1545
+ ],
1546
+ "automation": "assist",
1547
+ "axeRules": [
1548
+ "autocomplete-valid"
1549
+ ],
1550
+ "kRules": [
1551
+ "k-autocomplete-missing"
1552
+ ],
1553
+ "bRules": [],
1554
+ "testMethod_ko": [
1555
+ "이름·주소 등 필드에 autocomplete 속성이 있는지, 이전 입력값 재사용이 가능한지 확인한다."
1556
+ ],
1557
+ "commonErrors_ko": [
1558
+ "배송지 정보를 결제 단계에서 다시 전부 입력해야 함"
1559
+ ],
1560
+ "passExamples_ko": [
1561
+ "autocomplete=\"name\" 등 속성 부여, \"이전 정보와 동일\" 체크박스 제공"
1562
+ ],
1563
+ "components": [
1564
+ "form"
1565
+ ],
1566
+ "newIn22": true,
1567
+ "sources": [
1568
+ "kwcag22-a11ykr",
1569
+ "kwcag22-websoul"
1570
+ ]
1571
+ },
1572
+ {
1573
+ "id": "8.1.1",
1574
+ "alias": "4.1.1",
1575
+ "principle": {
1576
+ "no": 8,
1577
+ "alias": 4,
1578
+ "name": "견고성"
1579
+ },
1580
+ "guideline": {
1581
+ "no": "8.1",
1582
+ "alias": "4.1",
1583
+ "name": "문법 준수"
1584
+ },
1585
+ "name_ko": "마크업 오류 방지",
1586
+ "name_en": null,
1587
+ "requirement_ko": "마크업 언어의 요소는 열고 닫음, 중첩 관계 및 속성 선언에 오류가 없어야 한다.",
1588
+ "summary_ko": "요소의 열고 닫음, 중첩, 속성 선언에 문법 오류가 없어야 한다.",
1589
+ "wcag": [
1590
+ {
1591
+ "sc": "4.1.1",
1592
+ "level": "A"
1593
+ }
1594
+ ],
1595
+ "automation": "auto",
1596
+ "axeRules": [
1597
+ "duplicate-id-active",
1598
+ "duplicate-id-aria"
1599
+ ],
1600
+ "kRules": [
1601
+ "k-parse-errors"
1602
+ ],
1603
+ "bRules": [],
1604
+ "testMethod_ko": [
1605
+ "HTML 파서로 태그 닫힘·중첩·중복 id 오류를 검사한다."
1606
+ ],
1607
+ "commonErrors_ko": [
1608
+ "id 속성 중복",
1609
+ "태그를 닫지 않음"
1610
+ ],
1611
+ "passExamples_ko": [
1612
+ "유효성 검사기를 통과하는 마크업"
1613
+ ],
1614
+ "components": [],
1615
+ "newIn22": false,
1616
+ "sources": [
1617
+ "kwcag22-a11ykr",
1618
+ "kwcag22-websoul"
1619
+ ]
1620
+ },
1621
+ {
1622
+ "id": "8.2.1",
1623
+ "alias": "4.2.1",
1624
+ "principle": {
1625
+ "no": 8,
1626
+ "alias": 4,
1627
+ "name": "견고성"
1628
+ },
1629
+ "guideline": {
1630
+ "no": "8.2",
1631
+ "alias": "4.2",
1632
+ "name": "웹 애플리케이션 접근성"
1633
+ },
1634
+ "name_ko": "웹 애플리케이션 접근성 준수",
1635
+ "name_en": null,
1636
+ "requirement_ko": "콘텐츠에 포함된 웹 애플리케이션은 접근성이 있어야 한다.",
1637
+ "summary_ko": "웹 애플리케이션(위젯 등)에 사용된 ARIA 역할·속성이 접근성 API 규격에 맞아야 한다.",
1638
+ "wcag": [
1639
+ {
1640
+ "sc": "4.1.2",
1641
+ "level": "A"
1642
+ }
1643
+ ],
1644
+ "automation": "assist",
1645
+ "axeRules": [
1646
+ "aria-allowed-attr",
1647
+ "aria-required-attr",
1648
+ "aria-roles",
1649
+ "aria-valid-attr",
1650
+ "aria-valid-attr-value",
1651
+ "aria-hidden-focus",
1652
+ "aria-hidden-body",
1653
+ "button-name",
1654
+ "aria-command-name",
1655
+ "aria-input-field-name",
1656
+ "aria-toggle-field-name",
1657
+ "aria-dialog-name",
1658
+ "aria-progressbar-name",
1659
+ "aria-tooltip-name",
1660
+ "aria-treeitem-name",
1661
+ "presentation-role-conflict"
1662
+ ],
1663
+ "kRules": [],
1664
+ "bRules": [
1665
+ "b-widget-keyboard"
1666
+ ],
1667
+ "testMethod_ko": [
1668
+ "커스텀 위젯의 role·aria-* 속성이 유효하고 name을 갖는지 확인한다."
1669
+ ],
1670
+ "commonErrors_ko": [
1671
+ "버튼 역할인데 접근 가능한 이름 없음",
1672
+ "잘못된 aria 속성값"
1673
+ ],
1674
+ "passExamples_ko": [
1675
+ "role=\"dialog\" + aria-labelledby로 이름 제공"
1676
+ ],
1677
+ "components": [
1678
+ "modal",
1679
+ "widget"
1680
+ ],
1681
+ "newIn22": false,
1682
+ "sources": [
1683
+ "kwcag22-a11ykr",
1684
+ "kwcag22-websoul"
1685
+ ]
1686
+ }
1687
+ ]
1688
+ }