μžλ°”μŠ€ν¬λ¦½νŠΈUI

μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ λ§Œλ“œλŠ” μ•Œλ¦Ό(Toast) μ»΄ν¬λ„ŒνŠΈ

πŸ―κΏ€μƒμ΄πŸ 2025. 7. 4. 10:37

μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ λ§Œλ“œλŠ” μ•Œλ¦Ό(Toast) μ»΄ν¬λ„ŒνŠΈ

 

 

πŸ“Œ κ°œμš”

 

Toast μ•Œλ¦Όμ€ μ‚¬μš©μžμ—κ²Œ λΉ λ₯΄κ³  κ°„λ‹¨ν•œ ν”Όλ“œλ°±μ„ μ œκ³΅ν•˜λŠ” UI μš”μ†Œμž…λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄ “μ €μž₯λ˜μ—ˆμŠ΅λ‹ˆλ‹€”처럼 ν™”λ©΄ μƒλ‹¨μ΄λ‚˜ ν•˜λ‹¨μ— 짧게 λ‚˜νƒ€λ‚˜λŠ” μ•Œλ¦Ό 말이죠.

 

이 κΈ€μ—μ„œλŠ” 바닐라 μžλ°”μŠ€ν¬λ¦½νŠΈ(Vanilla JS)만으둜

μž¬μ‚¬μš© κ°€λŠ₯ν•œ toast μ»΄ν¬λ„ŒνŠΈλ₯Ό λ§Œλ“œλŠ” 법을 μ†Œκ°œν•©λ‹ˆλ‹€.

 

  • βœ… 순수 JS둜 κ°€λ³κ²Œ κ΅¬ν˜„
  • βœ… μœ„μΉ˜, 지속 μ‹œκ°„, μ• λ‹ˆλ©”μ΄μ…˜ μ„€μ • κ°€λŠ₯
  • βœ… 슀크린 리더 μ‚¬μš©μžλ„ κ³ λ €ν•œ μ ‘κ·Όμ„±

 

πŸ’‘ Toast UIλž€?

ToastλŠ” ν™”λ©΄ ν•œμͺ½μ— λͺ‡ μ΄ˆκ°„ ν‘œμ‹œλ˜λŠ” μΌμ‹œμ μΈ λ©”μ‹œμ§€μž…λ‹ˆλ‹€.

μ‚¬μš©μžκ°€ λ³„λ„μ˜ μ‘°μž‘ 없이 ν”Όλ“œλ°±μ„ 받을 수 μžˆμ–΄ UX ν–₯상에 효과적이죠.

 

πŸ“ˆ 자주 μ“°μ΄λŠ” 상황 μ˜ˆμ‹œ

  • 폼 제좜 ν›„ “제좜이 μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€”
  • 볡사 λ²„νŠΌ 클릭 μ‹œ “ν΄λ¦½λ³΄λ“œμ— 볡사됨”
  • μ €μž₯, μ‚­μ œ, 였λ₯˜ μ•ˆλ‚΄ λ“±

 

 

πŸ› οΈ HTML ꡬ쑰

 
<div id="toast-container"></div>

 

toast-containerλŠ” ν† μŠ€νŠΈ λ©”μ‹œμ§€λ₯Ό κ°μ‹ΈλŠ” μ»¨ν…Œμ΄λ„ˆμž…λ‹ˆλ‹€.

μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ λ™μ μœΌλ‘œ λ©”μ‹œμ§€λ₯Ό μ‚½μž…ν•΄ μ‚¬μš©ν•  μ˜ˆμ •μ΄μ—μš”.

 

 

🎨 CSS μŠ€νƒ€μΌ

