์๋ฌธ ์ ๋ชฉ: Your Dialog Has role='dialog'. That Doesn't Make It Accessible. ์๋ฌธ ๋งํฌ: https://dev.to/vmvenkatesh78/your-dialog-has-roledialog-that-doesnt-make-it-accessible-4lha ๋ฒ์ญ์ผ: 2026-03-09 KST
๋ง์ ์ปดํฌ๋ํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ค์ด์ผ๋ก๊ทธ ํจ๋์ role="dialog"์ aria-modal="true"๋ฅผ ๋ถ์ฌ ๋๊ณ ์ ๊ทผ์ฑ์ ๋๋๋ค๊ณ ์๊ฐํ๋ค. ํ์ง๋ง ํค๋ณด๋๋ก ์ค์ ์ฌ์ฉํด ๋ณด๋ฉด ๋ฌธ์ ๊ฐ ๋ฐ๋ก ๋๋ฌ๋๋ค.
๋ค์ด์ผ๋ก๊ทธ๋ฅผ ์ฐ ๋ค Tab์ ๋๋ ์ ๋ ํฌ์ปค์ค๊ฐ ๋ฐฐ๊ฒฝ ํ์ด์ง๋ก ๋น ์ง๋ฉด ๊ทธ ๋ค์ด์ผ๋ก๊ทธ๋ ์ ๊ทผ ๊ฐ๋ฅํ์ง ์๋ค. ํฌ์ปค์ค๊ฐ ๋ด๋ถ ์์ ์ฌ์ด๋ฅผ ์ํํ์ง ์์ผ๋ฉด ํฌ์ปค์ค ํธ๋ฉ์ด ์๋ ๊ฒ์ด๊ณ , Escape๋ฅผ ๋๋ฌ๋ ๋ซํ์ง ์๊ฑฐ๋ ํธ๋ฆฌ๊ฑฐ ๋ฒํผ์ผ๋ก ํฌ์ปค์ค๊ฐ ๋์์ค์ง ์์ผ๋ฉด ํค๋ณด๋ ์ฌ์ฉ์๋ ๊ธธ์ ์๋๋ค.
role="dialog"๋ ์คํฌ๋ฆฐ๋ฆฌ๋์๊ฒ โ์ด๊ฑด ๋ค์ด์ผ๋ก๊ทธ๋คโ๋ผ๊ณ ์๋ ค ์ฃผ๋ ๋ผ๋ฒจ์ผ ๋ฟ์ด๋ค. ํฌ์ปค์ค๋ฅผ ๊ฐ๋์ง๋ ์๊ณ , Escape๋ฅผ ์ฒ๋ฆฌํ์ง๋ ์๊ณ , ๋ซํ ๋ ํฌ์ปค์ค๋ฅผ ๋ณต์ํ์ง๋ ์๊ณ , ๋ฐฐ๊ฒฝ ํด๋ฆญ์ ๋ง์ ์ฃผ์ง๋ ์๋๋ค. ์ง์ง ์ ๊ทผ์ฑ์ ์์ฑ์ด ์๋๋ผ ๋์์ ์กฐํฉ์์ ๋์จ๋ค.
์์ฑ์๋ flintwork๋ผ๋ ํค๋๋ฆฌ์ค ๋์์ธ ์์คํ ์ ๋ง๋ค๋ฉฐ ์ด ๋์๋ค์ ์ง์ ๊ตฌํํ๋ค. ์ฌ๊ธฐ์๋ ํญ ๊ฐ๋ฅํ ์์ ๊ฐ์ง, ํฌ์ปค์ค ํธ๋ฉ, ๋ฐ๊นฅ ํด๋ฆญ ์ฒ๋ฆฌ, Escape ์ฒ๋ฆฌ, ํธ๋ฆฌ๊ฑฐ๋ก ํฌ์ปค์ค ๋ณต์, ์ด๊ธฐ ํฌ์ปค์ค ์ง์ ๊ฐ์ ๋ ๋ฆฝ์ ์ธ ํ๋์ด ๋ชจ๋ ํ์ํ๋ค.
์ฌ๋ฐ๋ฅด๊ฒ ๊ตฌํ๋ ๋ค์ด์ผ๋ก๊ทธ ํธ๋ฆฌ๊ฑฐ๋ โOpen settings, button, dialog popupโ์ฒ๋ผ ์ถฉ๋ถํ ๋งฅ๋ฝ์ ์ ๊ณตํ๋ค. ์ฌ๊ธฐ์๋ ๋ฒํผ ํ
์คํธ, ์์ ์ญํ , ๊ทธ๋ฆฌ๊ณ aria-haspopup="dialog"๊ฐ ํจ๊ป ์๋ํ๋ค.
๋ค์ด์ผ๋ก๊ทธ๊ฐ ์ด๋ฆฌ๋ฉด VoiceOver๋ โSettings, dialog. Update your preferences.โ์ฒ๋ผ ์ ๋ชฉ๊ณผ ์ค๋ช
์ ์ฝ์ด ์ค๋ค. ์ด๋ ์ ๋ชฉ์ aria-labelledby, ์ค๋ช
์ aria-describedby์์ ์จ๋ค. aria-labelledby๊ฐ ์์ผ๋ฉด ๋จ์ํ โdialogโ๋ง ์ฝํ์ ์ฌ์ฉ์๋ ์ด UI๊ฐ ๋ฌด์์ธ์ง ์ค์ค๋ก ํ์ํด ์์๋ด์ผ ํ๋ค.
Escape๋ฅผ ๋๋ฌ ๋ซ์์ ๋ ๋ค์ ํธ๋ฆฌ๊ฑฐ ๋ฒํผ์ผ๋ก ํฌ์ปค์ค๊ฐ ๋์๊ฐ๋ฉด ์ฌ์ฉ์๋ ์๋ ์์
๋งฅ๋ฝ์ ์ ์งํ ์ ์๋ค. ๋ฐ๋๋ก ํฌ์ปค์ค ๋ณต์์ด ์์ผ๋ฉด <body>๋ ํ์ด์ง์ ์ฒซ ๋ฒ์งธ ํฌ์ปค์ค ๊ฐ๋ฅํ ์์๋ก ํ์ด ๋ฒ๋ ค ์์น ๊ฐ๊ฐ์ ์๋๋ค.
์ฆ, ARIA ์์ฑ์ ๋จ์ํ ์ฒดํฌ๋ฆฌ์คํธ๊ฐ ์๋๋ผ ์ค๋์ค UX๋ฅผ ๊ตฌ์ฑํ๋ ์์๋ค. ์ค์ ๋ก ๋ค์ด ๋ณด๋ฉด ์ ์ค์ํ์ง ์ฆ์ ์ฒด๊ฐํ๊ฒ ๋๋ค.
์ฒ์์ ๋ค์์ฒ๋ผ ๋จ์ผ Dialog ์ปดํฌ๋ํธ๊ฐ ๊น๋ํด ๋ณด์ผ ์ ์๋ค.
<Dialog triggerText="Open" title="Confirm" onConfirm={handleConfirm} />ํ์ง๋ง ๊ณง ์๊ตฌ์ฌํญ์ด ๋์ด๋๋ค. ์ปค์คํ ํธ๋ฆฌ๊ฑฐ, ํผ ์ฝํ ์ธ , ์ฌ๋ฌ ์ก์ ๋ฒํผ, ๋ซ๊ธฐ ๋ฒํผ ์์น ์ปค์คํฐ๋ง์ด์ฆ๊ฐ ํ์ํด์ง๋ฉด prop๊ฐ ํญ์ฆํ๊ณ ๊ตฌ์กฐ๋ ๊ธ๋ฐฉ ๊ฒฝ์ง๋๋ค.
์์ฑ์๋ ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด compound component ํจํด์ ์ ํํ๋ค.
<Dialog open={open} onOpenChange={setOpen}>
<Dialog.Trigger>
<button>Open settings</button>
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay />
<Dialog.Content>
<Dialog.Title>Settings</Dialog.Title>
<Dialog.Description>Update your preferences.</Dialog.Description>
<Dialog.Close>
<button>Done</button>
</Dialog.Close>
</Dialog.Content>
</Dialog.Portal>
</Dialog>์ด ๊ตฌ์กฐ์์๋ ์๋น์๊ฐ ๋งํฌ์
๊ตฌ์กฐ๋ฅผ ์์ ๋กญ๊ฒ ๋ฐฐ์นํ๊ณ , ๊ฐ ํ์ ์ปดํฌ๋ํธ๊ฐ ํ์ํ ์ ๊ทผ์ฑ ์์ฑ๊ณผ ํ๋์ ์๋์ผ๋ก ๋ด๋นํ๋ค. ์๋ฅผ ๋ค์ด Dialog.Trigger๋ aria-haspopup="dialog"์ aria-expanded๋ฅผ, Dialog.Content๋ role="dialog"์ aria-modal="true"๋ฅผ ๋งก๋๋ค.
์ ๊ทผ ๊ฐ๋ฅํ ๋ชจ๋ฌ์ ํต์ฌ์ ํฌ์ปค์ค๊ฐ ๋ด๋ถ์๋ง ๋จธ๋ฌผ๊ฒ ํ๋ ๊ฒ์ด๋ค. ์์ฑ์๋ Tab/Shift+Tab์ ๊ฐ์งํ๊ณ , ํ์ฌ ๋ค์ด์ผ๋ก๊ทธ ์์ ํฌ์ปค์ค ๊ฐ๋ฅํ ์์ ๋ชฉ๋ก์ ๊ณ์ฐํ ๋ค, ๋ง์ง๋ง ์์์์ Tab์ ๋๋ฅด๋ฉด ์ฒ์์ผ๋ก, ์ฒซ ์์์์ Shift+Tab์ ๋๋ฅด๋ฉด ๋ง์ง๋ง์ผ๋ก ์ด๋์ํค๋ ๋ฐฉ์์ ๊ตฌํํ๋ค.
ํ์ง๋ง ์ค์ ๊ตฌํ์ ๋จ์ํ์ง ์๋ค. ์จ๊น ์์๋ ๋นํ์ฑ ์์๋ฅผ ์ ์ธํด์ผ ํ๊ณ , ๋ผ๋์ค ๊ทธ๋ฃน์ฒ๋ผ ํน์ํ ํฌ์ปค์ค ๊ท์น์ ๊ฐ์ง ์์๋ ๊ณ ๋ คํด์ผ ํ๋ค. ๋ค์ด์ผ๋ก๊ทธ๊ฐ ๋น์ด ์๊ฑฐ๋ ํฌ์ปค์ค ๊ฐ๋ฅํ ์์๊ฐ ํ๋๋ ์์ ๋์ fallback๋ ํ์ํ๋ค.
์ด๋ฐ ์ด์ ๋ก โํฌ์ปค์ค๋ฅผ ๊ฐ๋๋คโ๋ ๋ง์ ์งง์ง๋ง, ์ค์ ์ ํ ์์ค์ ๊ตฌํ์ ๋ง์ ์ฃ์ง ์ผ์ด์ค๋ฅผ ํฌํจํ๋ค.
์ฌ์ฉ์๋ ์ค๋ฒ๋ ์ด ๋ฐ๊นฅ์ ํด๋ฆญํ์ ๋ ๋ค์ด์ผ๋ก๊ทธ๊ฐ ๋ซํ๊ธธ ๊ธฐ๋ํ๋ค. ํ์ง๋ง pointerdown, pointerup, drag ๊ฐ์ ์ด๋ฒคํธ ํ๋ฆ์ ์ ๋๋ก ๋ค๋ฃจ์ง ์์ผ๋ฉด ๋ด๋ถ์์ ์์ํ ๋๋๊ทธ๊ฐ ์ธ๋ถ์์ ๋๋ฌ์ ๋ ์๋ชป ๋ซํ๊ฑฐ๋, ๋ฐ๋๋ก ์ธ๋ถ ํด๋ฆญ์ด ๋ฌด์๋ ์ ์๋ค.
๋ฐ๋ผ์ ๋จ์ํ event.target๋ง ๋ณด๋ ๋ฐฉ์์ ๋ถ์ถฉ๋ถํ๋ค. ์ํธ์์ฉ์ ์์์ ๊ณผ ๋์ , ์ค๋ฒ๋ ์ด์ ์ฝํ
์ธ ์ ๊ฒฝ๊ณ, ํฌ์ธํฐ ์ด๋ฒคํธ์ ์์๋ฅผ ๋ชจ๋ ๊ณ ๋ คํด์ผ ํ๋ค.
Escape๋ ๊ฐ์ฅ ์ต์ํ ์ข ๋ฃ ๋ฐฉ์ ์ค ํ๋๋ค. ํ์ง๋ง ๋ถ๋ชจ ์ปดํฌ๋ํธ๋ ๋ค๋ฅธ ๋ ์ด์ด์ ํค ์ด๋ฒคํธ๊ฐ ์์ด ๋๊ฐ์ง ์๋๋ก ํด์ผ ํ๋ฉฐ, ๋ซํ ๋ค์๋ ์๋ ๋ค์ด์ผ๋ก๊ทธ๋ฅผ ์ฐ ํธ๋ฆฌ๊ฑฐ ์์๋ก ํฌ์ปค์ค๋ฅผ ๋๋๋ ค์ผ ํ๋ค.
์ด ํฌ์ปค์ค ๋ณต์์ ์ฌ์ฉ์์ ๋งฅ๋ฝ ์ ์ง์ ๊ฒฐ์ ์ ์ด๋ค. ์๊ฐ์ ์ผ๋ก๋ ์ฌ์ํด ๋ณด์ฌ๋ ํค๋ณด๋ ์ฌ์ฉ์์ ์คํฌ๋ฆฐ๋ฆฌ๋ ์ฌ์ฉ์์๊ฒ๋ ํ์ ํ๋์ด๋ค.
๋ค์ด์ผ๋ก๊ทธ๊ฐ ์ด๋ฆด ๋ ์ด๋์ ํฌ์ปค์ค๋ฅผ ๋์ง๋ ์ค์ํ๋ค. ๋ณดํต์ ๋ค์ ์ฐ์ ์์๋ฅผ ๋๋ค.
- ๋ช ์์ ์ผ๋ก ์ง์ ๋ ์ด๊ธฐ ํฌ์ปค์ค ๋์
- ๋ค์ด์ผ๋ก๊ทธ ๋ด๋ถ์ ์ฒซ ๋ฒ์งธ ์๋ฏธ ์๋ ํฌ์ปค์ค ๊ฐ๋ฅํ ์์
- ํ์ํ๋ค๋ฉด ๋ค์ด์ผ๋ก๊ทธ ์ปจํ ์ด๋ ์์ฒด
์ด ์ฐ์ ์์๊ฐ ์์ผ๋ฉด ์ฌ์ฉ์๋ ๋ค์ด์ผ๋ก๊ทธ๊ฐ ์ด๋ฆฐ ์ฌ์ค์ ์ฆ์ ์ธ์งํ์ง ๋ชปํ๊ฑฐ๋, ์๋ฑํ ์์น์์ ํ์์ ์์ํ๊ฒ ๋๋ค.
์ ๊ทผ ๊ฐ๋ฅํ ๋ค์ด์ผ๋ก๊ทธ๋ ARIA ์์ฑ์ ๋ช ๊ฐ ๋ถ์ด๋ ๋ฌธ์ ๋ก ๋๋์ง ์๋๋ค. ํฌ์ปค์ค ํธ๋ฉ, ์ด๊ธฐ ํฌ์ปค์ค, Escape, ๋ฐ๊นฅ ํด๋ฆญ ์ฒ๋ฆฌ, ํฌ์ปค์ค ๋ณต์๊น์ง ํฌํจํ ์ํธ์์ฉ ์ ์ฒด๊ฐ ์ค๊ณ๋์ด์ผ ํ๋ค. FE ์ค๋ฌด์์ โ์ ๊ทผ์ฑ ์ง์โ์ ์ฃผ์ฅํ๋ ค๋ฉด ์๋งจํฑ๊ณผ ํ๋์ ํจ๊ป ์ ๊ณตํด์ผ ํ๋ค.