์๋ฐ์คํฌ๋ฆฝํธ๋ก ํญ ๊ธฐ๋ฅ ๋ง๋ค๊ธฐ (tab)
๐งญ ์น UI๋ฅผ ๋ค๋ฃจ๋ ๊ธฐ๋ณธ๊ธฐ – ํญ ๊ธฐ๋ฅ๋ถํฐ ํํํ๊ฒ
์น์ฌ์ดํธ๋ฅผ ์ฒ์ ๋ฐฉ๋ฌธํ ์ฌ์ฉ์๊ฐ ๊ฐ์ฅ ๋จผ์ ์ ํ๋ UI ์์ ์ค ํ๋๊ฐ ํญ ๋ฉ๋ด์ ๋๋ค.
์ ๋ณด๊ฐ ๋ง์์๋ก ์ฌ์ฉ์์๊ฒ ๋ณต์กํ๊ฒ ๋๊ปด์ง๊ธฐ ์ฌ์ด๋ฐ,
ํญ์ ์ด๋ฐ ๋ด์ฉ์ ์ฃผ์ ๋ณ๋ก ๋๋ ๊ฐ๋ ์ฑ๊ณผ ๊ฒฝํ์ ๋์์ ์ก์ ์ ์๋ ํ๋ฅญํ ๋๊ตฌ์์.
์ค๋์ ์์ ๋ฐ๋๋ผ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ํญ ๊ธฐ๋ฅ์ ๋ง๋๋ ๋ฐฉ๋ฒ๊ณผ ํจ๊ป
์ ๊ทผ์ฑ(Accessibility)๊น์ง ์ฑ๊ธฐ๋ ํ์ ์๊ฐํฉ๋๋ค.
๐ฏ ํญ UI๋?
ํญ ๋ฉ๋ด๋ ์ฌ๋ฌ ์ ๋ณด ๋ธ๋ก์ ๊ฒน์ณ๋๊ณ , ์ฌ์ฉ์๊ฐ ํด๋ฆญํ๋ ํญ์ ๋ฐ๋ผ ํด๋น ์ฝํ ์ธ ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ตฌ์กฐ์ ๋๋ค.
FAQ, ์ ํ ์ฌ์, ๋ฉค๋ฒ ํ๋กํ, ์นดํ ๊ณ ๋ฆฌ ๊ตฌ๋ถ ๋ฑ ๋ค์ํ ์ํฉ์ ํ์ฉ๋์ฃ .
๐งฑ HTML ๊ตฌ์กฐ๋ถํฐ ์ค๋นํ๊ธฐ
๋จผ์ ํญ ๋ฒํผ๊ณผ ์ฝํ ์ธ ์์ญ์ HTML๋ก ๊ตฌ์ฑํฉ๋๋ค.
<div class="tabs">
<ul class="tab-buttons">
<li class="active">ํญ 1</li>
<li>ํญ 2</li>
<li>ํญ 3</li>
</ul>
<div class="tab-contents">
<div class="tab-content active">๋ด์ฉ 1</div>
<div class="tab-content">๋ด์ฉ 2</div>
<div class="tab-content">๋ด์ฉ 3</div>
</div>
</div>
๐จ CSS ์คํ์ผ๋ง์ผ๋ก ์๊ฐ์ ํผ๋๋ฐฑ ์ฃผ๊ธฐ
.tab-content { display: none; }
.tab-content.active { display: block; }
.tab-buttons li.active { font-weight: bold; }
๐ง ์๋ฐ์คํฌ๋ฆฝํธ๋ก ํญ ๋์ ๊ตฌํ
const tabButtons = document.querySelectorAll('.tab-buttons li');
const tabContents = document.querySelectorAll('.tab-content');
tabButtons.forEach((btn, index) => {
btn.addEventListener('click', () => {
tabButtons.forEach(b => b.classList.remove('active'));
tabContents.forEach(c => c.classList.remove('active'));
btn.classList.add('active');
tabContents[index].classList.add('active');
});
});
๐ ์๋ฐ์คํฌ๋ฆฝํธ ํญ์๋ ์๋ฏธ ์๋ HTML ๊ตฌ์กฐ ์ฐ๊ธฐ
- <button> ์์๋ฅผ ์ฌ์ฉํ๋ฉด ์ ๊ทผ์ฑ์ ๋ ์ ๋ฆฌํฉ๋๋ค.
- ๊ฐ ์ฝํ ์ธ ์ aria-labelledby, role="tabpanel" ๊ฐ์ ์์ฑ์ ์ฌ์ฉํด ๊ฒ์์์ง๊ณผ ์คํฌ๋ฆฐ๋ฆฌ๋๋ ๋ด์ฉ์ ์ธ์ํ ์ ์๊ฒ ๋ง๋์ธ์.
- ํญ ์ด๋ฆ์ ํค์๋๋ฅผ ๋ฃ์ด ์ฝํ ์ธ ๊ฐ์์ฑ์ ๋์ด๋ ๊ฒ๋ ํ์ ๋๋ค.
์ ๊ทผ์ฑ์ ๊ณ ๋ คํ๋ฉด ๋ ๋ง์ ์ฌ์ฉ์,
ํนํ ์คํฌ๋ฆฐ ๋ฆฌ๋ ์ฌ์ฉ์๋ ํค๋ณด๋๋ง ์ฌ์ฉํ๋ ์ฌ๋๋ค์๊ฒ๋
ํญ ๊ธฐ๋ฅ์ ํธ๋ฆฌํ๊ฒ ์ ๊ณตํ ์ ์์ด์.
โฟ ์ ๊ทผ์ฑ๋ ์ฑ๊ธฐ์ – ๋๊ตฌ๋ ์ฐ๊ธฐ ์ฌ์ด UI ๋ง๋ค๊ธฐ
๊ธฐ๋ฅ ๊ตฌํ๋งํผ ์ค์ํ ๊ฒ์ด ๋ชจ๋๊ฐ ์ฌ์ฉํ ์ ์๋ ํ๊ฒฝ์ ๋๋ค.
ํค๋ณด๋๋ง ์ฐ๋ ์ฌ์ฉ์, ํ๋ฉด ๋ญ๋ ๊ธฐ ์ฌ์ฉ์์๊ฒ๋ ์๋ฒฝํ๊ฒ ์๋ํ๋ ค๋ฉด ์๋ ์์๋ค์ ๊ณ ๋ คํด์ผ ํฉ๋๋ค:
- ์๋งจํฑํ HTML ์ฌ์ฉ (<button> ์์, role="tablist" ๋ฑ)
- ARIA ์์ฑ ์ถ๊ฐ (aria-selected, aria-controls, aria-labelledby ๋ฑ)
- ํค๋ณด๋ ํ์ ์ง์ (keydown ์ด๋ฒคํธ, ๋ฐฉํฅํค ์ด๋)
- ํฌ์ปค์ค ์คํ์ผ ์ถ๊ฐ ๋ฐ tabindex="0" ์ง์
โ ์ ์ ๊ทผ์ฑ์ด ์ค์ํ ๊น์?
๋ชจ๋ ์ฌ์ฉ์๊ฐ ๋๋ฑํ ์ ๋ณด ์ ๊ทผ๊ณผ ์น ์ฌ์ฉ ๊ฒฝํ์ ๋๋ฆฌ๋๋ก ํ๋ ค๋ฉด ์น ์์์ ์๋ฏธ์ ๊ตฌ์กฐ๋ฅผ ์ ์ ๋ฌํด์ผ ํฉ๋๋ค. ํญ ๊ธฐ๋ฅ๋ ์์ธ๋ ์๋์์. ์คํฌ๋ฆฐ ๋ฆฌ๋๋ ํค๋ณด๋๋ง ์ฌ์ฉํ๋ ์ฌ์ฉ์๋ ๊ฐ ํญ์ด ๋ญ ๋ํ๋ด๋์ง ์ฝ๊ฒ ์ดํดํ ์ ์์ด์ผ ํฉ๋๋ค.
๐งฑ HTML ๊ตฌ์กฐ: ์๋งจํฑ ์์ & ARIA ์์ฑ ์ถ๊ฐ
<div class="tabs" role="tablist" aria-label="์ ๋ณด ํญ">
<button role="tab" aria-selected="true" aria-controls="panel-1" id="tab-1">ํญ 1</button>
<button role="tab" aria-selected="false" aria-controls="panel-2" id="tab-2">ํญ 2</button>
<button role="tab" aria-selected="false" aria-controls="panel-3" id="tab-3">ํญ 3</button>
<div id="panel-1" role="tabpanel" aria-labelledby="tab-1">๋ด์ฉ 1</div>
<div id="panel-2" role="tabpanel" aria-labelledby="tab-2" hidden>๋ด์ฉ 2</div>
<div id="panel-3" role="tabpanel" aria-labelledby="tab-3" hidden>๋ด์ฉ 3</div>
</div>
๐ฏ ์๋ฐ์คํฌ๋ฆฝํธ ์ ๊ทผ์ฑ ๋์: aria-selected์ hidden ์ฒ๋ฆฌ
const tabs = document.querySelectorAll('[role="tab"]');
const panels = document.querySelectorAll('[role="tabpanel"]');
tabs.forEach((tab, index) => {
tab.addEventListener('click', () => {
tabs.forEach(t => {
t.setAttribute('aria-selected', false);
t.classList.remove('active');
});
panels.forEach(p => p.hidden = true);
tab.setAttribute('aria-selected', true);
tab.classList.add('active');
panels[index].hidden = false;
});
});
๐ก ํค๋ณด๋ ์ฌ์ฉ์๋ ๊ณ ๋ คํ๋ฉด ์์ฑ๋ ์ !
- ๋ฐฉํฅํค(←, →)๋ก ํญ ์ด๋ ๊ฐ๋ฅํ๊ฒ ํ๋ ค๋ฉด keydown ์ด๋ฒคํธ๋ ์ถ๊ฐํ๋ฉด ์ข์์.
- focus() ๋ฉ์๋๋ฅผ ํ์ฉํด ํค๋ณด๋ ํฌ์ปค์ค๋ฅผ ๋ค์ ํญ์ผ๋ก ์ด๋์ํฌ ์ ์์ด์.
์ด๋ ๊ฒ ํ๋ฉด ์ ๊ทผ์ฑ ํ์ค(WCAG)๋ ์ถฉ์กฑํด์. ์น์ฌ์ดํธ ์ ๋ขฐ๋์ ์ฌ์ฉ์ ๋ง์กฑ๋๋ฅผ ๋ชจ๋ ๋์ผ ์ ์์ฃ .
๐ ๋ง๋ฌด๋ฆฌํ๋ฉฐ
์๋ฐ์คํฌ๋ฆฝํธ๋ก ํญ UI๋ฅผ ๊ตฌํํ๋ ๊ณผ์ ์ ๋จ์ํ ๋ฒํผ์ ๋๋ฅด๋ฉด ๋ด์ฉ์ด ๋ฐ๋๋ ์์ค์ ๋์ด,
์ฌ์ฉ์ ์ค์ฌ ์ค๊ณ์ ์น ํ์ค์ ๋ํ ์ดํด๋ฅผ ๋ํ ์ ์๋ ์ข์ ๊ธฐํ์ ๋๋ค.
์ฌ๊ธฐ์ ์ ๊ทผ์ฑ๊น์ง ์ฑ๊ธฐ๋ฉด ์ง์ง ์ค๋ฌด์ ๊ฐํ UI ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค ์ ์์ด์.
๋ค์ ํฌ์คํธ์์๋ ๋๋กญ๋ค์ด, ๋ชจ๋ฌ ์ฐฝ, ์ ๋๋ฉ์ด์ ๋ฑ ๋ ๋ค์ํ UI ๊ตฌ์ฑ ๋ฐฉ๋ฒ์ ์๊ฐํ ์์ ์ ๋๋ค.
UI ํ๋ํ๋์ ์จ์ ์ค๊ณ์ ์ฌ๋ฏธ๋ฅผ ํจ๊ป ๋ฐฐ์๊ฐ์! ๐
๊ตฌ๋ ๊ณผ ์ข์์๋ ๊ฐ๋ฐ์์๊ฒ ํฐ ํ์ด ๋ฉ๋๋ค. ๐