#toast-container {
  position: fixed;
  top: 1.5rem;
  right: 1.5rem;
  z-index: 9999;
}
.toast {
  background: #333;
  color: #fff;
  padding: 0.75rem 1.2rem;
  margin-top: 0.5rem;
  border-radius: 4px;
  opacity: 0;
  transform: translateY(-10px);
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.toast.show {
  opacity: 1;
  transform: translateY(0);
}

 

βš™οΈ μžλ°”μŠ€ν¬λ¦½νŠΈ 둜직

function showToast(message, duration = 3000) {
  const container = document.getElementById('toast-container');
  const toast = document.createElement('div');
  toast.className = 'toast';
  toast.innerText = message;

  container.appendChild(toast);

  // ν‘œμ‹œ
  requestAnimationFrame(() => toast.classList.add('show'));

  // 사라지기
  setTimeout(() => {
    toast.classList.remove('show');
    toast.addEventListener('transitionend', () => toast.remove());
  }, duration);
}

 

βœ… μ ‘κ·Όμ„± κ³ λ € (a11y)

toast.setAttribute('role', 'alert');
toast.setAttribute('aria-live', 'assertive');
  • role="alert": 슀크린 리더가 μ¦‰μ‹œ μ½μ–΄μ€λ‹ˆλ‹€.
  • aria-live="assertive": κΈ΄κΈ‰ν•˜κ²Œ 전달할 ν•„μš”κ°€ μžˆμ„ 경우 μ‚¬μš©ν•©λ‹ˆλ‹€.

 

πŸ§ͺ μ‚¬μš© μ˜ˆμ‹œ

<button onclick="showToast('λ³΅μ‚¬λ˜μ—ˆμŠ΅λ‹ˆλ‹€!')">볡사</button>

 

πŸš€ ν™•μž₯ 포인트

  • βœ… ν† μŠ€νŠΈ μœ„μΉ˜ μ»€μŠ€ν„°λ§ˆμ΄μ§• (μ™Όμͺ½, κ°€μš΄λ° λ“±)
  • βœ… μ•„μ΄μ½˜, 색상 λ³€κ²½
  • βœ… 큐(queue) 처리: μ—¬λŸ¬ toastκ°€ κ²ΉμΉ˜μ§€ μ•Šκ²Œ
  • βœ… μ‚¬μš΄λ“œ μΆ”κ°€ λ“± λ‹€μ–‘ν•œ μΈν„°λž™μ…˜

 

πŸ”Ž κ΄€λ ¨ ν‚€μ›Œλ“œ (SEO)

  • μžλ°”μŠ€ν¬λ¦½νŠΈ toast λ§Œλ“€κΈ°
  • 바닐라 JS μ•Œλ¦Ό UI
  • toast λ©”μ‹œμ§€ 예제
  • μžλ°”μŠ€ν¬λ¦½νŠΈ 동적 μ»΄ν¬λ„ŒνŠΈ
  • μ›Ή μ ‘κ·Όμ„± μ•Œλ¦Ό κ΅¬ν˜„

 

 

🧩 λ§ˆλ¬΄λ¦¬ν•˜λ©°

JavaScriptλ§ŒμœΌλ‘œλ„ 트리 UIλ₯Ό μΆ©λΆ„νžˆ ν’λΆ€ν•˜κ²Œ κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

κΈ°λ³Έ κΈ°λŠ₯μ—μ„œ μΆœλ°œν•΄ μ•„μ΄μ½˜, λ“œλž˜κ·Έ μ•€ λ“œλ‘­, 검색, 그리고 μ ‘κ·Όμ„±κΉŒμ§€ μ±™κΈ°λ©΄μ„œ

μ‚¬μš©μž κ²½ν—˜μ„ 더 μ •κ΅ν•˜κ²Œ λ‹€λ“¬λŠ” 과정은 ν”„λŸ°νŠΈμ—”λ“œ 개발의 μ§„μ§œ 재미λ₯Ό λŠλ‚„ 수 있게 ν•΄ μ€λ‹ˆλ‹€.

 

이제 μ—¬λŸ¬λΆ„μ˜ 트리 UIλŠ” λ‹¨μˆœν•œ 파일 ꡬ쑰 ν‘œν˜„μ„ λ„˜μ–΄,

λˆ„κ΅¬μ—κ²Œλ‚˜ μΉœμ ˆν•œ μΈν„°νŽ˜μ΄μŠ€λ‘œ ν™•μž₯될 μ€€λΉ„κ°€ λ˜μ—ˆμ–΄μš”.

 

여기에 μ• λ‹ˆλ©”μ΄μ…˜, API 연동, μ»€μŠ€ν„°λ§ˆμ΄μ§• μ˜΅μ…˜ λ“± μ›ν•˜λŠ” κΈ°λŠ₯을 덧뢙이면

λ‚˜λ§Œμ˜ λ©‹μ§„ μ»΄ν¬λ„ŒνŠΈκ°€ μ™„μ„±λ˜κ² μ£ . πŸ”§

 

κΆκΈˆν•œ μ μ΄λ‚˜ 더 λ‹€λ€˜μœΌλ©΄ ν•˜λŠ” UI μ£Όμ œκ°€ μžˆλ‹€λ©΄ λŒ“κΈ€λ‘œ μ•Œλ €μ£Όμ„Έμš”!

그럼 λ‹€μŒ ν¬μŠ€νŠΈμ—μ„œ 또 λ§Œλ‚˜μš”. 😊