| ์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ | 
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 | 
| 9 | 10 | 11 | 12 | 13 | 14 | 15 | 
| 16 | 17 | 18 | 19 | 20 | 21 | 22 | 
| 23 | 24 | 25 | 26 | 27 | 28 | 29 | 
| 30 | 
- ํํธ๋ฆญ์ค
 - ๋คํฌ๋ชจ๋ํ ๊ธ
 - ui์ปดํฌ๋ํธ
 - ๋น๋ณด๋์ฐจํธ
 - ์ผ๋ฐํ
 - UIUX
 - ์น๊ฐ๋ฐ
 - ๋ทํ๋ฆญ์คost
 - js์คํฌ๋กค์ด๋ฒคํธ
 - ์ผ์ดํ๋ฐ๋ชฌํํฐ์ค
 - ์ฌ์๋ณด์ด์ฆ
 - ์น๋์์ธ
 - ์๋ฐ์คํฌ๋ฆฝํธui
 - ์๋ฐ์คํฌ๋ฆฝํธ
 - kpopdemonhunters
 - ๋ทํ๋ฆญ์ค์ ๋๋ฉ์ด์ 
 - Golden
 - ๋ฐ๋ง์ผํ
 - UX๋์์ธ
 - ๋ฐ๋๋ผ์คํฌ๋ฆฝํธ
 - ํ๋ก ํธ์๋
 - JavaScript
 - ์นUI
 - ์น์ ๊ทผ์ฑ
 - ์ ๊ทผ์ฑ
 - ๊ณจ๋
 - ๋ฐ๋๋ผjs
 - ๊ฐ์์์ด๋
 - ๋คํฌ๋ชจ๋
 - ์คํฌ๋กค์ ๋๋ฉ์ด์ 
 
- Today
 
- Total
 
UI Code Lab
์๋ฐ์คํฌ๋ฆฝํธ๋ก ํญ ๊ธฐ๋ฅ ๋ง๋ค๊ธฐ (tab) ๋ณธ๋ฌธ
์๋ฐ์คํฌ๋ฆฝํธ๋ก ํญ ๊ธฐ๋ฅ ๋ง๋ค๊ธฐ (tab)
๐ฏ๊ฟ์์ด๐ 2025. 6. 20. 09:45
๐งญ ์น 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 ํ๋ํ๋์ ์จ์ ์ค๊ณ์ ์ฌ๋ฏธ๋ฅผ ํจ๊ป ๋ฐฐ์๊ฐ์! ๐
๊ตฌ๋ ๊ณผ ์ข์์๋ ๊ฐ๋ฐ์์๊ฒ ํฐ ํ์ด ๋ฉ๋๋ค. ๐