Vue 기반에서 부트스트랩 스타일의 커스텀 알림 메시지 구현
부트스트랩은 기본적으로 제공하는 알림 컴포넌트가 없을 수 있으며, 이를 해결하기 위해 다음과 같은 두 가지 방식으로 동작 가능한 메시지 박스를 생성할 수 있다.
/**
* 알림 메시지 표시
* @param message 표시할 텍스트 내용
* @param alertType 메시지 유형 (부트스트랩의 alert 클래스와 일치)
*/
showAlert(message, alertType = 'success') {
const container = document.createElement('div');
container.className = `alert alert-${alertType} alert-dismissible col-md-4 col-md-offset-4`;
const topPosition = window.pageYOffset + 60;
container.style.cssText = `
position: absolute;
top: ${topPosition}px;
z-index: 999999;
opacity: 0.9;
`;
container.textContent = message;
const closeButton = document.createElement('button');
closeButton.type = 'button';
closeButton.className = 'btn-close';
closeButton.setAttribute('data-bs-dismiss', 'alert');
closeButton.setAttribute('aria-label', '닫기');
container.appendChild(closeButton);
document.body.appendChild(container);
return container;
}
/**
* 일정 시간 후 상단으로 사라지는 애니메이션 메시지
* @param message 내용
* @param type 유형
*/
notify(message, type) {
const element = this.showAlert(message, type);
let isHovered = false;
element.addEventListener('mouseenter', () => { isHovered = true; });
element.addEventListener('mouseleave', () => { isHovered = false; });
setTimeout(() => {
const step = 20; // 애니메이션 간격 (밀리초)
const distance = 60; // 이동 거리 (픽셀)
const initialTop = element.getBoundingClientRect().top;
const targetTop = initialTop - distance;
element.style.transition = `opacity ${step * distance}ms ease-out`;
element.style.opacity = '0';
let intervalId = setInterval(() => {
const currentTop = element.getBoundingClientRect().top;
if (currentTop > targetTop) {
element.style.top = `${currentTop - 1}px`;
} else {
clearInterval(intervalId);
element.remove();
}
}, step);
if (isHovered) {
clearInterval(intervalId);
element.style.transition = 'none';
}
element.addEventListener('mouseenter', () => {
clearInterval(intervalId);
element.style.transition = 'none';
});
element.addEventListener('mouseleave', () => {
element.style.opacity = '0';
intervalId = setInterval(() => {
const currentTop = element.getBoundingClientRect().top;
if (currentTop > targetTop) {
element.style.top = `${currentTop - 1}px`;
} else {
clearInterval(intervalId);
element.remove();
}
}, step);
});
}, 1500);
}
URL 형식 검증 함수
정규표현식을 활용해 입력된 문자열이 유효한 URL인지 확인하는 함수이다.
isValidUrl(url) {
const pattern = /^((https|http|ftp|rtsp|mms)?\/\/)?([0-9a-z_!~*\'()&=+$%-]+:)?[0-9a-z_!~*\'()&=+$%-]+@?(([0-9]{1,3}\.){3}[0-9]{1,3}|([0-9a-z_!~*\'()-]+\.)+[a-z]{2,6})(:[0-9]{1,4})?(\/?|\/[0-9a-zA-Z_!~*\'();:@&=+$,%#-]+)*$/;
return pattern.test(url);
}
HTML 내에서 스크립트 동적 로드
브라우저 환경에서는 import나 require가 지원되지 않으므로, 동적으로 <script> 태그를 생성하여 외부 자바스크립트 파일을 불러올 수 있다.
loadScript(src) {
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
document.body.appendChild(script);
}
// 사용 예시
this.loadScript('./static/js/utils.js');