/** * RAG 검색 챗봇 UI 공통 유틸리티 JavaScript */ // 전역 유틸리티 함수 const AppUtils = { // 시스템 알림 메시지 추가 addSystemNotification: function(message) { console.log(`[시스템 알림] ${message}`); const messageDiv = document.createElement('div'); messageDiv.classList.add('message', 'system'); const contentDiv = document.createElement('div'); contentDiv.classList.add('message-content'); const messageP = document.createElement('p'); messageP.innerHTML = ` ${message}`; contentDiv.appendChild(messageP); messageDiv.appendChild(contentDiv); // 채팅 메시지 영역이 있으면 추가 const chatMessages = document.getElementById('chatMessages'); if (chatMessages) { chatMessages.appendChild(messageDiv); // 스크롤을 가장 아래로 이동 chatMessages.scrollTop = chatMessages.scrollHeight; } }, // 오류 메시지 추가 addErrorMessage: function(errorText) { console.error(`[오류] ${errorText}`); const messageDiv = document.createElement('div'); messageDiv.classList.add('message', 'system'); const contentDiv = document.createElement('div'); contentDiv.classList.add('message-content'); contentDiv.style.backgroundColor = 'rgba(239, 68, 68, 0.1)'; contentDiv.style.color = 'var(--error-color)'; const errorP = document.createElement('p'); errorP.innerHTML = ` ${errorText}`; contentDiv.appendChild(errorP); messageDiv.appendChild(contentDiv); // 채팅 메시지 영역이 있으면 추가 const chatMessages = document.getElementById('chatMessages'); if (chatMessages) { chatMessages.appendChild(messageDiv); // 스크롤을 가장 아래로 이동 chatMessages.scrollTop = chatMessages.scrollHeight; } }, // 타임아웃 기능이 있는 fetch fetchWithTimeout: async function(url, options = {}, timeout = 30000) { console.log(`API 요청: ${options.method || 'GET'} ${url}`); const controller = new AbortController(); const id = setTimeout(() => controller.abort(), timeout); try { const response = await fetch(url, { ...options, signal: controller.signal }); clearTimeout(id); console.log(`API 응답 상태: ${response.status}`); return response; } catch (error) { clearTimeout(id); if (error.name === 'AbortError') { console.error(`API 요청 타임아웃: ${url}`); throw new Error('요청 시간이 초과되었습니다.'); } console.error(`API 요청 실패: ${url}`, error); throw error; } }, // 로딩 스피너 HTML 생성 createLoadingSpinner: function() { return '
'; }, // 날짜 포맷팅 formatDate: function(date) { return new Date(date).toLocaleString('ko-KR', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }); }, // HTML 문자열 이스케이프 (XSS 방지) escapeHtml: function(html) { const div = document.createElement('div'); div.textContent = html; return div.innerHTML; } }; // 페이지 로드 완료 시 공통 초기화 document.addEventListener('DOMContentLoaded', function() { console.log('앱 코어 모듈 초기화 완료'); });