viewlogic 1.1.2 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/plugins/I18nManager.js", "../src/plugins/AuthManager.js", "../src/plugins/CacheManager.js", "../src/plugins/QueryManager.js", "../src/core/RouteLoader.js", "../src/core/ErrorHandler.js", "../src/core/ComponentLoader.js", "../src/viewlogic-router.js"],
|
|
4
|
-
"sourcesContent": ["/**\r\n * ViewLogic Internationalization System\r\n * \uB2E4\uAD6D\uC5B4 \uC9C0\uC6D0 \uC2DC\uC2A4\uD15C\r\n */\r\nexport class I18nManager {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n enabled: options.useI18n !== undefined ? options.useI18n : true,\r\n defaultLanguage: options.defaultLanguage || 'ko',\r\n fallbackLanguage: options.defaultLanguage || 'ko',\r\n cacheKey: options.cacheKey || 'viewlogic_lang',\r\n dataCacheKey: options.dataCacheKey || 'viewlogic_i18n_data',\r\n cacheVersion: options.cacheVersion || '1.0.0',\r\n enableDataCache: options.enableDataCache !== false,\r\n debug: options.debug || false\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870 (\uD544\uC694\uC2DC \uC5B8\uC5B4 \uBCC0\uACBD \uC2DC \uB77C\uC6B0\uD130 \uC0C1\uD0DC \uC5C5\uB370\uC774\uD2B8)\r\n this.router = router;\r\n \r\n this.messages = new Map();\r\n this.currentLanguage = this.config.defaultLanguage;\r\n this.isLoading = false;\r\n this.loadPromises = new Map();\r\n \r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108\uB4E4\r\n this.listeners = {\r\n languageChanged: []\r\n };\r\n \r\n // \uBE44\uB3D9\uAE30 \uCD08\uAE30\uD654 \uC2DC\uC791 (constructor \uB0B4\uC5D0\uC11C\uB294 await \uBD88\uAC00)\r\n this.initPromise = this.init();\r\n }\r\n\r\n async init() {\r\n // i18n\uC774 \uBE44\uD65C\uC131\uD654\uB41C \uACBD\uC6B0 \uCD08\uAE30\uD654\uD558\uC9C0 \uC54A\uC74C\r\n if (!this.config.enabled) {\r\n this.log('info', 'I18n system disabled');\r\n return;\r\n }\r\n \r\n // \uCE90\uC2DC\uC5D0\uC11C \uC5B8\uC5B4 \uC124\uC815 \uB85C\uB4DC\r\n this.loadLanguageFromCache();\r\n \r\n // \uAC1C\uBC1C \uBAA8\uB4DC\uC5D0\uC11C\uB294 \uCE90\uC2DC \uBE44\uD65C\uC131\uD654\r\n if (this.config.debug) {\r\n this.config.enableDataCache = false;\r\n this.log('debug', 'Data cache disabled in debug mode');\r\n }\r\n \r\n // \uCD08\uAE30 \uC5B8\uC5B4 \uD30C\uC77C \uC790\uB3D9 \uB85C\uB4DC (\uC544\uC9C1 \uB85C\uB4DC\uB418\uC9C0 \uC54A\uC740 \uACBD\uC6B0\uC5D0\uB9CC)\r\n if (!this.messages.has(this.currentLanguage)) {\r\n try {\r\n await this.loadMessages(this.currentLanguage);\r\n } catch (error) {\r\n this.log('error', 'Failed to load initial language file:', error);\r\n }\r\n } else {\r\n this.log('debug', 'Language messages already loaded:', this.currentLanguage);\r\n }\r\n }\r\n\r\n /**\r\n * \uCE90\uC2DC\uC5D0\uC11C \uC5B8\uC5B4 \uC124\uC815 \uB85C\uB4DC\r\n */\r\n loadLanguageFromCache() {\r\n try {\r\n const cachedLang = localStorage.getItem(this.config.cacheKey);\r\n if (cachedLang && this.isValidLanguage(cachedLang)) {\r\n this.currentLanguage = cachedLang;\r\n this.log('debug', 'Language loaded from cache:', cachedLang);\r\n }\r\n } catch (error) {\r\n this.log('warn', 'Failed to load language from cache:', error);\r\n }\r\n }\r\n\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uC720\uD6A8\uC131 \uAC80\uC0AC\r\n */\r\n isValidLanguage(lang) {\r\n return typeof lang === 'string' && /^[a-z]{2}$/.test(lang);\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uC5B8\uC5B4 \uBC18\uD658\r\n */\r\n getCurrentLanguage() {\r\n return this.currentLanguage;\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uBCC0\uACBD\r\n */\r\n async setLanguage(language) {\r\n if (!this.isValidLanguage(language)) {\r\n this.log('warn', 'Invalid language code:', language);\r\n return false;\r\n }\r\n\r\n if (this.currentLanguage === language) {\r\n this.log('debug', 'Language already set to:', language);\r\n return true;\r\n }\r\n\r\n const oldLanguage = this.currentLanguage;\r\n this.currentLanguage = language;\r\n\r\n try {\r\n // \uC5B8\uC5B4 \uD30C\uC77C \uB85C\uB4DC\r\n await this.loadMessages(language);\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n this.saveLanguageToCache(language);\r\n \r\n // \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n this.emit('languageChanged', {\r\n from: oldLanguage,\r\n to: language,\r\n messages: this.messages.get(language)\r\n });\r\n \r\n this.log('info', 'Language changed successfully', { from: oldLanguage, to: language });\r\n return true;\r\n } catch (error) {\r\n // \uC2E4\uD328 \uC2DC \uC774\uC804 \uC5B8\uC5B4\uB85C \uBCF5\uC6D0\r\n this.currentLanguage = oldLanguage;\r\n this.log('error', 'Failed to change language:', error);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4\uB97C \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n */\r\n saveLanguageToCache(language) {\r\n try {\r\n localStorage.setItem(this.config.cacheKey, language);\r\n this.log('debug', 'Language saved to cache:', language);\r\n } catch (error) {\r\n this.log('warn', 'Failed to save language to cache:', error);\r\n }\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uBA54\uC2DC\uC9C0 \uD30C\uC77C \uB85C\uB4DC\r\n */\r\n async loadMessages(language) {\r\n // \uC774\uBBF8 \uB85C\uB4DC\uB41C \uACBD\uC6B0\r\n if (this.messages.has(language)) {\r\n this.log('debug', 'Messages already loaded for:', language);\r\n return this.messages.get(language);\r\n }\r\n\r\n // \uC774\uBBF8 \uB85C\uB529 \uC911\uC778 \uACBD\uC6B0\r\n if (this.loadPromises.has(language)) {\r\n this.log('debug', 'Messages loading in progress for:', language);\r\n return await this.loadPromises.get(language);\r\n }\r\n\r\n const loadPromise = this._loadMessagesFromFile(language);\r\n this.loadPromises.set(language, loadPromise);\r\n\r\n try {\r\n const messages = await loadPromise;\r\n this.messages.set(language, messages);\r\n this.loadPromises.delete(language);\r\n this.log('debug', 'Messages loaded successfully for:', language);\r\n return messages;\r\n } catch (error) {\r\n this.loadPromises.delete(language);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * \uD30C\uC77C\uC5D0\uC11C \uBA54\uC2DC\uC9C0 \uB85C\uB4DC (\uCE90\uC2F1 \uC9C0\uC6D0)\r\n */\r\n async _loadMessagesFromFile(language) {\r\n // \uCE90\uC2DC\uC5D0\uC11C \uBA3C\uC800 \uC2DC\uB3C4\r\n if (this.config.enableDataCache) {\r\n const cachedData = this.getDataFromCache(language);\r\n if (cachedData) {\r\n this.log('debug', 'Messages loaded from cache:', language);\r\n return cachedData;\r\n }\r\n }\r\n \r\n try {\r\n // JSON \uD30C\uC77C\uB85C \uBCC0\uACBD - config\uC758 i18nPath \uC0AC\uC6A9\r\n const i18nPath = `${this.router.config.i18nPath}/${language}.json`;\r\n const response = await fetch(i18nPath);\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n const messages = await response.json();\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n if (this.config.enableDataCache) {\r\n this.saveDataToCache(language, messages);\r\n }\r\n \r\n return messages;\r\n } catch (error) {\r\n this.log('error', 'Failed to load messages file for:', language, error);\r\n \r\n // \uD3F4\uBC31 \uC5B8\uC5B4 \uC2DC\uB3C4\r\n if (language !== this.config.fallbackLanguage) {\r\n this.log('info', 'Trying fallback language:', this.config.fallbackLanguage);\r\n return await this._loadMessagesFromFile(this.config.fallbackLanguage);\r\n }\r\n \r\n throw new Error(`Failed to load messages for language: ${language}`);\r\n }\r\n }\r\n \r\n /**\r\n * \uC5B8\uC5B4 \uB370\uC774\uD130\uB97C \uCE90\uC2DC\uC5D0\uC11C \uAC00\uC838\uC624\uAE30\r\n */\r\n getDataFromCache(language) {\r\n try {\r\n const cacheKey = `${this.config.dataCacheKey}_${language}_${this.config.cacheVersion}`;\r\n const cachedItem = localStorage.getItem(cacheKey);\r\n \r\n if (cachedItem) {\r\n const { data, timestamp, version } = JSON.parse(cachedItem);\r\n \r\n // \uBC84\uC804 \uD655\uC778\r\n if (version !== this.config.cacheVersion) {\r\n this.log('debug', 'Cache version mismatch, clearing:', language);\r\n localStorage.removeItem(cacheKey);\r\n return null;\r\n }\r\n \r\n // TTL \uD655\uC778 (24\uC2DC\uAC04)\r\n const now = Date.now();\r\n const maxAge = 24 * 60 * 60 * 1000; // 24\uC2DC\uAC04\r\n \r\n if (now - timestamp > maxAge) {\r\n this.log('debug', 'Cache expired, removing:', language);\r\n localStorage.removeItem(cacheKey);\r\n return null;\r\n }\r\n \r\n return data;\r\n }\r\n } catch (error) {\r\n this.log('warn', 'Failed to read from cache:', error);\r\n }\r\n \r\n return null;\r\n }\r\n \r\n /**\r\n * \uC5B8\uC5B4 \uB370\uC774\uD130\uB97C \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n */\r\n saveDataToCache(language, data) {\r\n try {\r\n const cacheKey = `${this.config.dataCacheKey}_${language}_${this.config.cacheVersion}`;\r\n const cacheItem = {\r\n data,\r\n timestamp: Date.now(),\r\n version: this.config.cacheVersion\r\n };\r\n \r\n localStorage.setItem(cacheKey, JSON.stringify(cacheItem));\r\n this.log('debug', 'Data saved to cache:', language);\r\n } catch (error) {\r\n this.log('warn', 'Failed to save to cache:', error);\r\n }\r\n }\r\n\r\n /**\r\n * \uBA54\uC2DC\uC9C0 \uBC88\uC5ED\r\n */\r\n t(key, params = {}) {\r\n // i18n\uC774 \uBE44\uD65C\uC131\uD654\uB41C \uACBD\uC6B0 \uD0A4 \uC790\uCCB4\uB97C \uBC18\uD658\r\n if (!this.config.enabled) {\r\n return key;\r\n }\r\n \r\n const messages = this.messages.get(this.currentLanguage);\r\n if (!messages) {\r\n this.log('warn', 'No messages loaded for current language:', this.currentLanguage);\r\n return key;\r\n }\r\n\r\n const message = this.getNestedValue(messages, key);\r\n if (message === undefined) {\r\n this.log('warn', 'Translation not found for key:', key);\r\n \r\n // \uD3F4\uBC31 \uC5B8\uC5B4\uC5D0\uC11C \uCC3E\uAE30\r\n const fallbackMessages = this.messages.get(this.config.fallbackLanguage);\r\n if (fallbackMessages && this.currentLanguage !== this.config.fallbackLanguage) {\r\n const fallbackMessage = this.getNestedValue(fallbackMessages, key);\r\n if (fallbackMessage !== undefined) {\r\n return this.interpolate(fallbackMessage, params);\r\n }\r\n }\r\n \r\n return key;\r\n }\r\n\r\n return this.interpolate(message, params);\r\n }\r\n\r\n /**\r\n * \uC911\uCCA9\uB41C \uAC1D\uCCB4\uC5D0\uC11C \uAC12 \uAC00\uC838\uC624\uAE30\r\n */\r\n getNestedValue(obj, path) {\r\n return path.split('.').reduce((current, key) => {\r\n return current && current[key] !== undefined ? current[key] : undefined;\r\n }, obj);\r\n }\r\n\r\n /**\r\n * \uBB38\uC790\uC5F4 \uBCF4\uAC04 \uCC98\uB9AC\r\n */\r\n interpolate(message, params) {\r\n if (typeof message !== 'string') {\r\n return message;\r\n }\r\n\r\n return message.replace(/\\{(\\w+)\\}/g, (match, key) => {\r\n return params.hasOwnProperty(key) ? params[key] : match;\r\n });\r\n }\r\n\r\n /**\r\n * \uBCF5\uC218\uD615 \uCC98\uB9AC\r\n */\r\n plural(key, count, params = {}) {\r\n const pluralKey = count === 1 ? `${key}.singular` : `${key}.plural`;\r\n return this.t(pluralKey, { ...params, count });\r\n }\r\n\r\n /**\r\n * \uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uC5B8\uC5B4 \uBAA9\uB85D\r\n */\r\n getAvailableLanguages() {\r\n return ['ko', 'en']; // \uCD94\uD6C4 \uB3D9\uC801\uC73C\uB85C \uB85C\uB4DC\uD558\uB3C4\uB85D \uBCC0\uACBD \uAC00\uB2A5\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uBCC0\uACBD \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uB4F1\uB85D\r\n */\r\n on(event, callback) {\r\n if (this.listeners[event]) {\r\n this.listeners[event].push(callback);\r\n }\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uBCC0\uACBD \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70\r\n */\r\n off(event, callback) {\r\n if (this.listeners[event]) {\r\n const index = this.listeners[event].indexOf(callback);\r\n if (index > -1) {\r\n this.listeners[event].splice(index, 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n */\r\n emit(event, data) {\r\n if (this.listeners[event]) {\r\n this.listeners[event].forEach(callback => {\r\n try {\r\n callback(data);\r\n } catch (error) {\r\n this.log('error', 'Error in event listener:', error);\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uC5B8\uC5B4\uC758 \uBAA8\uB4E0 \uBA54\uC2DC\uC9C0 \uBC18\uD658\r\n */\r\n getMessages() {\r\n return this.messages.get(this.currentLanguage) || {};\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4\uBCC4 \uB0A0\uC9DC \uD3EC\uB9F7\uD305\r\n */\r\n formatDate(date, options = {}) {\r\n const locale = this.currentLanguage === 'ko' ? 'ko-KR' : 'en-US';\r\n return new Intl.DateTimeFormat(locale, options).format(new Date(date));\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4\uBCC4 \uC22B\uC790 \uD3EC\uB9F7\uD305\r\n */\r\n formatNumber(number, options = {}) {\r\n const locale = this.currentLanguage === 'ko' ? 'ko-KR' : 'en-US';\r\n return new Intl.NumberFormat(locale, options).format(number);\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'I18nManager', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * i18n \uD65C\uC131\uD654 \uC5EC\uBD80 \uD655\uC778\r\n */\r\n isEnabled() {\r\n return this.config.enabled;\r\n }\r\n \r\n /**\r\n * \uCD08\uAE30 \uB85C\uB529\uC774 \uC644\uB8CC\uB418\uC5C8\uB294\uC9C0 \uD655\uC778\r\n */\r\n async isReady() {\r\n if (!this.config.enabled) {\r\n return true;\r\n }\r\n \r\n try {\r\n await this.initPromise;\r\n return true;\r\n } catch (error) {\r\n this.log('error', 'I18n initialization failed:', error);\r\n return false;\r\n }\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC \uCD08\uAE30\uD654 (\uBC84\uC804 \uBCC0\uACBD \uC2DC \uC0AC\uC6A9)\r\n */\r\n clearCache() {\r\n try {\r\n const keys = Object.keys(localStorage);\r\n const cacheKeys = keys.filter(key => key.startsWith(this.config.dataCacheKey));\r\n \r\n cacheKeys.forEach(key => {\r\n localStorage.removeItem(key);\r\n });\r\n \r\n this.log('debug', 'Cache cleared, removed', cacheKeys.length, 'items');\r\n } catch (error) {\r\n this.log('warn', 'Failed to clear cache:', error);\r\n }\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC \uC0C1\uD0DC \uD655\uC778\r\n */\r\n getCacheInfo() {\r\n const info = {\r\n enabled: this.config.enableDataCache,\r\n version: this.config.cacheVersion,\r\n languages: {}\r\n };\r\n \r\n try {\r\n const keys = Object.keys(localStorage);\r\n const cacheKeys = keys.filter(key => key.startsWith(this.config.dataCacheKey));\r\n \r\n cacheKeys.forEach(key => {\r\n const match = key.match(new RegExp(`${this.config.dataCacheKey}_(\\w+)_(.+)`));\r\n if (match) {\r\n const [, language, version] = match;\r\n const cachedItem = JSON.parse(localStorage.getItem(key));\r\n \r\n info.languages[language] = {\r\n version,\r\n timestamp: cachedItem.timestamp,\r\n age: Date.now() - cachedItem.timestamp\r\n };\r\n }\r\n });\r\n } catch (error) {\r\n this.log('warn', 'Failed to get cache info:', error);\r\n }\r\n \r\n return info;\r\n }\r\n \r\n /**\r\n * \uC2DC\uC2A4\uD15C \uCD08\uAE30\uD654 (\uD604\uC7AC \uC5B8\uC5B4\uC758 \uBA54\uC2DC\uC9C0 \uB85C\uB4DC)\r\n */\r\n async initialize() {\r\n if (!this.config.enabled) {\r\n this.log('info', 'I18n system is disabled, skipping initialization');\r\n return true;\r\n }\r\n \r\n try {\r\n // \uCD08\uAE30 \uC124\uC815\uC774 \uC644\uB8CC\uB420 \uB54C\uAE4C\uC9C0 \uB300\uAE30\r\n await this.initPromise;\r\n this.log('info', 'I18n system fully initialized');\r\n return true;\r\n } catch (error) {\r\n this.log('error', 'Failed to initialize I18n system:', error);\r\n return false;\r\n }\r\n }\r\n}", "/**\r\n * ViewLogic Authentication Management System\r\n * \uC778\uC99D \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class AuthManager {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n enabled: options.authEnabled || false,\r\n loginRoute: options.loginRoute || 'login',\r\n protectedRoutes: options.protectedRoutes || [],\r\n protectedPrefixes: options.protectedPrefixes || [],\r\n publicRoutes: options.publicRoutes || ['login', 'register', 'home'],\r\n checkAuthFunction: options.checkAuthFunction || null,\r\n redirectAfterLogin: options.redirectAfterLogin || 'home',\r\n // \uCFE0\uD0A4/\uC2A4\uD1A0\uB9AC\uC9C0 \uC124\uC815\r\n authCookieName: options.authCookieName || 'authToken',\r\n authFallbackCookieNames: options.authFallbackCookieNames || ['accessToken', 'token', 'jwt'],\r\n authStorage: options.authStorage || 'cookie',\r\n authCookieOptions: options.authCookieOptions || {},\r\n authSkipValidation: options.authSkipValidation || false,\r\n debug: options.debug || false\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870 (\uD544\uC218 \uC758\uC874\uC131)\r\n this.router = router;\r\n \r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108\uB4E4\r\n this.eventListeners = new Map();\r\n \r\n this.log('info', 'AuthManager initialized', { enabled: this.config.enabled });\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'AuthManager', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD2B8 \uC778\uC99D \uD655\uC778\r\n */\r\n async checkAuthentication(routeName) {\r\n // \uC778\uC99D \uC2DC\uC2A4\uD15C\uC774 \uBE44\uD65C\uC131\uD654\uB41C \uACBD\uC6B0\r\n if (!this.config.enabled) {\r\n return { allowed: true, reason: 'auth_disabled' };\r\n }\r\n\r\n this.log('debug', `\uD83D\uDD10 Checking authentication for route: ${routeName}`);\r\n\r\n // \uACF5\uAC1C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n if (this.isPublicRoute(routeName)) {\r\n return { allowed: true, reason: 'public_route' };\r\n }\r\n\r\n // \uBCF4\uD638\uB41C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n const isProtected = this.isProtectedRoute(routeName);\r\n if (!isProtected) {\r\n return { allowed: true, reason: 'not_protected' };\r\n }\r\n\r\n // \uC0AC\uC6A9\uC790 \uC815\uC758 \uC778\uC99D \uCCB4\uD06C \uD568\uC218\uAC00 \uC788\uB294 \uACBD\uC6B0\r\n if (typeof this.config.checkAuthFunction === 'function') {\r\n try {\r\n const isAuthenticated = await this.config.checkAuthFunction(routeName);\r\n return {\r\n allowed: isAuthenticated, \r\n reason: isAuthenticated ? 'custom_auth_success' : 'custom_auth_failed',\r\n routeName\r\n };\r\n } catch (error) {\r\n this.log('error', 'Custom auth function failed:', error);\r\n return { allowed: false, reason: 'custom_auth_error', error };\r\n }\r\n }\r\n\r\n // \uAE30\uBCF8 \uC778\uC99D \uD655\uC778\r\n const isAuthenticated = this.isUserAuthenticated();\r\n return {\r\n allowed: isAuthenticated, \r\n reason: isAuthenticated ? 'authenticated' : 'not_authenticated',\r\n routeName\r\n };\r\n }\r\n\r\n /**\r\n * \uC0AC\uC6A9\uC790 \uC778\uC99D \uC0C1\uD0DC \uD655\uC778\r\n */\r\n isUserAuthenticated() {\r\n this.log('debug', '\uD83D\uDD0D Checking user authentication status');\r\n\r\n // 1. localStorage \uD655\uC778\r\n const token = localStorage.getItem('authToken') || localStorage.getItem('accessToken');\r\n if (token) {\r\n try {\r\n if (token.includes('.')) {\r\n const payload = JSON.parse(atob(token.split('.')[1]));\r\n if (payload.exp && Date.now() >= payload.exp * 1000) {\r\n this.log('debug', 'localStorage token expired, removing...');\r\n localStorage.removeItem('authToken');\r\n localStorage.removeItem('accessToken');\r\n return false;\r\n }\r\n }\r\n this.log('debug', '\u2705 Valid token found in localStorage');\r\n return true;\r\n } catch (error) {\r\n this.log('warn', 'Invalid token in localStorage:', error);\r\n }\r\n }\r\n\r\n // 2. sessionStorage \uD655\uC778\r\n const sessionToken = sessionStorage.getItem('authToken') || sessionStorage.getItem('accessToken');\r\n if (sessionToken) {\r\n this.log('debug', '\u2705 Token found in sessionStorage');\r\n return true;\r\n }\r\n\r\n // 3. \uCFE0\uD0A4 \uD655\uC778\r\n const authCookie = this.getAuthCookie();\r\n if (authCookie) {\r\n try {\r\n if (authCookie.includes('.')) {\r\n const payload = JSON.parse(atob(authCookie.split('.')[1]));\r\n if (payload.exp && Date.now() >= payload.exp * 1000) {\r\n this.log('debug', 'Cookie token expired, removing...');\r\n this.removeAuthCookie();\r\n return false;\r\n }\r\n }\r\n this.log('debug', '\u2705 Valid token found in cookies');\r\n return true;\r\n } catch (error) {\r\n this.log('warn', 'Cookie token validation failed:', error);\r\n }\r\n }\r\n\r\n // 4. \uC804\uC5ED \uBCC0\uC218 \uD655\uC778 (\uB808\uAC70\uC2DC \uC9C0\uC6D0)\r\n if (window.user || window.isAuthenticated) {\r\n this.log('debug', '\u2705 Global authentication variable found');\r\n return true;\r\n }\r\n\r\n this.log('debug', '\u274C No valid authentication found');\r\n return false;\r\n }\r\n\r\n /**\r\n * \uACF5\uAC1C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n */\r\n isPublicRoute(routeName) {\r\n return this.config.publicRoutes.includes(routeName);\r\n }\r\n\r\n /**\r\n * \uBCF4\uD638\uB41C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n */\r\n isProtectedRoute(routeName) {\r\n // \uD2B9\uC815 \uB77C\uC6B0\uD2B8\uAC00 \uBCF4\uD638\uB41C \uB77C\uC6B0\uD2B8 \uBAA9\uB85D\uC5D0 \uC788\uB294\uC9C0 \uD655\uC778\r\n if (this.config.protectedRoutes.includes(routeName)) {\r\n return true;\r\n }\r\n\r\n // prefix\uB85C \uBCF4\uD638\uB41C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n for (const prefix of this.config.protectedPrefixes) {\r\n if (routeName.startsWith(prefix)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uCFE0\uD0A4 \uAC00\uC838\uC624\uAE30\r\n */\r\n getAuthCookie() {\r\n // \uC8FC \uCFE0\uD0A4 \uC774\uB984 \uD655\uC778\r\n const primaryCookie = this.getCookieValue(this.config.authCookieName);\r\n if (primaryCookie) {\r\n return primaryCookie;\r\n }\r\n\r\n // \uB300\uCCB4 \uCFE0\uD0A4 \uC774\uB984\uB4E4 \uD655\uC778\r\n for (const cookieName of this.config.authFallbackCookieNames) {\r\n const cookieValue = this.getCookieValue(cookieName);\r\n if (cookieValue) {\r\n this.log('debug', `Found auth token in fallback cookie: ${cookieName}`);\r\n return cookieValue;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * \uCFE0\uD0A4 \uAC12 \uAC00\uC838\uC624\uAE30\r\n */\r\n getCookieValue(name) {\r\n const value = `; ${document.cookie}`;\r\n const parts = value.split(`; ${name}=`);\r\n if (parts.length === 2) {\r\n return decodeURIComponent(parts.pop().split(';').shift());\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uCFE0\uD0A4 \uC81C\uAC70\r\n */\r\n removeAuthCookie() {\r\n const cookiesToRemove = [this.config.authCookieName, ...this.config.authFallbackCookieNames];\r\n \r\n cookiesToRemove.forEach(cookieName => {\r\n // \uD604\uC7AC \uACBD\uB85C\uC640 \uB8E8\uD2B8 \uACBD\uB85C\uC5D0\uC11C \uBAA8\uB450 \uC81C\uAC70\r\n document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;\r\n document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${window.location.pathname};`;\r\n });\r\n \r\n this.log('debug', 'Auth cookies removed');\r\n }\r\n\r\n /**\r\n * \uC561\uC138\uC2A4 \uD1A0\uD070 \uAC00\uC838\uC624\uAE30\r\n */\r\n getAccessToken() {\r\n // localStorage \uD655\uC778\r\n let token = localStorage.getItem('authToken') || localStorage.getItem('accessToken');\r\n if (token) return token;\r\n\r\n // sessionStorage \uD655\uC778\r\n token = sessionStorage.getItem('authToken') || sessionStorage.getItem('accessToken');\r\n if (token) return token;\r\n\r\n // \uCFE0\uD0A4 \uD655\uC778\r\n token = this.getAuthCookie();\r\n if (token) return token;\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * \uC561\uC138\uC2A4 \uD1A0\uD070 \uC124\uC815\r\n */\r\n setAccessToken(token, options = {}) {\r\n if (!token) {\r\n this.log('warn', 'Empty token provided');\r\n return false;\r\n }\r\n\r\n const {\r\n storage = this.config.authStorage,\r\n cookieOptions = this.config.authCookieOptions,\r\n skipValidation = this.config.authSkipValidation\r\n } = options;\r\n\r\n try {\r\n // JWT \uD1A0\uD070 \uAC80\uC99D (\uC635\uC158)\r\n if (!skipValidation && token.includes('.')) {\r\n try {\r\n const payload = JSON.parse(atob(token.split('.')[1]));\r\n if (payload.exp && Date.now() >= payload.exp * 1000) {\r\n this.log('warn', '\u274C Token is expired');\r\n return false;\r\n }\r\n this.log('debug', '\u2705 JWT token validated');\r\n } catch (error) {\r\n this.log('warn', '\u26A0\uFE0F JWT validation failed, but proceeding:', error.message);\r\n }\r\n }\r\n\r\n // \uC2A4\uD1A0\uB9AC\uC9C0\uBCC4 \uC800\uC7A5\r\n switch (storage) {\r\n case 'localStorage':\r\n localStorage.setItem('authToken', token);\r\n this.log('debug', 'Token saved to localStorage');\r\n break;\r\n\r\n case 'sessionStorage':\r\n sessionStorage.setItem('authToken', token);\r\n this.log('debug', 'Token saved to sessionStorage');\r\n break;\r\n\r\n case 'cookie':\r\n this.setAuthCookie(token, cookieOptions);\r\n break;\r\n\r\n default:\r\n // \uAE30\uBCF8\uAC12: localStorage\r\n localStorage.setItem('authToken', token);\r\n this.log('debug', 'Token saved to localStorage (default)');\r\n }\r\n\r\n this.emitAuthEvent('token_set', { \r\n storage,\r\n tokenLength: token.length,\r\n hasExpiration: token.includes('.')\r\n });\r\n\r\n return true;\r\n\r\n } catch (error) {\r\n this.log('Failed to set token:', error);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uCFE0\uD0A4 \uC124\uC815\r\n */\r\n setAuthCookie(token, options = {}) {\r\n const {\r\n cookieName = this.config.authCookieName,\r\n secure = window.location.protocol === 'https:',\r\n sameSite = 'Strict',\r\n path = '/',\r\n domain = null\r\n } = options;\r\n\r\n let cookieString = `${cookieName}=${encodeURIComponent(token)}; path=${path}`;\r\n\r\n if (secure) {\r\n cookieString += '; Secure';\r\n }\r\n\r\n if (sameSite) {\r\n cookieString += `; SameSite=${sameSite}`;\r\n }\r\n\r\n if (domain) {\r\n cookieString += `; Domain=${domain}`;\r\n }\r\n\r\n // JWT\uC5D0\uC11C \uB9CC\uB8CC \uC2DC\uAC04 \uCD94\uCD9C\r\n try {\r\n if (token.includes('.')) {\r\n try {\r\n const payload = JSON.parse(atob(token.split('.')[1]));\r\n if (payload.exp) {\r\n const expireDate = new Date(payload.exp * 1000);\r\n cookieString += `; Expires=${expireDate.toUTCString()}`;\r\n }\r\n } catch (error) {\r\n this.log('Could not extract expiration from JWT token');\r\n }\r\n }\r\n } catch (error) {\r\n this.log('Token processing error:', error);\r\n }\r\n\r\n document.cookie = cookieString;\r\n this.log(`Auth cookie set: ${cookieName}`);\r\n }\r\n\r\n /**\r\n * \uD1A0\uD070 \uC81C\uAC70\r\n */\r\n removeAccessToken(storage = 'all') {\r\n switch (storage) {\r\n case 'localStorage':\r\n localStorage.removeItem('authToken');\r\n localStorage.removeItem('accessToken');\r\n break;\r\n\r\n case 'sessionStorage':\r\n sessionStorage.removeItem('authToken');\r\n sessionStorage.removeItem('accessToken');\r\n break;\r\n\r\n case 'cookie':\r\n this.removeAuthCookie();\r\n break;\r\n\r\n case 'all':\r\n default:\r\n localStorage.removeItem('authToken');\r\n localStorage.removeItem('accessToken');\r\n sessionStorage.removeItem('authToken');\r\n sessionStorage.removeItem('accessToken');\r\n this.removeAuthCookie();\r\n break;\r\n }\r\n\r\n this.emitAuthEvent('token_removed', { storage });\r\n this.log(`Token removed from: ${storage}`);\r\n }\r\n\r\n /**\r\n * \uB85C\uADF8\uC778 \uC131\uACF5 \uCC98\uB9AC\r\n */\r\n handleLoginSuccess(targetRoute = null) {\r\n const redirectRoute = targetRoute || this.config.redirectAfterLogin;\r\n \r\n this.log(`\uD83C\uDF89 Login success, redirecting to: ${redirectRoute}`);\r\n \r\n this.emitAuthEvent('login_success', { targetRoute: redirectRoute });\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4\uAC00 \uC788\uC73C\uBA74 \uC9C1\uC811 \uB124\uBE44\uAC8C\uC774\uC158\r\n if (this.router && typeof this.router.navigateTo === 'function') {\r\n this.router.navigateTo(redirectRoute);\r\n }\r\n \r\n return redirectRoute;\r\n }\r\n\r\n /**\r\n * \uB85C\uADF8\uC544\uC6C3 \uCC98\uB9AC\r\n */\r\n handleLogout() {\r\n this.log('\uD83D\uDC4B Logging out user');\r\n \r\n // \uBAA8\uB4E0 \uC800\uC7A5\uC18C\uC5D0\uC11C \uD1A0\uD070 \uC81C\uAC70\r\n this.removeAccessToken();\r\n \r\n // \uC804\uC5ED \uBCC0\uC218 \uC815\uB9AC\r\n if (window.user) window.user = null;\r\n if (window.isAuthenticated) window.isAuthenticated = false;\r\n \r\n this.emitAuthEvent('logout', {});\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4\uAC00 \uC788\uC73C\uBA74 \uC9C1\uC811 \uB124\uBE44\uAC8C\uC774\uC158\r\n if (this.router && typeof this.router.navigateTo === 'function') {\r\n this.router.navigateTo(this.config.loginRoute);\r\n }\r\n \r\n return this.config.loginRoute;\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n */\r\n emitAuthEvent(eventType, data) {\r\n const event = new CustomEvent('router:auth', {\r\n detail: {\r\n type: eventType,\r\n timestamp: Date.now(),\r\n ...data\r\n }\r\n });\r\n \r\n document.dispatchEvent(event);\r\n \r\n // \uB0B4\uBD80 \uB9AC\uC2A4\uB108\uB4E4\uC5D0\uAC8C\uB3C4 \uC54C\uB9BC\r\n if (this.eventListeners.has(eventType)) {\r\n this.eventListeners.get(eventType).forEach(listener => {\r\n try {\r\n listener(data);\r\n } catch (error) {\r\n this.log('Event listener error:', error);\r\n }\r\n });\r\n }\r\n \r\n this.log(`\uD83D\uDD14 Auth event emitted: ${eventType}`, data);\r\n }\r\n\r\n /**\r\n * \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uB4F1\uB85D\r\n */\r\n on(eventType, listener) {\r\n if (!this.eventListeners.has(eventType)) {\r\n this.eventListeners.set(eventType, []);\r\n }\r\n this.eventListeners.get(eventType).push(listener);\r\n }\r\n\r\n /**\r\n * \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70\r\n */\r\n off(eventType, listener) {\r\n if (this.eventListeners.has(eventType)) {\r\n const listeners = this.eventListeners.get(eventType);\r\n const index = listeners.indexOf(listener);\r\n if (index > -1) {\r\n listeners.splice(index, 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uC0C1\uD0DC \uD1B5\uACC4\r\n */\r\n getAuthStats() {\r\n return {\r\n enabled: this.config.enabled,\r\n isAuthenticated: this.isUserAuthenticated(),\r\n hasToken: !!this.getAccessToken(),\r\n protectedRoutesCount: this.config.protectedRoutes.length,\r\n protectedPrefixesCount: this.config.protectedPrefixes.length,\r\n publicRoutesCount: this.config.publicRoutes.length,\r\n storage: this.config.authStorage,\r\n loginRoute: this.config.loginRoute\r\n };\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.eventListeners.clear();\r\n this.log('debug', 'AuthManager destroyed');\r\n }\r\n}", "/**\r\n * ViewLogic Cache Management System\r\n * \uCE90\uC2DC \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class CacheManager {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n cacheMode: options.cacheMode || 'memory', // 'memory' \uB610\uB294 'lru'\r\n cacheTTL: options.cacheTTL || 300000, // 5\uBD84 (\uBC00\uB9AC\uCD08)\r\n maxCacheSize: options.maxCacheSize || 50, // LRU \uCE90\uC2DC \uCD5C\uB300 \uD06C\uAE30\r\n debug: options.debug || false\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870 (\uD544\uC694\uC2DC \uB77C\uC6B0\uD130 \uC0C1\uD0DC \uD655\uC778\uC6A9)\r\n this.router = router;\r\n \r\n // \uCE90\uC2DC \uC800\uC7A5\uC18C\uB4E4\r\n this.cache = new Map();\r\n this.cacheTimestamps = new Map();\r\n this.lruOrder = []; // LRU \uC21C\uC11C \uCD94\uC801\r\n \r\n this.log('info', 'CacheManager initialized with config:', this.config);\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'CacheManager', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uCE90\uC2DC\uC5D0 \uAC12 \uC800\uC7A5\r\n */\r\n setCache(key, value) {\r\n const now = Date.now();\r\n \r\n if (this.config.cacheMode === 'lru') {\r\n // LRU \uCE90\uC2DC \uAD00\uB9AC\r\n if (this.cache.size >= this.config.maxCacheSize && !this.cache.has(key)) {\r\n const oldestKey = this.lruOrder.shift();\r\n if (oldestKey) {\r\n this.cache.delete(oldestKey);\r\n this.cacheTimestamps.delete(oldestKey);\r\n this.log('debug', `\uD83D\uDDD1\uFE0F LRU evicted cache key: ${oldestKey}`);\r\n }\r\n }\r\n \r\n // \uAE30\uC874 \uD0A4\uAC00 \uC788\uC73C\uBA74 LRU \uC21C\uC11C\uC5D0\uC11C \uC81C\uAC70\r\n const existingIndex = this.lruOrder.indexOf(key);\r\n if (existingIndex > -1) {\r\n this.lruOrder.splice(existingIndex, 1);\r\n }\r\n \r\n // \uCD5C\uC2E0 \uC21C\uC11C\uB85C \uCD94\uAC00\r\n this.lruOrder.push(key);\r\n }\r\n \r\n this.cache.set(key, value);\r\n this.cacheTimestamps.set(key, now);\r\n \r\n this.log('debug', `\uD83D\uDCBE Cached: ${key} (size: ${this.cache.size})`);\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC\uC5D0\uC11C \uAC12 \uAC00\uC838\uC624\uAE30\r\n */\r\n getFromCache(key) {\r\n const now = Date.now();\r\n const timestamp = this.cacheTimestamps.get(key);\r\n \r\n // TTL \uCCB4\uD06C\r\n if (timestamp && (now - timestamp) > this.config.cacheTTL) {\r\n this.cache.delete(key);\r\n this.cacheTimestamps.delete(key);\r\n \r\n if (this.config.cacheMode === 'lru') {\r\n const index = this.lruOrder.indexOf(key);\r\n if (index > -1) {\r\n this.lruOrder.splice(index, 1);\r\n }\r\n }\r\n \r\n this.log('debug', `\u23F0 Cache expired and removed: ${key}`);\r\n return null;\r\n }\r\n \r\n const value = this.cache.get(key);\r\n \r\n if (value && this.config.cacheMode === 'lru') {\r\n // LRU \uC21C\uC11C \uC5C5\uB370\uC774\uD2B8\r\n const index = this.lruOrder.indexOf(key);\r\n if (index > -1) {\r\n this.lruOrder.splice(index, 1);\r\n this.lruOrder.push(key);\r\n }\r\n }\r\n \r\n if (value) {\r\n this.log('debug', `\uD83C\uDFAF Cache hit: ${key}`);\r\n } else {\r\n this.log('debug', `\u274C Cache miss: ${key}`);\r\n }\r\n \r\n return value;\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC\uC5D0 \uD0A4\uAC00 \uC788\uB294\uC9C0 \uD655\uC778\r\n */\r\n hasCache(key) {\r\n return this.cache.has(key) && this.getFromCache(key) !== null;\r\n }\r\n \r\n /**\r\n * \uD2B9\uC815 \uD0A4 \uD328\uD134\uC758 \uCE90\uC2DC \uC0AD\uC81C\r\n */\r\n invalidateByPattern(pattern) {\r\n const keysToDelete = [];\r\n \r\n for (const key of this.cache.keys()) {\r\n if (key.includes(pattern) || key.startsWith(pattern)) {\r\n keysToDelete.push(key);\r\n }\r\n }\r\n \r\n keysToDelete.forEach(key => {\r\n this.cache.delete(key);\r\n this.cacheTimestamps.delete(key);\r\n \r\n if (this.config.cacheMode === 'lru') {\r\n const index = this.lruOrder.indexOf(key);\r\n if (index > -1) {\r\n this.lruOrder.splice(index, 1);\r\n }\r\n }\r\n });\r\n \r\n this.log('debug', `\uD83E\uDDF9 Invalidated ${keysToDelete.length} cache entries matching: ${pattern}`);\r\n return keysToDelete.length;\r\n }\r\n \r\n /**\r\n * \uD2B9\uC815 \uCEF4\uD3EC\uB10C\uD2B8 \uCE90\uC2DC \uBB34\uD6A8\uD654\r\n */\r\n invalidateComponentCache(routeName) {\r\n const patterns = [\r\n `component_${routeName}`,\r\n `script_${routeName}`,\r\n `template_${routeName}`,\r\n `style_${routeName}`,\r\n `layout_${routeName}`\r\n ];\r\n \r\n let totalInvalidated = 0;\r\n patterns.forEach(pattern => {\r\n totalInvalidated += this.invalidateByPattern(pattern);\r\n });\r\n \r\n this.log(`\uD83D\uDD04 Invalidated component cache for route: ${routeName} (${totalInvalidated} entries)`);\r\n return totalInvalidated;\r\n }\r\n \r\n /**\r\n * \uBAA8\uB4E0 \uCEF4\uD3EC\uB10C\uD2B8 \uCE90\uC2DC \uC0AD\uC81C\r\n */\r\n clearComponentCache() {\r\n const componentPatterns = ['component_', 'script_', 'template_', 'style_', 'layout_'];\r\n let totalCleared = 0;\r\n \r\n componentPatterns.forEach(pattern => {\r\n totalCleared += this.invalidateByPattern(pattern);\r\n });\r\n \r\n this.log(`\uD83E\uDDFD Cleared all component caches (${totalCleared} entries)`);\r\n return totalCleared;\r\n }\r\n \r\n /**\r\n * \uC804\uCCB4 \uCE90\uC2DC \uC0AD\uC81C\r\n */\r\n clearCache() {\r\n const size = this.cache.size;\r\n this.cache.clear();\r\n this.cacheTimestamps.clear();\r\n this.lruOrder = [];\r\n \r\n this.log(`\uD83D\uDD25 Cleared all cache (${size} entries)`);\r\n }\r\n \r\n /**\r\n * \uB9CC\uB8CC\uB41C \uCE90\uC2DC \uD56D\uBAA9\uB4E4 \uC815\uB9AC\r\n */\r\n cleanExpiredCache() {\r\n const now = Date.now();\r\n const expiredKeys = [];\r\n \r\n for (const [key, timestamp] of this.cacheTimestamps.entries()) {\r\n if ((now - timestamp) > this.config.cacheTTL) {\r\n expiredKeys.push(key);\r\n }\r\n }\r\n \r\n expiredKeys.forEach(key => {\r\n this.cache.delete(key);\r\n this.cacheTimestamps.delete(key);\r\n \r\n if (this.config.cacheMode === 'lru') {\r\n const index = this.lruOrder.indexOf(key);\r\n if (index > -1) {\r\n this.lruOrder.splice(index, 1);\r\n }\r\n }\r\n });\r\n \r\n if (expiredKeys.length > 0) {\r\n this.log(`\u23F1\uFE0F Cleaned ${expiredKeys.length} expired cache entries`);\r\n }\r\n \r\n return expiredKeys.length;\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC \uD1B5\uACC4 \uC815\uBCF4\r\n */\r\n getCacheStats() {\r\n return {\r\n size: this.cache.size,\r\n maxSize: this.config.maxCacheSize,\r\n mode: this.config.cacheMode,\r\n ttl: this.config.cacheTTL,\r\n memoryUsage: this.getMemoryUsage(),\r\n hitRatio: this.getHitRatio(),\r\n categories: this.getCategorizedStats()\r\n };\r\n }\r\n \r\n /**\r\n * \uBA54\uBAA8\uB9AC \uC0AC\uC6A9\uB7C9 \uCD94\uC815\r\n */\r\n getMemoryUsage() {\r\n let estimatedBytes = 0;\r\n \r\n for (const [key, value] of this.cache.entries()) {\r\n // \uD0A4 \uD06C\uAE30\r\n estimatedBytes += key.length * 2; // UTF-16\r\n \r\n // \uAC12 \uD06C\uAE30 \uCD94\uC815\r\n if (typeof value === 'string') {\r\n estimatedBytes += value.length * 2;\r\n } else if (typeof value === 'object' && value !== null) {\r\n estimatedBytes += JSON.stringify(value).length * 2;\r\n } else {\r\n estimatedBytes += 8; // \uB300\uB7B5\uC801\uC778 \uD06C\uAE30\r\n }\r\n }\r\n \r\n return {\r\n bytes: estimatedBytes,\r\n kb: Math.round(estimatedBytes / 1024 * 100) / 100,\r\n mb: Math.round(estimatedBytes / (1024 * 1024) * 100) / 100\r\n };\r\n }\r\n \r\n /**\r\n * \uD788\uD2B8 \uBE44\uC728 \uACC4\uC0B0 (\uAC04\uB2E8\uD55C \uCD94\uC815)\r\n */\r\n getHitRatio() {\r\n // \uC2E4\uC81C \uD788\uD2B8/\uBBF8\uC2A4 \uCD94\uC801\uC744 \uC704\uD574\uC11C\uB294 \uBCC4\uB3C4\uC758 \uCE74\uC6B4\uD130\uAC00 \uD544\uC694\r\n // \uD604\uC7AC\uB294 \uCE90\uC2DC \uD06C\uAE30 \uAE30\uBC18 \uCD94\uC815\uCE58 \uBC18\uD658\r\n const ratio = this.cache.size > 0 ? Math.min(this.cache.size / this.config.maxCacheSize, 1) : 0;\r\n return Math.round(ratio * 100);\r\n }\r\n \r\n /**\r\n * \uCE74\uD14C\uACE0\uB9AC\uBCC4 \uCE90\uC2DC \uD1B5\uACC4\r\n */\r\n getCategorizedStats() {\r\n const categories = {\r\n components: 0,\r\n scripts: 0,\r\n templates: 0,\r\n styles: 0,\r\n layouts: 0,\r\n others: 0\r\n };\r\n \r\n for (const key of this.cache.keys()) {\r\n if (key.startsWith('component_')) categories.components++;\r\n else if (key.startsWith('script_')) categories.scripts++;\r\n else if (key.startsWith('template_')) categories.templates++;\r\n else if (key.startsWith('style_')) categories.styles++;\r\n else if (key.startsWith('layout_')) categories.layouts++;\r\n else categories.others++;\r\n }\r\n \r\n return categories;\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC \uD0A4 \uBAA9\uB85D \uBC18\uD658\r\n */\r\n getCacheKeys() {\r\n return Array.from(this.cache.keys());\r\n }\r\n \r\n /**\r\n * \uD2B9\uC815 \uD328\uD134\uC758 \uCE90\uC2DC \uD0A4\uB4E4 \uBC18\uD658\r\n */\r\n getCacheKeysByPattern(pattern) {\r\n return this.getCacheKeys().filter(key => \r\n key.includes(pattern) || key.startsWith(pattern)\r\n );\r\n }\r\n \r\n /**\r\n * \uC790\uB3D9 \uC815\uB9AC \uC2DC\uC791 (\uBC31\uADF8\uB77C\uC6B4\uB4DC\uC5D0\uC11C \uB9CC\uB8CC\uB41C \uCE90\uC2DC \uC815\uB9AC)\r\n */\r\n startAutoCleanup(interval = 60000) { // \uAE30\uBCF8 1\uBD84 \uAC04\uACA9\r\n if (this.cleanupInterval) {\r\n clearInterval(this.cleanupInterval);\r\n }\r\n \r\n this.cleanupInterval = setInterval(() => {\r\n this.cleanExpiredCache();\r\n }, interval);\r\n \r\n this.log(`\uD83E\uDD16 Auto cleanup started (interval: ${interval}ms)`);\r\n }\r\n \r\n /**\r\n * \uC790\uB3D9 \uC815\uB9AC \uC911\uC9C0\r\n */\r\n stopAutoCleanup() {\r\n if (this.cleanupInterval) {\r\n clearInterval(this.cleanupInterval);\r\n this.cleanupInterval = null;\r\n this.log('debug', '\uD83D\uDED1 Auto cleanup stopped');\r\n }\r\n }\r\n \r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.stopAutoCleanup();\r\n this.clearCache();\r\n this.log('debug', 'CacheManager destroyed');\r\n }\r\n}", "/**\r\n * ViewLogic Query Management System\r\n * URL \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class QueryManager {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n enableParameterValidation: options.enableParameterValidation !== false,\r\n logSecurityWarnings: options.logSecurityWarnings !== false,\r\n maxParameterLength: options.maxParameterLength || 1000,\r\n maxArraySize: options.maxArraySize || 100,\r\n maxParameterCount: options.maxParameterCount || 50,\r\n allowedKeyPattern: options.allowedKeyPattern || /^[a-zA-Z0-9_\\-]+$/,\r\n debug: options.debug || false\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870\r\n this.router = router;\r\n \r\n // \uD604\uC7AC \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC0C1\uD0DC\r\n this.currentQueryParams = {};\r\n \r\n // \uD604\uC7AC \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130 \uC0C1\uD0DC (navigateTo\uB85C \uC804\uB2EC\uB41C params)\r\n this.currentRouteParams = {};\r\n \r\n this.log('info', 'QueryManager initialized with config:', this.config);\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'QueryManager', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uD30C\uB77C\uBBF8\uD130 \uAC12 sanitize (XSS, SQL Injection \uBC29\uC5B4)\r\n */\r\n sanitizeParameter(value) {\r\n if (typeof value !== 'string') return value;\r\n \r\n // XSS \uBC29\uC5B4: HTML \uD0DC\uADF8\uC640 \uC2A4\uD06C\uB9BD\uD2B8 \uC81C\uAC70\r\n let sanitized = value\r\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '') // script \uD0DC\uADF8 \uC81C\uAC70\r\n .replace(/<iframe\\b[^<]*(?:(?!<\\/iframe>)<[^<]*)*<\\/iframe>/gi, '') // iframe \uD0DC\uADF8 \uC81C\uAC70\r\n .replace(/<object\\b[^<]*(?:(?!<\\/object>)<[^<]*)*<\\/object>/gi, '') // object \uD0DC\uADF8 \uC81C\uAC70\r\n .replace(/<embed\\b[^<]*(?:(?!<\\/embed>)<[^<]*)*<\\/embed>/gi, '') // embed \uD0DC\uADF8 \uC81C\uAC70\r\n .replace(/<link\\b[^<]*>/gi, '') // link \uD0DC\uADF8 \uC81C\uAC70\r\n .replace(/<meta\\b[^<]*>/gi, '') // meta \uD0DC\uADF8 \uC81C\uAC70\r\n .replace(/javascript:/gi, '') // javascript: \uD504\uB85C\uD1A0\uCF5C \uC81C\uAC70\r\n .replace(/vbscript:/gi, '') // vbscript: \uD504\uB85C\uD1A0\uCF5C \uC81C\uAC70\r\n .replace(/data:/gi, '') // data: \uD504\uB85C\uD1A0\uCF5C \uC81C\uAC70\r\n .replace(/on\\w+\\s*=/gi, '') // \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC \uC81C\uAC70 (onclick, onload \uB4F1)\r\n .replace(/expression\\s*\\(/gi, '') // CSS expression \uC81C\uAC70\r\n .replace(/url\\s*\\(/gi, ''); // CSS url() \uC81C\uAC70\r\n \r\n // SQL Injection \uBC29\uC5B4: \uC704\uD5D8\uD55C SQL \uD0A4\uC6CC\uB4DC \uD544\uD130\uB9C1\r\n const sqlPatterns = [\r\n /(\\b(union|select|insert|update|delete|drop|create|alter|exec|execute|sp_|xp_)\\b)/gi,\r\n /(;|\\||&|\\*|%|<|>)/g, // \uC704\uD5D8\uD55C \uD2B9\uC218\uBB38\uC790\r\n /(--|\\/\\*|\\*\\/)/g, // SQL \uC8FC\uC11D\r\n /(\\bor\\b.*\\b=\\b|\\band\\b.*\\b=\\b)/gi, // OR/AND \uC870\uAC74\uBB38\r\n /('.*'|\".*\")/g, // \uB530\uC634\uD45C\uB85C \uB458\uB7EC\uC2F8\uC778 \uBB38\uC790\uC5F4\r\n /(\\\\\\w+)/g // \uBC31\uC2AC\uB798\uC2DC \uC774\uC2A4\uCF00\uC774\uD504\r\n ];\r\n \r\n for (const pattern of sqlPatterns) {\r\n sanitized = sanitized.replace(pattern, '');\r\n }\r\n \r\n // \uCD94\uAC00 \uBCF4\uC548: \uC5F0\uC18D\uB41C \uD2B9\uC218\uBB38\uC790 \uC81C\uAC70\r\n sanitized = sanitized.replace(/[<>'\"&]{2,}/g, '');\r\n \r\n // \uAE38\uC774 \uC81C\uD55C (DoS \uBC29\uC5B4)\r\n if (sanitized.length > this.config.maxParameterLength) {\r\n sanitized = sanitized.substring(0, this.config.maxParameterLength);\r\n }\r\n \r\n return sanitized.trim();\r\n }\r\n\r\n /**\r\n * \uD30C\uB77C\uBBF8\uD130 \uC720\uD6A8\uC131 \uAC80\uC99D\r\n */\r\n validateParameter(key, value) {\r\n // \uBCF4\uC548 \uAC80\uC99D\uC774 \uBE44\uD65C\uC131\uD654\uB41C \uACBD\uC6B0 \uD1B5\uACFC\r\n if (!this.config.enableParameterValidation) {\r\n return true;\r\n }\r\n \r\n // \uD30C\uB77C\uBBF8\uD130 \uD0A4 \uAC80\uC99D\r\n if (typeof key !== 'string' || key.length === 0) {\r\n return false;\r\n }\r\n \r\n // \uD0A4 \uC774\uB984 \uC81C\uD55C\r\n if (!this.config.allowedKeyPattern.test(key)) {\r\n if (this.config.logSecurityWarnings) {\r\n console.warn(`Invalid parameter key format: ${key}`);\r\n }\r\n return false;\r\n }\r\n \r\n // \uD0A4 \uAE38\uC774 \uC81C\uD55C\r\n if (key.length > 50) {\r\n if (this.config.logSecurityWarnings) {\r\n console.warn(`Parameter key too long: ${key}`);\r\n }\r\n return false;\r\n }\r\n \r\n // \uAC12 \uD0C0\uC785 \uAC80\uC99D\r\n if (value !== null && value !== undefined) {\r\n if (typeof value === 'string') {\r\n // \uBB38\uC790\uC5F4 \uAE38\uC774 \uC81C\uD55C\r\n if (value.length > this.config.maxParameterLength) {\r\n if (this.config.logSecurityWarnings) {\r\n console.warn(`Parameter value too long for key: ${key}`);\r\n }\r\n return false;\r\n }\r\n \r\n // \uC704\uD5D8\uD55C \uD328\uD134 \uAC10\uC9C0\r\n const dangerousPatterns = [\r\n /<script|<iframe|<object|<embed/gi,\r\n /javascript:|vbscript:|data:/gi,\r\n /union.*select|insert.*into|delete.*from/gi,\r\n /\\.\\.\\//g, // \uACBD\uB85C \uD0D0\uC0C9 \uACF5\uACA9\r\n /[<>'\"&]{3,}/g // \uC5F0\uC18D\uB41C \uD2B9\uC218\uBB38\uC790\r\n ];\r\n \r\n for (const pattern of dangerousPatterns) {\r\n if (pattern.test(value)) {\r\n if (this.config.logSecurityWarnings) {\r\n console.warn(`Dangerous pattern detected in parameter ${key}:`, value);\r\n }\r\n return false;\r\n }\r\n }\r\n } else if (Array.isArray(value)) {\r\n // \uBC30\uC5F4 \uAE38\uC774 \uC81C\uD55C\r\n if (value.length > this.config.maxArraySize) {\r\n if (this.config.logSecurityWarnings) {\r\n console.warn(`Parameter array too large for key: ${key}`);\r\n }\r\n return false;\r\n }\r\n \r\n // \uBC30\uC5F4 \uAC01 \uC694\uC18C \uAC80\uC99D\r\n for (const item of value) {\r\n if (!this.validateParameter(`${key}[]`, item)) {\r\n return false;\r\n }\r\n }\r\n }\r\n }\r\n \r\n return true;\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC\uC2A4\uD2B8\uB9C1 \uD30C\uC2F1\r\n */\r\n parseQueryString(queryString) {\r\n const params = {};\r\n if (!queryString) return params;\r\n \r\n const pairs = queryString.split('&');\r\n for (const pair of pairs) {\r\n try {\r\n const [rawKey, rawValue] = pair.split('=');\r\n if (!rawKey) continue;\r\n \r\n let key, value;\r\n try {\r\n key = decodeURIComponent(rawKey);\r\n value = rawValue ? decodeURIComponent(rawValue) : '';\r\n } catch (e) {\r\n this.log('warn', 'Failed to decode URI component:', pair);\r\n continue;\r\n }\r\n \r\n // \uBCF4\uC548 \uAC80\uC99D\r\n if (!this.validateParameter(key, value)) {\r\n this.log('warn', `Parameter rejected by security filter: ${key}`);\r\n continue;\r\n }\r\n \r\n // \uAC12 sanitize\r\n const sanitizedValue = this.sanitizeParameter(value);\r\n \r\n // \uBC30\uC5F4 \uD615\uD0DC\uC758 \uD30C\uB77C\uBBF8\uD130 \uCC98\uB9AC (\uC608: tags[]=a&tags[]=b)\r\n if (key.endsWith('[]')) {\r\n const arrayKey = key.slice(0, -2);\r\n \r\n // \uBC30\uC5F4 \uD0A4\uB3C4 \uAC80\uC99D\r\n if (!this.validateParameter(arrayKey, [])) {\r\n continue;\r\n }\r\n \r\n if (!params[arrayKey]) params[arrayKey] = [];\r\n \r\n // \uBC30\uC5F4 \uD06C\uAE30 \uC81C\uD55C\r\n if (params[arrayKey].length < this.config.maxArraySize) {\r\n params[arrayKey].push(sanitizedValue);\r\n } else {\r\n if (this.config.logSecurityWarnings) {\r\n console.warn(`Array parameter ${arrayKey} size limit exceeded`);\r\n }\r\n }\r\n } else {\r\n params[key] = sanitizedValue;\r\n }\r\n } catch (error) {\r\n this.log('error', 'Error parsing query parameter:', pair, error);\r\n }\r\n }\r\n \r\n // \uC804\uCCB4 \uD30C\uB77C\uBBF8\uD130 \uAC1C\uC218 \uC81C\uD55C\r\n const paramCount = Object.keys(params).length;\r\n if (paramCount > this.config.maxParameterCount) {\r\n if (this.config.logSecurityWarnings) {\r\n console.warn(`Too many parameters (${paramCount}). Limiting to first ${this.config.maxParameterCount}.`);\r\n }\r\n const limitedParams = {};\r\n let count = 0;\r\n for (const [key, value] of Object.entries(params)) {\r\n if (count >= this.config.maxParameterCount) break;\r\n limitedParams[key] = value;\r\n count++;\r\n }\r\n return limitedParams;\r\n }\r\n \r\n return params;\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC\uC2A4\uD2B8\uB9C1 \uC0DD\uC131\r\n */\r\n buildQueryString(params) {\r\n if (!params || Object.keys(params).length === 0) return '';\r\n \r\n const pairs = [];\r\n for (const [key, value] of Object.entries(params)) {\r\n if (Array.isArray(value)) {\r\n // \uBC30\uC5F4 \uD30C\uB77C\uBBF8\uD130 \uCC98\uB9AC\r\n for (const item of value) {\r\n pairs.push(`${encodeURIComponent(key)}[]=${encodeURIComponent(item)}`);\r\n }\r\n } else if (value !== undefined && value !== null) {\r\n pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\r\n }\r\n }\r\n return pairs.join('&');\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uBCC0\uACBD \uAC10\uC9C0\r\n */\r\n hasQueryParamsChanged(newParams) {\r\n if (!this.currentQueryParams && !newParams) return false;\r\n if (!this.currentQueryParams || !newParams) return true;\r\n \r\n const oldKeys = Object.keys(this.currentQueryParams);\r\n const newKeys = Object.keys(newParams);\r\n \r\n if (oldKeys.length !== newKeys.length) return true;\r\n \r\n for (const key of oldKeys) {\r\n if (JSON.stringify(this.currentQueryParams[key]) !== JSON.stringify(newParams[key])) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC804\uCCB4 \uAC00\uC838\uC624\uAE30\r\n */\r\n getQueryParams() {\r\n return { ...this.currentQueryParams };\r\n }\r\n\r\n /**\r\n * \uD2B9\uC815 \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uAC00\uC838\uC624\uAE30\r\n */\r\n getQueryParam(key, defaultValue = undefined) {\r\n const value = this.currentQueryParams ? this.currentQueryParams[key] : undefined;\r\n return value !== undefined ? value : defaultValue;\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC124\uC815\r\n */\r\n setQueryParams(params, replace = false) {\r\n if (!params || typeof params !== 'object') {\r\n console.warn('Invalid parameters object provided to setQueryParams');\r\n return;\r\n }\r\n \r\n const currentParams = replace ? {} : { ...this.currentQueryParams };\r\n const sanitizedParams = {};\r\n \r\n // \uD30C\uB77C\uBBF8\uD130 \uAC80\uC99D \uBC0F sanitize\r\n for (const [key, value] of Object.entries(params)) {\r\n // \uD0A4\uC640 \uAC12 \uAC80\uC99D\r\n if (!this.validateParameter(key, value)) {\r\n console.warn(`Parameter ${key} rejected by security filter`);\r\n continue;\r\n }\r\n \r\n // \uAC12 \uCC98\uB9AC\r\n if (value !== undefined && value !== null) {\r\n if (Array.isArray(value)) {\r\n sanitizedParams[key] = value.map(item => this.sanitizeParameter(item));\r\n } else {\r\n sanitizedParams[key] = this.sanitizeParameter(value);\r\n }\r\n }\r\n }\r\n \r\n // \uD604\uC7AC \uD30C\uB77C\uBBF8\uD130 \uC5C5\uB370\uC774\uD2B8\r\n Object.assign(currentParams, sanitizedParams);\r\n \r\n // undefined\uB098 null \uAC12 \uC81C\uAC70\r\n for (const [key, value] of Object.entries(currentParams)) {\r\n if (value === undefined || value === null || value === '') {\r\n delete currentParams[key];\r\n }\r\n }\r\n \r\n // \uCD5C\uB300 \uD30C\uB77C\uBBF8\uD130 \uAC1C\uC218 \uD655\uC778\r\n const paramCount = Object.keys(currentParams).length;\r\n if (paramCount > this.config.maxParameterCount) {\r\n if (this.config.logSecurityWarnings) {\r\n console.warn(`Too many parameters after update (${paramCount}). Some parameters may be dropped.`);\r\n }\r\n }\r\n \r\n this.currentQueryParams = currentParams;\r\n this.updateURL();\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC81C\uAC70\r\n */\r\n removeQueryParams(keys) {\r\n if (!keys) return;\r\n \r\n const keysToRemove = Array.isArray(keys) ? keys : [keys];\r\n for (const key of keysToRemove) {\r\n delete this.currentQueryParams[key];\r\n }\r\n \r\n this.updateURL();\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uCD08\uAE30\uD654\r\n */\r\n clearQueryParams() {\r\n this.currentQueryParams = {};\r\n this.updateURL();\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC124\uC815 (\uB77C\uC6B0\uD130\uC5D0\uC11C \uD638\uCD9C)\r\n */\r\n setCurrentQueryParams(params) {\r\n this.currentQueryParams = params || {};\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130 \uC124\uC815 (navigateTo\uC5D0\uC11C \uD638\uCD9C)\r\n */\r\n setCurrentRouteParams(params) {\r\n this.currentRouteParams = params || {};\r\n this.log('debug', 'Route params set:', this.currentRouteParams);\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569\uB41C \uD30C\uB77C\uBBF8\uD130 \uBC18\uD658 (\uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130 + \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130)\r\n */\r\n getAllParams() {\r\n return {\r\n ...this.currentRouteParams,\r\n ...this.currentQueryParams\r\n };\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569\uB41C \uD30C\uB77C\uBBF8\uD130\uC5D0\uC11C \uD2B9\uC815 \uD0A4 \uAC12 \uBC18\uD658\r\n */\r\n getParam(key, defaultValue = undefined) {\r\n // \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130\uAC00 \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130\uBCF4\uB2E4 \uC6B0\uC120\uC21C\uC704 \uB192\uC74C\r\n const value = this.currentQueryParams[key] !== undefined ? \r\n this.currentQueryParams[key] : \r\n this.currentRouteParams[key];\r\n return value !== undefined ? value : defaultValue;\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130\uB9CC \uBC18\uD658\r\n */\r\n getRouteParams() {\r\n return { ...this.currentRouteParams };\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130\uC5D0\uC11C \uD2B9\uC815 \uD0A4 \uAC12 \uBC18\uD658\r\n */\r\n getRouteParam(key, defaultValue = undefined) {\r\n const value = this.currentRouteParams[key];\r\n return value !== undefined ? value : defaultValue;\r\n }\r\n\r\n /**\r\n * URL \uC5C5\uB370\uC774\uD2B8 (\uB77C\uC6B0\uD130\uC758 updateURL \uBA54\uC18C\uB4DC \uD638\uCD9C)\r\n */\r\n updateURL() {\r\n if (this.router && typeof this.router.updateURL === 'function') {\r\n const route = this.router.currentHash || 'home';\r\n this.router.updateURL(route, this.currentQueryParams);\r\n }\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uD1B5\uACC4\r\n */\r\n getStats() {\r\n return {\r\n currentParams: Object.keys(this.currentQueryParams).length,\r\n maxAllowed: this.config.maxParameterCount,\r\n validationEnabled: this.config.enableParameterValidation,\r\n currentQueryString: this.buildQueryString(this.currentQueryParams)\r\n };\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.currentQueryParams = {};\r\n this.currentRouteParams = {};\r\n this.router = null;\r\n this.log('debug', 'QueryManager destroyed');\r\n }\r\n}", "/**\r\n * ViewLogic Route Loading System\r\n * \uB77C\uC6B0\uD2B8 \uB85C\uB529 \uBC0F \uCEF4\uD3EC\uB10C\uD2B8 \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class RouteLoader {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n basePath: options.basePath || '/src',\r\n routesPath: options.routesPath || '/routes',\r\n environment: options.environment || 'development',\r\n useLayout: options.useLayout !== false,\r\n defaultLayout: options.defaultLayout || 'default',\r\n useComponents: options.useComponents !== false,\r\n debug: options.debug || false\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870\r\n this.router = router;\r\n this.log('debug', 'RouteLoader initialized with config:', this.config);\r\n }\r\n\r\n /**\r\n * \uC2A4\uD06C\uB9BD\uD2B8 \uD30C\uC77C \uB85C\uB4DC\r\n */\r\n async loadScript(routeName) {\r\n let script;\r\n try {\r\n if (this.config.environment === 'production') {\r\n // \uD504\uB85C\uB355\uC158 \uBAA8\uB4DC: routes \uD3F4\uB354\uC5D0\uC11C \uBE4C\uB4DC\uB41C JS \uB85C\uB4DC (\uC808\uB300 \uACBD\uB85C)\r\n const importPath = `${this.config.routesPath}/${routeName}.js`;\r\n this.log('debug', `Loading production route: ${importPath}`);\r\n const module = await import(importPath);\r\n script = module.default;\r\n } else {\r\n // \uAC1C\uBC1C \uBAA8\uB4DC: basePath\uB294 \uC774\uBBF8 origin\uC774 \uD3EC\uD568\uB418\uC5B4 \uC788\uC74C\r\n const importPath = `${this.config.basePath}/logic/${routeName}.js`;\r\n this.log('debug', `Loading development route: ${importPath}`);\r\n const module = await import(importPath);\r\n script = module.default;\r\n }\r\n \r\n if (!script) {\r\n throw new Error(`Route '${routeName}' not found - no default export`);\r\n }\r\n \r\n } catch (error) {\r\n // import \uC5D0\uB7EC\uB97C 404\uB85C \uBD84\uB958\r\n if (error.message.includes('Failed to resolve') || \r\n error.message.includes('Failed to fetch') ||\r\n error.message.includes('not found') ||\r\n error.name === 'TypeError') {\r\n throw new Error(`Route '${routeName}' not found - 404`);\r\n }\r\n // \uB2E4\uB978 \uC5D0\uB7EC\uB294 \uADF8\uB300\uB85C \uC804\uD30C\r\n throw error;\r\n }\r\n \r\n return script;\r\n }\r\n\r\n /**\r\n * \uD15C\uD50C\uB9BF \uD30C\uC77C \uB85C\uB4DC (\uC2E4\uD328\uC2DC \uAE30\uBCF8\uAC12 \uBC18\uD658)\r\n */\r\n async loadTemplate(routeName) {\r\n try {\r\n const templatePath = `${this.config.basePath}/views/${routeName}.html`;\r\n const response = await fetch(templatePath);\r\n if (!response.ok) throw new Error(`Template not found: ${response.status}`);\r\n const template = await response.text();\r\n this.log('debug', `Template '${routeName}' loaded successfully`);\r\n return template;\r\n } catch (error) {\r\n this.log('warn', `Template '${routeName}' not found, using default:`, error.message);\r\n // \uAE30\uBCF8 \uD15C\uD50C\uB9BF \uBC18\uD658\r\n return this.generateDefaultTemplate(routeName);\r\n }\r\n }\r\n\r\n /**\r\n * \uC2A4\uD0C0\uC77C \uD30C\uC77C \uB85C\uB4DC (\uC2E4\uD328\uC2DC \uBE48 \uBB38\uC790\uC5F4 \uBC18\uD658)\r\n */\r\n async loadStyle(routeName) {\r\n try {\r\n const stylePath = `${this.config.basePath}/styles/${routeName}.css`;\r\n const response = await fetch(stylePath);\r\n if (!response.ok) throw new Error(`Style not found: ${response.status}`);\r\n const style = await response.text();\r\n this.log('debug', `Style '${routeName}' loaded successfully`);\r\n return style;\r\n } catch (error) {\r\n this.log('debug', `Style '${routeName}' not found, no styles applied:`, error.message);\r\n // \uC2A4\uD0C0\uC77C\uC774 \uC5C6\uC73C\uBA74 \uBE48 \uBB38\uC790\uC5F4 \uBC18\uD658\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * \uB808\uC774\uC544\uC6C3 \uD30C\uC77C \uB85C\uB4DC (\uC2E4\uD328\uC2DC null \uBC18\uD658)\r\n */\r\n async loadLayout(layoutName) {\r\n try {\r\n const layoutPath = `${this.config.basePath}/layouts/${layoutName}.html`;\r\n const response = await fetch(layoutPath);\r\n if (!response.ok) throw new Error(`Layout not found: ${response.status}`);\r\n const layout = await response.text();\r\n \r\n this.log('debug', `Layout '${layoutName}' loaded successfully`);\r\n return layout;\r\n } catch (error) {\r\n this.log('debug', `Layout '${layoutName}' not found, no layout applied:`, error.message);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * \uB808\uC774\uC544\uC6C3\uACFC \uD15C\uD50C\uB9BF \uBCD1\uD569\r\n */\r\n mergeLayoutWithTemplate(routeName, layout, template) {\r\n let result;\r\n // \uB808\uC774\uC544\uC6C3\uC5D0\uC11C <slot name=\"content\"> \uBD80\uBD84\uC744 \uD15C\uD50C\uB9BF\uC73C\uB85C \uAD50\uCCB4\r\n if (layout.includes('{{ content }}')) {\r\n result = layout.replace(\r\n /{{ content }}/s,\r\n template\r\n );\r\n }\r\n // slot\uC774 \uC5C6\uC73C\uBA74 main-content \uD074\uB798\uC2A4 \uB0B4\uC6A9 \uAD50\uCCB4\r\n else if (layout.includes('class=\"main-content\"')) {\r\n this.log('debug', 'Using main-content replacement');\r\n result = layout.replace(\r\n /(<div class=\"container\">).*?(<\\/div>\\s*<\\/main>)/s,\r\n `$1${template}$2`\r\n );\r\n }\r\n // \uB9C8\uC9C0\uB9C9 \uB300\uC548: \uC804\uCCB4 \uB808\uC774\uC544\uC6C3\uC744 \uD15C\uD50C\uB9BF\uC73C\uB85C \uAC10\uC2F8\uAE30\r\n else {\r\n this.log('debug', 'Wrapping template with layout');\r\n result = `${layout}\\n${template}`;\r\n }\r\n \r\n return result;\r\n }\r\n\r\n\r\n /**\r\n * Vue \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131\r\n */\r\n async createVueComponent(routeName) {\r\n // \uCE90\uC2DC\uB41C Vue \uCEF4\uD3EC\uB10C\uD2B8\uAC00 \uC788\uB294\uC9C0 \uD655\uC778\r\n const cacheKey = `component_${routeName}`;\r\n const cached = this.router.cacheManager?.getFromCache(cacheKey);\r\n if (cached) {\r\n return cached;\r\n }\r\n \r\n const script = await this.loadScript(routeName);\r\n const router = this.router;\r\n const isProduction = this.config.environment === 'production';\r\n \r\n // \uD658\uACBD\uBCC4 \uB9AC\uC18C\uC2A4 \uB85C\uB529\r\n let template, style = '', layout = null;\r\n \r\n if (isProduction) {\r\n // \uD504\uB85C\uB355\uC158: \uC2A4\uD06C\uB9BD\uD2B8\uC5D0 \uC788\uB294 \uD15C\uD50C\uB9BF \uC0AC\uC6A9 \uB610\uB294 \uAE30\uBCF8\uAC12\r\n template = script.template || this.generateDefaultTemplate(routeName);\r\n } else {\r\n // \uAC1C\uBC1C: \uAC1C\uBCC4 \uD30C\uC77C\uB4E4 \uB85C\uB4DC\r\n template = await this.loadTemplate(routeName);\r\n style = await this.loadStyle(routeName);\r\n layout = this.config.useLayout && script.layout !== null ? \r\n await this.loadLayout(script.layout || this.config.defaultLayout) : null;\r\n \r\n // \uB808\uC774\uC544\uC6C3\uACFC \uD15C\uD50C\uB9BF \uBCD1\uD569\r\n if (layout) {\r\n template = this.mergeLayoutWithTemplate(routeName, layout, template);\r\n }\r\n }\r\n \r\n // \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529 (\uC2E4\uD328\uD574\uB3C4 \uB77C\uC6B0\uD130\uB294 \uACC4\uC18D \uC791\uB3D9)\r\n let loadedComponents = {};\r\n if (this.config.useComponents && router.componentLoader) {\r\n try {\r\n loadedComponents = await router.componentLoader.loadAllComponents();\r\n this.log('debug', `Components loaded successfully for route: ${routeName}`);\r\n } catch (error) {\r\n this.log('warn', `Component loading failed for route '${routeName}', continuing without components:`, error.message);\r\n loadedComponents = {}; // \uBE48 \uAC1D\uCCB4\uB85C \uD3F4\uBC31\r\n }\r\n }\r\n\r\n // \uB2E8\uC77C \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131\r\n const component = {\r\n ...script,\r\n name: script.name || this.toPascalCase(routeName),\r\n template,\r\n components: loadedComponents,\r\n data() {\r\n const originalData = script.data ? script.data() : {};\r\n const commonData = {\r\n ...originalData,\r\n currentRoute: routeName,\r\n $query: router.queryManager?.getQueryParams() || {},\r\n $lang: router.i18nManager?.getCurrentLanguage() || router.config.i18nDefaultLanguage,\r\n $dataLoading: false\r\n };\r\n \r\n return commonData;\r\n },\r\n computed: {\r\n ...(script.computed || {}),\r\n // \uD558\uC704 \uD638\uD658\uC131\uC744 \uC704\uD574 params\uB294 \uC720\uC9C0\uD558\uB418 getAllParams \uC0AC\uC6A9\r\n params() {\r\n return router.queryManager?.getAllParams() || {};\r\n }\r\n },\r\n async mounted() {\r\n if (script.mounted) {\r\n await script.mounted.call(this);\r\n }\r\n if (script.dataURL) {\r\n if (typeof script.dataURL === 'string') {\r\n // \uAE30\uC874 \uB2E8\uC77C API \uBC29\uC2DD (\uD558\uC704 \uD638\uD658\uC131)\r\n await this.$fetchData();\r\n } else if (typeof script.dataURL === 'object') {\r\n // \uC0C8\uB85C\uC6B4 \uB2E4\uC911 API \uBC29\uC2DD\r\n await this.$fetchMultipleData();\r\n }\r\n }\r\n \r\n // \uD83C\uDD95 \uC790\uB3D9 \uD3FC \uBC14\uC778\uB529\r\n await this.$nextTick(); // DOM\uC774 \uC644\uC804\uD788 \uB80C\uB354\uB9C1\uB41C \uD6C4\r\n this.$bindAutoForms();\r\n },\r\n methods: {\r\n ...script.methods,\r\n // \uB77C\uC6B0\uD305 \uAD00\uB828\r\n navigateTo: (route, params) => router.navigateTo(route, params),\r\n getCurrentRoute: () => router.getCurrentRoute(),\r\n \r\n // \uD1B5\uD569\uB41C \uD30C\uB77C\uBBF8\uD130 \uAD00\uB9AC (\uB77C\uC6B0\uD305 + \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130)\r\n getParams: () => router.queryManager?.getAllParams() || {},\r\n getParam: (key, defaultValue) => router.queryManager?.getParam(key, defaultValue),\r\n \r\n // i18n \uAD00\uB828\r\n $t: (key, params) => router.i18nManager?.t(key, params) || key,\r\n\r\n // \uC778\uC99D \uAD00\uB828\r\n $isAuthenticated: () => router.authManager?.isUserAuthenticated() || false,\r\n $logout: () => router.authManager ? router.navigateTo(router.authManager.handleLogout()) : null,\r\n $loginSuccess: (target) => router.authManager ? router.navigateTo(router.authManager.handleLoginSuccess(target)) : null,\r\n $checkAuth: (route) => router.authManager ? router.authManager.checkAuthentication(route) : Promise.resolve({ allowed: true, reason: 'auth_disabled' }),\r\n $getToken: () => router.authManager?.getAccessToken() || null,\r\n $setToken: (token, options) => router.authManager?.setAccessToken(token, options) || false,\r\n $removeToken: (storage) => router.authManager?.removeAccessToken(storage) || null,\r\n $getAuthCookie: () => router.authManager?.getAuthCookie() || null,\r\n $getCookie: (name) => router.authManager?.getCookieValue(name) || null,\r\n \r\n // \uB370\uC774\uD130 fetch (\uB2E8\uC77C API \uB610\uB294 \uD2B9\uC815 API)\r\n async $fetchData(apiName) {\r\n if (!script.dataURL) return;\r\n \r\n this.$dataLoading = true;\r\n try {\r\n if (typeof script.dataURL === 'string') {\r\n // \uAE30\uC874 \uB2E8\uC77C API \uBC29\uC2DD\r\n const data = await router.routeLoader.fetchComponentData(script.dataURL);\r\n if (router.errorHandler) router.errorHandler.debug('RouteLoader', `Data fetched for ${routeName}:`, data);\r\n Object.assign(this, data);\r\n this.$emit('data-loaded', data);\r\n } else if (typeof script.dataURL === 'object' && apiName) {\r\n // \uD2B9\uC815 API\uB9CC \uC0C8\uB85C\uACE0\uCE68\r\n const url = script.dataURL[apiName];\r\n if (url) {\r\n const data = await router.routeLoader.fetchComponentData(url);\r\n if (router.errorHandler) router.errorHandler.debug('RouteLoader', `Data fetched for ${routeName}.${apiName}:`, data);\r\n this[apiName] = data;\r\n this.$emit('data-loaded', { [apiName]: data });\r\n }\r\n } else {\r\n // \uB2E4\uC911 API - \uC804\uCCB4 \uC0C8\uB85C\uACE0\uCE68\r\n await this.$fetchMultipleData();\r\n }\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Failed to fetch data for ${routeName}:`, error);\r\n this.$emit('data-error', error);\r\n } finally {\r\n this.$dataLoading = false;\r\n }\r\n },\r\n\r\n // \uB2E4\uC911 API \uB370\uC774\uD130 fetch\r\n async $fetchMultipleData() {\r\n if (!script.dataURL || typeof script.dataURL !== 'object') return;\r\n \r\n const dataURLs = script.dataURL;\r\n this.$dataLoading = true;\r\n \r\n try {\r\n // \uBCD1\uB82C\uB85C \uBAA8\uB4E0 API \uD638\uCD9C\r\n const promises = Object.entries(dataURLs).map(async ([key, url]) => {\r\n try {\r\n const data = await router.routeLoader.fetchComponentData(url);\r\n return { key, data, success: true };\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Failed to fetch ${key} for ${routeName}:`, error);\r\n return { key, error, success: false };\r\n }\r\n });\r\n \r\n const results = await Promise.all(promises);\r\n const successfulResults = {};\r\n const errors = {};\r\n \r\n // \uACB0\uACFC \uCC98\uB9AC\r\n results.forEach(({ key, data, error, success }) => {\r\n if (success) {\r\n this[key] = data;\r\n successfulResults[key] = data;\r\n } else {\r\n errors[key] = error;\r\n }\r\n });\r\n \r\n if (router.errorHandler) router.errorHandler.debug('RouteLoader', `Multiple data fetched for ${routeName}:`, successfulResults);\r\n \r\n // \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n if (Object.keys(successfulResults).length > 0) {\r\n this.$emit('data-loaded', successfulResults);\r\n }\r\n if (Object.keys(errors).length > 0) {\r\n this.$emit('data-error', errors);\r\n }\r\n \r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Failed to fetch multiple data for ${routeName}:`, error);\r\n this.$emit('data-error', error);\r\n } finally {\r\n this.$dataLoading = false;\r\n }\r\n },\r\n\r\n // \uC804\uCCB4 \uB370\uC774\uD130 \uC0C8\uB85C\uACE0\uCE68 (\uBA85\uC2DC\uC801 \uBA54\uC11C\uB4DC)\r\n async $fetchAllData() {\r\n if (typeof script.dataURL === 'string') {\r\n await this.$fetchData();\r\n } else if (typeof script.dataURL === 'object') {\r\n await this.$fetchMultipleData();\r\n }\r\n },\r\n\r\n // \uD83C\uDD95 \uC790\uB3D9 \uD3FC \uBC14\uC778\uB529 \uBA54\uC11C\uB4DC\r\n $bindAutoForms() {\r\n const forms = document.querySelectorAll('form.auto-form, form[action]');\r\n \r\n forms.forEach(form => {\r\n // \uAE30\uC874 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70 (\uC911\uBCF5 \uBC29\uC9C0)\r\n form.removeEventListener('submit', form._boundSubmitHandler);\r\n \r\n // \uC0C8 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uCD94\uAC00\r\n const boundHandler = (e) => this.$handleFormSubmit(e);\r\n form._boundSubmitHandler = boundHandler;\r\n form.addEventListener('submit', boundHandler);\r\n \r\n if (router.errorHandler) router.errorHandler.debug('RouteLoader', `Form auto-bound: ${form.getAttribute('action')}`);\r\n });\r\n },\r\n\r\n // \uD83C\uDD95 \uD3FC \uC11C\uBE0C\uBC0B \uD578\uB4E4\uB7EC\r\n async $handleFormSubmit(event) {\r\n event.preventDefault();\r\n \r\n const form = event.target;\r\n let action = form.getAttribute('action');\r\n const method = form.getAttribute('method') || 'POST';\r\n \r\n // \uD578\uB4E4\uB7EC \uD568\uC218\uB4E4 \uAC00\uC838\uC624\uAE30\r\n const successHandler = form.getAttribute('data-success-handler');\r\n const errorHandler = form.getAttribute('data-error-handler'); \r\n const loadingHandler = form.getAttribute('data-loading-handler');\r\n const redirectTo = form.getAttribute('data-redirect');\r\n\r\n try {\r\n // \uB85C\uB529 \uC2DC\uC791\r\n if (loadingHandler && this[loadingHandler]) {\r\n this[loadingHandler](true, form);\r\n }\r\n\r\n // \uD83C\uDD95 \uC561\uC158 URL\uC5D0 \uAC00\uBCC0 \uD30C\uB77C\uBBF8\uD130 \uCC98\uB9AC (\uAC04\uB2E8\uD55C \uD15C\uD50C\uB9BF \uCE58\uD658)\r\n action = this.$processActionParams(action);\r\n\r\n // \uD074\uB77C\uC774\uC5B8\uD2B8 \uC0AC\uC774\uB4DC \uAC80\uC99D\r\n if (!this.$validateForm(form)) {\r\n return;\r\n }\r\n\r\n // FormData \uC0DD\uC131\r\n const formData = new FormData(form);\r\n const data = Object.fromEntries(formData.entries());\r\n\r\n if (router.errorHandler) router.errorHandler.debug('RouteLoader', `Form submitting to: ${action}`, data);\r\n\r\n // API \uD638\uCD9C\r\n const response = await this.$submitFormData(action, method, data, form);\r\n \r\n // \uC131\uACF5 \uD578\uB4E4\uB7EC \uD638\uCD9C\r\n if (successHandler && this[successHandler]) {\r\n this[successHandler](response, form);\r\n }\r\n\r\n // \uC790\uB3D9 \uB9AC\uB2E4\uC774\uB809\uD2B8\r\n if (redirectTo) {\r\n setTimeout(() => {\r\n this.navigateTo(redirectTo);\r\n }, 1000); // 1\uCD08 \uD6C4 \uB9AC\uB2E4\uC774\uB809\uD2B8\r\n }\r\n\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Form submission error:`, error);\r\n \r\n // \uC5D0\uB7EC \uD578\uB4E4\uB7EC \uD638\uCD9C\r\n if (errorHandler && this[errorHandler]) {\r\n this[errorHandler](error, form);\r\n } else {\r\n console.error('Form submission error:', error);\r\n }\r\n } finally {\r\n // \uB85C\uB529 \uC885\uB8CC\r\n if (loadingHandler && this[loadingHandler]) {\r\n this[loadingHandler](false, form);\r\n }\r\n }\r\n },\r\n\r\n // \uD83C\uDD95 \uC561\uC158 \uD30C\uB77C\uBBF8\uD130 \uCC98\uB9AC \uBA54\uC11C\uB4DC (\uAC04\uB2E8\uD55C \uD15C\uD50C\uB9BF \uCE58\uD658)\r\n $processActionParams(actionTemplate) {\r\n let processedAction = actionTemplate;\r\n \r\n // {paramName} \uD328\uD134 \uCC3E\uAE30\r\n const paramMatches = actionTemplate.match(/\\{([^}]+)\\}/g);\r\n \r\n if (paramMatches) {\r\n paramMatches.forEach(match => {\r\n const paramName = match.slice(1, -1); // {id} -> id\r\n \r\n try {\r\n // \uCEF4\uD3EC\uB10C\uD2B8\uC758 data\uB098 computed, methods\uC5D0\uC11C \uAC12 \uCC3E\uAE30\r\n let paramValue = null;\r\n \r\n // 1. \uBA3C\uC800 getParam\uC73C\uB85C \uB77C\uC6B0\uD2B8 \uD30C\uB77C\uBBF8\uD130\uC5D0\uC11C \uCC3E\uAE30\r\n paramValue = this.getParam(paramName);\r\n \r\n // 2. \uCEF4\uD3EC\uB10C\uD2B8 data\uC5D0\uC11C \uCC3E\uAE30\r\n if (paramValue === null || paramValue === undefined) {\r\n paramValue = this[paramName];\r\n }\r\n \r\n // 3. computed \uC18D\uC131\uC5D0\uC11C \uCC3E\uAE30\r\n if (paramValue === null || paramValue === undefined) {\r\n if (this.$options.computed && this.$options.computed[paramName]) {\r\n paramValue = this[paramName];\r\n }\r\n }\r\n \r\n if (paramValue !== null && paramValue !== undefined) {\r\n // \uD15C\uD50C\uB9BF \uB300\uCCB4: {id} -> \uC2E4\uC81C\uAC12\r\n processedAction = processedAction.replace(\r\n match, \r\n encodeURIComponent(paramValue)\r\n );\r\n \r\n if (router.errorHandler) router.errorHandler.debug('RouteLoader', `Parameter resolved: ${paramName} = ${paramValue}`);\r\n } else {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Parameter '${paramName}' not found in component data, computed, or route params`);\r\n // \uD30C\uB77C\uBBF8\uD130\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC73C\uBA74 \uC6D0\uBCF8 \uADF8\uB300\uB85C \uC720\uC9C0\r\n }\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Error processing parameter '${paramName}':`, error);\r\n // \uC5D0\uB7EC\uAC00 \uBC1C\uC0DD\uD574\uB3C4 \uC6D0\uBCF8 \uADF8\uB300\uB85C \uC720\uC9C0\r\n }\r\n });\r\n }\r\n \r\n return processedAction;\r\n },\r\n\r\n\r\n // \uD83C\uDD95 \uD3FC \uB370\uC774\uD130 \uC11C\uBE0C\uBC0B\r\n async $submitFormData(action, method, data, form) {\r\n // \uD30C\uC77C \uC5C5\uB85C\uB4DC \uCCB4\uD06C\r\n const hasFile = Array.from(form.elements).some(el => el.type === 'file' && el.files.length > 0);\r\n \r\n const headers = {\r\n 'Accept': 'application/json',\r\n // \uC778\uC99D \uD1A0\uD070 \uC790\uB3D9 \uCD94\uAC00\r\n ...(this.$getToken() && {\r\n 'Authorization': `Bearer ${this.$getToken()}`\r\n })\r\n };\r\n\r\n let body;\r\n if (hasFile) {\r\n // \uD30C\uC77C\uC774 \uC788\uC73C\uBA74 FormData \uADF8\uB300\uB85C \uC804\uC1A1\r\n body = new FormData(form);\r\n // Content-Type\uC744 \uC124\uC815\uD558\uC9C0 \uC54A\uC74C (\uBE0C\uB77C\uC6B0\uC800\uAC00 \uC790\uB3D9\uC73C\uB85C multipart/form-data\uB85C \uC124\uC815)\r\n } else {\r\n // JSON\uC73C\uB85C \uC804\uC1A1\r\n headers['Content-Type'] = 'application/json';\r\n body = JSON.stringify(data);\r\n }\r\n\r\n const response = await fetch(action, {\r\n method: method.toUpperCase(),\r\n headers,\r\n body\r\n });\r\n\r\n if (!response.ok) {\r\n let error;\r\n try {\r\n error = await response.json();\r\n } catch (e) {\r\n error = { message: `HTTP ${response.status}: ${response.statusText}` };\r\n }\r\n throw new Error(error.message || `HTTP ${response.status}`);\r\n }\r\n\r\n try {\r\n return await response.json();\r\n } catch (e) {\r\n // \uC751\uB2F5\uC774 JSON\uC774 \uC544\uB2CC \uACBD\uC6B0 (\uC608: 204 No Content)\r\n return { success: true };\r\n }\r\n },\r\n\r\n // \uD83C\uDD95 \uD074\uB77C\uC774\uC5B8\uD2B8 \uC0AC\uC774\uB4DC \uD3FC \uAC80\uC99D\r\n $validateForm(form) {\r\n let isValid = true;\r\n const inputs = form.querySelectorAll('input, textarea, select');\r\n\r\n inputs.forEach(input => {\r\n // \uAE30\uBCF8 HTML5 \uAC80\uC99D\r\n if (!input.checkValidity()) {\r\n isValid = false;\r\n input.classList.add('error');\r\n return;\r\n }\r\n\r\n // \uCEE4\uC2A4\uD140 \uAC80\uC99D \uD568\uC218 \uD655\uC778\r\n const validationFunction = input.getAttribute('data-validation');\r\n if (validationFunction) {\r\n const isInputValid = this.$validateInput(input, validationFunction);\r\n if (!isInputValid) {\r\n isValid = false;\r\n input.classList.add('error');\r\n } else {\r\n input.classList.remove('error');\r\n }\r\n } else {\r\n input.classList.remove('error');\r\n }\r\n });\r\n\r\n return isValid;\r\n },\r\n\r\n // \uD83C\uDD95 \uAC1C\uBCC4 \uC785\uB825 \uAC80\uC99D\r\n $validateInput(input, validationFunction) {\r\n const value = input.value;\r\n \r\n // \uCEE4\uC2A4\uD140 \uAC80\uC99D \uD568\uC218 \uD638\uCD9C\r\n if (typeof this[validationFunction] === 'function') {\r\n try {\r\n return this[validationFunction](value, input);\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Validation function '${validationFunction}' error:`, error);\r\n return false;\r\n }\r\n }\r\n \r\n // \uD568\uC218\uAC00 \uC5C6\uC73C\uBA74 true \uBC18\uD658\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Validation function '${validationFunction}' not found`);\r\n return true;\r\n }\r\n },\r\n _routeName: routeName\r\n };\r\n \r\n // \uAC1C\uBC1C \uBAA8\uB4DC\uC5D0\uC11C\uB9CC \uC2A4\uD0C0\uC77C \uBA54\uD0C0\uB370\uC774\uD130 \uC800\uC7A5 (\uB80C\uB354\uB9C1 \uC2DC \uC8FC\uC785\uC6A9)\r\n if (!isProduction && style) {\r\n component._style = style;\r\n }\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n this.router.cacheManager?.setCache(cacheKey, component);\r\n \r\n return component;\r\n }\r\n\r\n /**\r\n * \uBB38\uC790\uC5F4\uC744 PascalCase\uB85C \uBCC0\uD658\r\n */\r\n toPascalCase(str) {\r\n return str\r\n .split(/[-_\\s]+/) // \uD558\uC774\uD508, \uC5B8\uB354\uC2A4\uCF54\uC5B4, \uACF5\uBC31\uC73C\uB85C \uBD84\uB9AC\r\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\r\n .join('');\r\n }\r\n\r\n /**\r\n * \uAE30\uBCF8 \uD15C\uD50C\uB9BF \uC0DD\uC131\r\n */\r\n generateDefaultTemplate(routeName) {\r\n return `<div class=\"route-${routeName}\"><h1>Route: ${routeName}</h1></div>`;\r\n }\r\n\r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8 \uB370\uC774\uD130 \uAC00\uC838\uC624\uAE30\r\n */\r\n async fetchComponentData(dataURL) {\r\n try {\r\n // \uD604\uC7AC \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130\uB97C URL\uC5D0 \uCD94\uAC00\r\n const queryString = this.router.queryManager?.buildQueryString(this.router.queryManager?.getQueryParams()) || '';\r\n const fullURL = queryString ? `${dataURL}?${queryString}` : dataURL;\r\n \r\n this.log('debug', `Fetching data from: ${fullURL}`);\r\n \r\n const response = await fetch(fullURL, {\r\n method: 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json'\r\n }\r\n });\r\n \r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n \r\n const data = await response.json();\r\n \r\n // \uB370\uC774\uD130 \uC720\uD6A8\uC131 \uAC80\uC0AC\r\n if (typeof data !== 'object' || data === null) {\r\n throw new Error('Invalid data format: expected object');\r\n }\r\n \r\n return data;\r\n \r\n } catch (error) {\r\n this.log('error', 'Failed to fetch component data:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * \uCE90\uC2DC \uBB34\uD6A8\uD654\r\n */\r\n invalidateCache(routeName) {\r\n if (this.router.cacheManager) {\r\n this.router.cacheManager.invalidateComponentCache(routeName);\r\n }\r\n this.log('debug', `Cache invalidated for route: ${routeName}`);\r\n }\r\n\r\n /**\r\n * \uD1B5\uACC4 \uC815\uBCF4 \uBC18\uD658\r\n */\r\n getStats() {\r\n return {\r\n environment: this.config.environment,\r\n basePath: this.config.basePath,\r\n routesPath: this.config.routesPath,\r\n useLayout: this.config.useLayout,\r\n useComponents: this.config.useComponents\r\n };\r\n }\r\n\r\n /**\r\n * \uD398\uC774\uC9C0 \uC81C\uBAA9 \uC0DD\uC131\r\n */\r\n generatePageTitle(routeName) {\r\n return this.toPascalCase(routeName).replace(/([A-Z])/g, ' $1').trim();\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'RouteLoader', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.log('debug', 'RouteLoader destroyed');\r\n this.router = null;\r\n }\r\n}", "/**\r\n * ViewLogic Error Handling System\r\n * \uB77C\uC6B0\uD2B8 \uBC0F \uC2DC\uC2A4\uD15C \uC5D0\uB7EC \uCC98\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class ErrorHandler {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n enableErrorReporting: options.enableErrorReporting !== false,\r\n debug: options.debug || false,\r\n logLevel: options.logLevel || (options.debug ? 'debug' : 'info'),\r\n environment: options.environment || 'development'\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870\r\n this.router = router;\r\n \r\n // \uB85C\uADF8 \uB808\uBCA8 \uB9E4\uD551\r\n this.logLevels = {\r\n error: 0,\r\n warn: 1, \r\n info: 2,\r\n debug: 3\r\n };\r\n \r\n this.log('info', 'ErrorHandler', 'ErrorHandler initialized with config:', this.config);\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD2B8 \uC5D0\uB7EC \uCC98\uB9AC\r\n */\r\n async handleRouteError(routeName, error) {\r\n let errorCode = 500;\r\n let errorMessage = '\uD398\uC774\uC9C0\uB97C \uB85C\uB4DC\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.';\r\n \r\n this.debug('ErrorHandler', '\uC5D0\uB7EC \uC0C1\uC138:', error.message, error.name);\r\n \r\n // \uC5D0\uB7EC \uD0C0\uC785 \uBD84\uC11D (\uB354 \uC815\uD655\uD55C 404 \uAC10\uC9C0)\r\n if (error.message.includes('not found') || \r\n error.message.includes('404') ||\r\n error.message.includes('Failed to resolve') ||\r\n error.message.includes('Failed to fetch') ||\r\n (error.name === 'TypeError' && error.message.includes('resolve'))) {\r\n errorCode = 404;\r\n errorMessage = `'${routeName}' \uD398\uC774\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`;\r\n } else if (error.message.includes('network') && !error.message.includes('not found')) {\r\n errorCode = 503;\r\n errorMessage = '\uB124\uD2B8\uC6CC\uD06C \uC5F0\uACB0\uC744 \uD655\uC778\uD574 \uC8FC\uC138\uC694.';\r\n } else if (error.message.includes('permission') || error.message.includes('403')) {\r\n errorCode = 403;\r\n errorMessage = '\uD398\uC774\uC9C0\uC5D0 \uC811\uADFC\uD560 \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.';\r\n }\r\n \r\n this.debug('ErrorHandler', `\uC5D0\uB7EC \uCF54\uB4DC \uACB0\uC815: ${errorCode} (\uB77C\uC6B0\uD2B8: ${routeName})`);\r\n \r\n // \uC5D0\uB7EC \uB9AC\uD3EC\uD305\r\n if (this.config.enableErrorReporting) {\r\n this.reportError(routeName, error, errorCode);\r\n }\r\n \r\n try {\r\n // 404 \uD398\uC774\uC9C0 \uC804\uC6A9 \uCC98\uB9AC\r\n if (errorCode === 404) {\r\n await this.load404Page();\r\n } else {\r\n // \uC77C\uBC18 \uC5D0\uB7EC \uD398\uC774\uC9C0\r\n await this.loadErrorPage(errorCode, errorMessage);\r\n }\r\n } catch (fallbackError) {\r\n this.error('ErrorHandler', '\uC5D0\uB7EC \uD398\uC774\uC9C0 \uB85C\uB529 \uC2E4\uD328:', fallbackError);\r\n // \uBAA8\uB4E0 \uC5D0\uB7EC \uD398\uC774\uC9C0\uAC00 \uC2E4\uD328\uD588\uC744 \uB54C \uCD5C\uD6C4\uC758 \uD3F4\uBC31 \uD398\uC774\uC9C0 \uD45C\uC2DC\r\n this.showFallbackErrorPage(errorCode, errorMessage);\r\n }\r\n }\r\n\r\n /**\r\n * 404 \uD398\uC774\uC9C0 \uB85C\uB529\r\n */\r\n async load404Page() {\r\n try {\r\n this.info('ErrorHandler', 'Loading 404 page...');\r\n const component = await this.createVueComponent('404');\r\n await this.renderComponentWithTransition(component, '404');\r\n this.info('ErrorHandler', '404 page loaded successfully');\r\n } catch (error) {\r\n this.error('ErrorHandler', '404 page loading failed:', error);\r\n // 404 \uD398\uC774\uC9C0\uB3C4 \uC5C6\uC73C\uBA74 \uAC04\uB2E8\uD55C \uC5D0\uB7EC \uBA54\uC2DC\uC9C0 \uD45C\uC2DC\r\n this.showFallbackErrorPage('404', '\uD398\uC774\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.');\r\n }\r\n }\r\n\r\n /**\r\n * \uC5D0\uB7EC \uD398\uC774\uC9C0 \uB85C\uB529\r\n */\r\n async loadErrorPage(errorCode, errorMessage) {\r\n try {\r\n this.info('ErrorHandler', `Loading error page for ${errorCode}...`);\r\n \r\n // \uC5D0\uB7EC \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131\r\n const errorComponent = await this.createErrorComponent(errorCode, errorMessage);\r\n await this.renderComponentWithTransition(errorComponent, 'error');\r\n this.info('ErrorHandler', `Error page ${errorCode} loaded successfully`);\r\n } catch (error) {\r\n this.error('ErrorHandler', `Error page ${errorCode} loading failed:`, error);\r\n // \uC5D0\uB7EC \uD398\uC774\uC9C0\uB3C4 \uB85C\uB529 \uC2E4\uD328\uD558\uBA74 \uD3F4\uBC31 \uD45C\uC2DC\r\n this.showFallbackErrorPage(errorCode, errorMessage);\r\n }\r\n }\r\n\r\n /**\r\n * \uC5D0\uB7EC \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131\r\n */\r\n async createErrorComponent(errorCode, errorMessage) {\r\n try {\r\n // \uC5D0\uB7EC \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uB3D9\uC801\uC73C\uB85C \uB85C\uB4DC\r\n const component = await this.createVueComponent('error');\r\n \r\n // \uC5D0\uB7EC \uC815\uBCF4\uB97C props\uB85C \uC804\uB2EC\r\n const errorComponent = {\r\n ...component,\r\n data() {\r\n const originalData = component.data ? component.data() : {};\r\n return {\r\n ...originalData,\r\n errorCode,\r\n errorMessage,\r\n showRetry: true,\r\n showGoHome: true\r\n };\r\n }\r\n };\r\n \r\n return errorComponent;\r\n } catch (error) {\r\n // \uC5D0\uB7EC \uCEF4\uD3EC\uB10C\uD2B8\uB3C4 \uB85C\uB4DC\uD560 \uC218 \uC5C6\uB294 \uACBD\uC6B0 \uAC04\uB2E8\uD55C \uC5D0\uB7EC \uD45C\uC2DC\r\n this.error('ErrorHandler', 'Error component load failed:', error);\r\n throw new Error(`Cannot load error page: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * \uD3F4\uBC31 \uC5D0\uB7EC \uD398\uC774\uC9C0 \uD45C\uC2DC (\uBAA8\uB4E0 \uC5D0\uB7EC \uD398\uC774\uC9C0\uAC00 \uC2E4\uD328\uD588\uC744 \uB54C)\r\n */\r\n showFallbackErrorPage(errorCode, errorMessage) {\r\n const appElement = document.getElementById('app');\r\n if (!appElement) return;\r\n\r\n const fallbackHTML = `\r\n <div class=\"fallback-error-page\" style=\"\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n min-height: 100vh;\r\n padding: 2rem;\r\n text-align: center;\r\n background: #f8f9fa;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\r\n \">\r\n <div style=\"\r\n background: white;\r\n padding: 3rem;\r\n border-radius: 12px;\r\n box-shadow: 0 4px 20px rgba(0,0,0,0.1);\r\n max-width: 500px;\r\n \">\r\n <h1 style=\"\r\n font-size: 4rem;\r\n margin: 0;\r\n color: #dc3545;\r\n font-weight: 300;\r\n \">${errorCode}</h1>\r\n <h2 style=\"\r\n margin: 1rem 0;\r\n color: #495057;\r\n font-weight: 400;\r\n \">${errorMessage}</h2>\r\n <p style=\"\r\n color: #6c757d;\r\n margin-bottom: 2rem;\r\n line-height: 1.5;\r\n \">\uC694\uCCAD\uD558\uC2E0 \uD398\uC774\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.</p>\r\n <button onclick=\"window.location.hash = '#/'\" style=\"\r\n background: #007bff;\r\n color: white;\r\n border: none;\r\n padding: 12px 24px;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n font-size: 1rem;\r\n transition: background 0.2s;\r\n \" onmouseover=\"this.style.background='#0056b3'\" onmouseout=\"this.style.background='#007bff'\">\r\n \uD648\uC73C\uB85C \uB3CC\uC544\uAC00\uAE30\r\n </button>\r\n </div>\r\n </div>\r\n `;\r\n\r\n // \uAE30\uC874 \uCEE8\uD14C\uC774\uB108\uB4E4 \uC815\uB9AC\r\n appElement.innerHTML = fallbackHTML;\r\n \r\n this.info('ErrorHandler', `Fallback error page displayed for ${errorCode}`);\r\n }\r\n\r\n /**\r\n * \uC5D0\uB7EC \uB9AC\uD3EC\uD305\r\n */\r\n reportError(routeName, error, errorCode) {\r\n const errorReport = {\r\n route: routeName,\r\n errorCode,\r\n errorMessage: error.message,\r\n stack: error.stack,\r\n url: window.location.href,\r\n userAgent: navigator.userAgent,\r\n timestamp: new Date().toISOString(),\r\n routerConfig: {\r\n environment: this.router.config.environment,\r\n mode: this.router.config.mode\r\n }\r\n };\r\n \r\n this.error('ErrorHandler', '\uB77C\uC6B0\uD130 \uC5D0\uB7EC \uB9AC\uD3EC\uD2B8:', errorReport);\r\n \r\n // \uCD94\uD6C4 \uC5D0\uB7EC \uCD94\uC801 \uC11C\uBE44\uC2A4\uB85C \uC804\uC1A1\uD560 \uC218 \uC788\uC74C\r\n // \uC608: analytics.track('router_error', errorReport);\r\n }\r\n\r\n /**\r\n * Vue \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131 (RouteLoader \uC704\uC784)\r\n */\r\n async createVueComponent(routeName) {\r\n if (this.router.routeLoader) {\r\n return await this.router.routeLoader.createVueComponent(routeName);\r\n }\r\n throw new Error('RouteLoader not available');\r\n }\r\n\r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8 \uB80C\uB354\uB9C1 (ViewManager \uC704\uC784)\r\n */\r\n async renderComponentWithTransition(component, routeName) {\r\n if (this.router.renderComponentWithTransition) {\r\n return await this.router.renderComponentWithTransition(component, routeName);\r\n }\r\n throw new Error('Render function not available');\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569 \uB85C\uAE45 \uC2DC\uC2A4\uD15C\r\n * @param {string} level - \uB85C\uADF8 \uB808\uBCA8 (error, warn, info, debug)\r\n * @param {string} component - \uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984 (\uC120\uD0DD\uC801)\r\n * @param {...any} args - \uB85C\uADF8 \uBA54\uC2DC\uC9C0\r\n */\r\n log(level, component, ...args) {\r\n // \uD558\uC704 \uD638\uD658\uC131: \uAE30\uC874 \uBC29\uC2DD\uB3C4 \uC9C0\uC6D0\r\n if (typeof level !== 'string' || !this.logLevels.hasOwnProperty(level)) {\r\n args = [component, ...args];\r\n component = level;\r\n level = this.config.debug ? 'debug' : 'info';\r\n }\r\n \r\n // \uB85C\uADF8 \uB808\uBCA8 \uD655\uC778\r\n const currentLevelValue = this.logLevels[this.config.logLevel] || this.logLevels.info;\r\n const messageLevelValue = this.logLevels[level] || this.logLevels.info;\r\n \r\n if (messageLevelValue > currentLevelValue) {\r\n return; // \uD604\uC7AC \uC124\uC815\uB41C \uB808\uBCA8\uBCF4\uB2E4 \uB192\uC73C\uBA74 \uCD9C\uB825 \uC548\uD568\r\n }\r\n \r\n // \uD504\uB85C\uB355\uC158 \uD658\uACBD\uC5D0\uC11C\uB294 error\uC640 warn\uB9CC \uCD9C\uB825\r\n if (this.config.environment === 'production' && messageLevelValue > this.logLevels.warn) {\r\n return;\r\n }\r\n \r\n const prefix = component ? `[${component}]` : '[ViewLogic]';\r\n const timestamp = new Date().toISOString().substring(11, 23); // HH:MM:SS.mmm\r\n \r\n switch (level) {\r\n case 'error':\r\n console.error(`${timestamp} ${prefix}`, ...args);\r\n break;\r\n case 'warn':\r\n console.warn(`${timestamp} ${prefix}`, ...args);\r\n break;\r\n case 'info':\r\n console.info(`${timestamp} ${prefix}`, ...args);\r\n break;\r\n case 'debug':\r\n console.log(`${timestamp} ${prefix}`, ...args);\r\n break;\r\n default:\r\n console.log(`${timestamp} ${prefix}`, ...args);\r\n }\r\n }\r\n \r\n /**\r\n * \uC5D0\uB7EC \uB85C\uADF8 (\uD56D\uC0C1 \uCD9C\uB825)\r\n */\r\n error(component, ...args) {\r\n this.log('error', component, ...args);\r\n }\r\n \r\n /**\r\n * \uACBD\uACE0 \uB85C\uADF8\r\n */\r\n warn(component, ...args) {\r\n this.log('warn', component, ...args);\r\n }\r\n \r\n /**\r\n * \uC815\uBCF4 \uB85C\uADF8\r\n */\r\n info(component, ...args) {\r\n this.log('info', component, ...args);\r\n }\r\n \r\n /**\r\n * \uB514\uBC84\uADF8 \uB85C\uADF8\r\n */\r\n debug(component, ...args) {\r\n this.log('debug', component, ...args);\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.router = null;\r\n this.info('ErrorHandler', 'ErrorHandler destroyed');\r\n }\r\n}", "/**\r\n * ComponentLoader\r\n * \uB3D9\uC801\uC73C\uB85C \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uB85C\uB4DC\uD558\uACE0 \uB4F1\uB85D\uD558\uB294 \uC2DC\uC2A4\uD15C\r\n */\r\nexport class ComponentLoader {\r\n constructor(router = null, options = {}) {\r\n\r\n this.config = {\r\n basePath: options.basePath || '/src/components',\r\n debug: options.debug || false,\r\n environment: options.environment || 'development',\r\n ...options\r\n };\r\n \r\n this.router = router;\r\n this.loadingPromises = new Map();\r\n this.unifiedComponents = null;\r\n }\r\n \r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'ComponentLoader', ...args);\r\n }\r\n }\r\n \r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uBE44\uB3D9\uAE30\uB85C \uB85C\uB4DC\r\n */\r\n async loadComponent(componentName) {\r\n if (!componentName || typeof componentName !== 'string') {\r\n throw new Error('Component name must be a non-empty string');\r\n }\r\n \r\n // \uC774\uBBF8 \uB85C\uB529 \uC911\uC778 \uACBD\uC6B0 \uAE30\uC874 Promise \uBC18\uD658\r\n if (this.loadingPromises.has(componentName)) {\r\n return this.loadingPromises.get(componentName);\r\n }\r\n \r\n const loadPromise = this._loadComponentFromFile(componentName);\r\n this.loadingPromises.set(componentName, loadPromise);\r\n \r\n try {\r\n const component = await loadPromise;\r\n return component;\r\n } catch (error) {\r\n throw error;\r\n } finally {\r\n this.loadingPromises.delete(componentName);\r\n }\r\n }\r\n \r\n /**\r\n * \uD30C\uC77C\uC5D0\uC11C \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB4DC\r\n */\r\n async _loadComponentFromFile(componentName) {\r\n const componentPath = `${this.config.basePath}/${componentName}.js`;\r\n \r\n try {\r\n const module = await import(componentPath);\r\n const component = module.default;\r\n \r\n if (!component) {\r\n throw new Error(`Component '${componentName}' has no default export`);\r\n }\r\n \r\n if (!component.name) {\r\n component.name = componentName;\r\n }\r\n \r\n this.log('debug', `Component '${componentName}' loaded successfully`);\r\n return component;\r\n \r\n } catch (error) {\r\n this.log('error', `Failed to load component '${componentName}':`, error);\r\n throw new Error(`Component '${componentName}' not found: ${error.message}`);\r\n }\r\n }\r\n \r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8 \uBAA8\uB4C8 \uD074\uB9AC\uC5B4\r\n */\r\n clearComponents() {\r\n this.loadingPromises.clear();\r\n this.unifiedComponents = null;\r\n this.log('debug', 'All components cleared');\r\n }\r\n \r\n /**\r\n * \uD658\uACBD\uC5D0 \uB530\uB978 \uBAA8\uB4E0 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529 (\uCE90\uC2F1 \uC9C0\uC6D0)\r\n */\r\n async loadAllComponents() {\r\n // \uC774\uBBF8 \uB85C\uB4DC\uB41C unifiedComponents\uAC00 \uC788\uC73C\uBA74 \uBC18\uD658\r\n if (this.unifiedComponents) {\r\n this.log('debug', 'Using existing unified components');\r\n return this.unifiedComponents;\r\n }\r\n \r\n // \uC6B4\uC601 \uBAA8\uB4DC: \uD1B5\uD569 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529 \uC2DC\uB3C4\r\n if (this.config.environment === 'production') {\r\n return await this._loadProductionComponents();\r\n }\r\n \r\n // \uAC1C\uBC1C \uBAA8\uB4DC: \uAC1C\uBCC4 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529\r\n return await this._loadDevelopmentComponents();\r\n }\r\n \r\n /**\r\n * \uC6B4\uC601 \uBAA8\uB4DC: \uD1B5\uD569 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529\r\n */\r\n async _loadProductionComponents() {\r\n try {\r\n const componentsPath = `${this.config.routesPath}/_components.js`;\r\n this.log('info', '[PRODUCTION] Loading unified components from:', componentsPath);\r\n \r\n const componentsModule = await import(componentsPath);\r\n \r\n if (typeof componentsModule.registerComponents === 'function') {\r\n this.unifiedComponents = componentsModule.components || {};\r\n this.log('info', `[PRODUCTION] Unified components loaded: ${Object.keys(this.unifiedComponents).length} components`);\r\n return this.unifiedComponents;\r\n } else {\r\n throw new Error('registerComponents function not found in components module');\r\n }\r\n } catch (error) {\r\n this.log('warn', '[PRODUCTION] Failed to load unified components:', error.message);\r\n this.unifiedComponents = {};\r\n return {};\r\n }\r\n }\r\n \r\n /**\r\n * \uAC1C\uBC1C \uBAA8\uB4DC: \uAC1C\uBCC4 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529\r\n */\r\n async _loadDevelopmentComponents() {\r\n const componentNames = this._getComponentNames();\r\n const components = {};\r\n \r\n this.log('info', `[DEVELOPMENT] Loading individual components: ${componentNames.join(', ')}`);\r\n \r\n for (const name of componentNames) {\r\n try {\r\n const component = await this.loadComponent(name);\r\n if (component) {\r\n components[name] = component;\r\n }\r\n } catch (loadError) {\r\n this.log('warn', `[DEVELOPMENT] Failed to load component ${name}:`, loadError.message);\r\n }\r\n }\r\n \r\n this.unifiedComponents = components;\r\n this.log('info', `[DEVELOPMENT] Individual components loaded: ${Object.keys(components).length} components`);\r\n return components;\r\n }\r\n \r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984 \uBAA9\uB85D \uAC00\uC838\uC624\uAE30\r\n */\r\n _getComponentNames() {\r\n if (Array.isArray(this.config.componentNames) && this.config.componentNames.length > 0) {\r\n return [...this.config.componentNames];\r\n }\r\n \r\n // \uD3F4\uBC31: \uAE30\uC874 \uD558\uB4DC\uCF54\uB529 \uBAA9\uB85D\r\n return [\r\n 'Button', 'Modal', 'Card', 'Toast', 'Input', 'Tabs',\r\n 'Checkbox', 'Alert', 'DynamicInclude', 'HtmlInclude'\r\n ];\r\n }\r\n \r\n /**\r\n * \uBA54\uBAA8\uB9AC \uC815\uB9AC\r\n */\r\n dispose() {\r\n this.clearComponents();\r\n this.log('debug', 'ComponentLoader disposed');\r\n this.router = null;\r\n }\r\n}", "// ViewLogic Router - ES6 Module\r\nimport { I18nManager } from './plugins/I18nManager.js';\r\nimport { AuthManager } from './plugins/AuthManager.js';\r\nimport { CacheManager } from './plugins/CacheManager.js';\r\nimport { QueryManager } from './plugins/QueryManager.js';\r\nimport { RouteLoader } from './core/RouteLoader.js';\r\nimport { ErrorHandler } from './core/ErrorHandler.js';\r\nimport { ComponentLoader } from './core/ComponentLoader.js';\r\n\r\nexport class ViewLogicRouter {\r\n constructor(options = {}) {\r\n // \uBC84\uC804 \uC815\uBCF4\r\n this.version = options.version || '1.0.0';\r\n \r\n // \uAE30\uBCF8 \uD658\uACBD\uC124\uC815 \uCD5C\uC801\uD654\r\n this.config = this._buildConfig(options);\r\n \r\n this.currentHash = '';\r\n this.currentVueApp = null;\r\n this.previousVueApp = null; // \uC774\uC804 Vue \uC571 (\uC804\uD658 \uD6A8\uACFC\uB97C \uC704\uD574 \uBCF4\uAD00)\r\n this.componentLoader = null; // \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB354 \uC778\uC2A4\uD134\uC2A4\r\n\r\n // LoadingManager\uAC00 \uC5C6\uC744 \uB54C\uB97C \uC704\uD55C \uAE30\uBCF8 \uC804\uD658 \uC0C1\uD0DC\r\n this.transitionInProgress = false;\r\n \r\n // \uCD08\uAE30\uD654 \uC900\uBE44 \uC0C1\uD0DC\r\n this.isReady = false;\r\n this.readyPromise = null;\r\n \r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uBC14\uC778\uB529 \uCD5C\uC801\uD654\r\n this._boundHandleRouteChange = this.handleRouteChange.bind(this);\r\n \r\n // \uBAA8\uB4E0 \uCD08\uAE30\uD654\uB97C \uD55C\uBC88\uC5D0 \uCC98\uB9AC\r\n this.readyPromise = this.initialize();\r\n }\r\n\r\n /**\r\n * \uC124\uC815 \uBE4C\uB4DC (\uBD84\uB9AC\uD558\uC5EC \uAC00\uB3C5\uC131 \uD5A5\uC0C1)\r\n */\r\n _buildConfig(options) {\r\n const currentOrigin = window.location.origin;\r\n \r\n const defaults = {\r\n basePath: `${currentOrigin}/src`,\r\n mode: 'hash',\r\n cacheMode: 'memory',\r\n cacheTTL: 300000,\r\n maxCacheSize: 50,\r\n useLayout: true,\r\n defaultLayout: 'default',\r\n environment: 'development',\r\n routesPath: `${currentOrigin}/routes`,\r\n enableErrorReporting: true,\r\n useComponents: true,\r\n componentNames: ['Button', 'Modal', 'Card', 'Toast', 'Input', 'Tabs', 'Checkbox', 'Alert', 'DynamicInclude', 'HtmlInclude'],\r\n useI18n: true,\r\n defaultLanguage: 'ko',\r\n i18nPath: `${currentOrigin}/i18n`,\r\n logLevel: 'info',\r\n authEnabled: false,\r\n loginRoute: 'login',\r\n protectedRoutes: [],\r\n protectedPrefixes: [],\r\n publicRoutes: ['login', 'register', 'home'],\r\n checkAuthFunction: null,\r\n redirectAfterLogin: 'home',\r\n authCookieName: 'authToken',\r\n authFallbackCookieNames: ['accessToken', 'token', 'jwt'],\r\n authStorage: 'cookie',\r\n authCookieOptions: {},\r\n authSkipValidation: false,\r\n enableParameterValidation: true,\r\n maxParameterLength: 1000,\r\n maxParameterCount: 50,\r\n maxArraySize: 100,\r\n allowedKeyPattern: /^[a-zA-Z0-9_-]+$/,\r\n logSecurityWarnings: true\r\n };\r\n \r\n const config = { ...defaults, ...options };\r\n \r\n // \uC0AC\uC6A9\uC790\uAC00 \uC81C\uACF5\uD55C basePath\uC640 routesPath\uC5D0 origin\uC774 \uC5C6\uC73C\uBA74 \uCD94\uAC00\r\n if (options.basePath && !options.basePath.startsWith('http')) {\r\n config.basePath = `${currentOrigin}${options.basePath}`;\r\n }\r\n if (options.routesPath && !options.routesPath.startsWith('http')) {\r\n config.routesPath = `${currentOrigin}${options.routesPath}`;\r\n }\r\n if (options.i18nPath && !options.i18nPath.startsWith('http')) {\r\n config.i18nPath = `${currentOrigin}${options.i18nPath}`;\r\n }\r\n \r\n return config;\r\n }\r\n\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.errorHandler) {\r\n this.errorHandler.log(level, 'Router', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569 \uCD08\uAE30\uD654 - \uB9E4\uB2C8\uC800 \uC0DD\uC131 \u2192 \uBE44\uB3D9\uAE30 \uB85C\uB529 \u2192 \uB77C\uC6B0\uD130 \uC2DC\uC791\r\n */\r\n async initialize() {\r\n try {\r\n // 1. \uB9E4\uB2C8\uC800 \uCD08\uAE30\uD654 (\uB3D9\uAE30)\r\n // \uD56D\uC0C1 \uD544\uC694\uD55C \uB9E4\uB2C8\uC800\uB4E4\r\n this.cacheManager = new CacheManager(this, this.config);\r\n this.routeLoader = new RouteLoader(this, this.config);\r\n this.queryManager = new QueryManager(this, this.config);\r\n this.errorHandler = new ErrorHandler(this, this.config);\r\n \r\n // \uC870\uAC74\uBD80 \uB9E4\uB2C8\uC800\uB4E4\r\n if (this.config.useI18n) {\r\n this.i18nManager = new I18nManager(this, this.config);\r\n if (this.i18nManager.initPromise) {\r\n await this.i18nManager.initPromise;\r\n }\r\n }\r\n \r\n if (this.config.authEnabled) {\r\n this.authManager = new AuthManager(this, this.config);\r\n }\r\n \r\n if (this.config.useComponents) {\r\n try {\r\n this.componentLoader = new ComponentLoader(this, {\r\n ...this.config,\r\n basePath: `${this.config.basePath}/components`,\r\n cache: true,\r\n componentNames: this.config.componentNames\r\n });\r\n await this.componentLoader.loadAllComponents();\r\n this.log('info', 'ComponentLoader initialized successfully');\r\n } catch (componentError) {\r\n this.log('warn', 'ComponentLoader initialization failed, continuing without components:', componentError.message);\r\n this.componentLoader = null; // \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB354 \uBE44\uD65C\uC131\uD654\r\n }\r\n }\r\n \r\n // 2. \uB77C\uC6B0\uD130 \uC2DC\uC791\r\n this.isReady = true;\r\n this.init();\r\n \r\n } catch (error) {\r\n this.log('error', 'Router initialization failed:', error);\r\n // \uC2E4\uD328\uD574\uB3C4 \uB77C\uC6B0\uD130\uB294 \uC2DC\uC791 (graceful degradation)\r\n this.isReady = true;\r\n this.init();\r\n }\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD130\uAC00 \uC900\uBE44\uB420 \uB54C\uAE4C\uC9C0 \uB300\uAE30\r\n */\r\n async waitForReady() {\r\n if (this.isReady) return true;\r\n if (this.readyPromise) {\r\n await this.readyPromise;\r\n }\r\n return this.isReady;\r\n }\r\n\r\n\r\n init() {\r\n const isHashMode = this.config.mode === 'hash';\r\n \r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uB4F1\uB85D (\uBA54\uBAA8\uB9AC \uCD5C\uC801\uD654)\r\n window.addEventListener(\r\n isHashMode ? 'hashchange' : 'popstate',\r\n this._boundHandleRouteChange\r\n );\r\n \r\n // DOM \uB85C\uB4DC \uCC98\uB9AC \uD1B5\uD569\r\n const initRoute = () => {\r\n if (isHashMode && !window.location.hash) {\r\n window.location.hash = '#/';\r\n } else if (!isHashMode && window.location.pathname === '/') {\r\n this.navigateTo('home');\r\n } else {\r\n this.handleRouteChange();\r\n }\r\n };\r\n \r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', initRoute);\r\n } else {\r\n // requestAnimationFrame\uC73C\uB85C \uC131\uB2A5 \uAC1C\uC120\r\n requestAnimationFrame(initRoute);\r\n }\r\n }\r\n\r\n handleRouteChange() {\r\n const { route, queryParams } = this._parseCurrentLocation();\r\n \r\n // Store current query parameters in QueryManager\r\n this.queryManager?.setCurrentQueryParams(queryParams);\r\n \r\n // \uBCC0\uACBD\uC0AC\uD56D\uC774 \uC788\uC744 \uB54C\uB9CC \uB85C\uB4DC (\uC131\uB2A5 \uCD5C\uC801\uD654)\r\n if (route !== this.currentHash || this.queryManager?.hasQueryParamsChanged(queryParams)) {\r\n this.currentHash = route;\r\n this.loadRoute(route);\r\n }\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uC704\uCE58 \uD30C\uC2F1 (\uBD84\uB9AC\uD558\uC5EC \uAC00\uB3C5\uC131 \uD5A5\uC0C1)\r\n */\r\n _parseCurrentLocation() {\r\n if (this.config.mode === 'hash') {\r\n const hashPath = window.location.hash.slice(1) || '/';\r\n const [pathPart, queryPart] = hashPath.split('?');\r\n \r\n // \uACBD\uB85C \uD30C\uC2F1 \uCD5C\uC801\uD654\r\n let route = 'home';\r\n if (pathPart && pathPart !== '/') {\r\n route = pathPart.startsWith('/') ? pathPart.slice(1) : pathPart;\r\n }\r\n \r\n return {\r\n route: route || 'home',\r\n queryParams: this.queryManager?.parseQueryString(queryPart || window.location.search.slice(1)) || {}\r\n };\r\n } else {\r\n return {\r\n route: window.location.pathname.slice(1) || 'home',\r\n queryParams: this.queryManager?.parseQueryString(window.location.search.slice(1)) || {}\r\n };\r\n }\r\n }\r\n\r\n async loadRoute(routeName) {\r\n // \uC804\uD658\uC774 \uC9C4\uD589 \uC911\uC774\uBA74 \uBB34\uC2DC\r\n const inProgress = this.transitionInProgress;\r\n \r\n if (inProgress) {\r\n return;\r\n }\r\n\r\n try {\r\n this.transitionInProgress = true;\r\n \r\n // \uC778\uC99D \uCCB4\uD06C\r\n const authResult = this.authManager ? \r\n await this.authManager.checkAuthentication(routeName) :\r\n { allowed: true, reason: 'auth_disabled' };\r\n if (!authResult.allowed) {\r\n // \uC778\uC99D \uC2E4\uD328 \uC2DC \uB85C\uADF8\uC778 \uD398\uC774\uC9C0\uB85C \uB9AC\uB2E4\uC774\uB809\uD2B8\r\n if (this.authManager) {\r\n this.authManager.emitAuthEvent('auth_required', { \r\n originalRoute: routeName,\r\n loginRoute: this.config.loginRoute \r\n });\r\n \r\n // navigateTo\uB97C \uC0AC\uC6A9\uD558\uC5EC \uC774\uC804 \uD398\uC774\uC9C0\uB85C \uB3CC\uC544\uAC00\uAE30 \uC9C0\uC6D0\r\n if (routeName !== this.config.loginRoute) {\r\n this.navigateTo(this.config.loginRoute, { redirect: routeName });\r\n } else {\r\n this.navigateTo(this.config.loginRoute);\r\n }\r\n }\r\n return;\r\n }\r\n \r\n const appElement = document.getElementById('app');\r\n if (!appElement) {\r\n throw new Error('App element not found');\r\n }\r\n\r\n // Vue \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131 (\uBC31\uADF8\uB77C\uC6B4\uB4DC\uC5D0\uC11C)\r\n const component = await this.routeLoader.createVueComponent(routeName);\r\n \r\n // \uC0C8\uB85C\uC6B4 \uD398\uC774\uC9C0\uB97C \uC624\uBC84\uB808\uC774\uB85C \uB80C\uB354\uB9C1\r\n await this.renderComponentWithTransition(component, routeName);\r\n \r\n // \uB85C\uB529 \uC644\uB8CC\r\n \r\n } catch (error) {\r\n this.log('error', `Route loading failed [${routeName}]:`, error.message);\r\n \r\n \r\n // \uC5D0\uB7EC \uD0C0\uC785\uC5D0 \uB530\uB978 \uCC98\uB9AC\r\n if (this.errorHandler) {\r\n await this.errorHandler.handleRouteError(routeName, error);\r\n } else {\r\n console.error('[Router] No error handler available');\r\n }\r\n } finally {\r\n // \uBAA8\uB4E0 \uCC98\uB9AC\uAC00 \uC644\uB8CC\uB41C \uD6C4 \uC804\uD658 \uC0C1\uD0DC \uB9AC\uC14B\r\n this.transitionInProgress = false;\r\n }\r\n }\r\n\r\n async renderComponentWithTransition(vueComponent, routeName) {\r\n const appElement = document.getElementById('app');\r\n if (!appElement) return;\r\n\r\n // \uC0C8\uB85C\uC6B4 \uD398\uC774\uC9C0 \uCEE8\uD14C\uC774\uB108 \uC0DD\uC131\r\n const newPageContainer = document.createElement('div');\r\n newPageContainer.className = 'page-container page-entered';\r\n newPageContainer.id = `page-${routeName}-${Date.now()}`;\r\n \r\n // \uAE30\uC874 \uCEE8\uD14C\uC774\uB108\uAC00 \uC788\uB2E4\uBA74 \uC989\uC2DC \uC228\uAE30\uAE30\r\n const existingContainers = appElement.querySelectorAll('.page-container');\r\n existingContainers.forEach(container => {\r\n container.classList.remove('page-entered');\r\n container.classList.add('page-exiting');\r\n });\r\n\r\n // \uC0C8 \uCEE8\uD14C\uC774\uB108\uB97C \uC571\uC5D0 \uCD94\uAC00\r\n appElement.appendChild(newPageContainer);\r\n\r\n // \uAC1C\uBC1C \uBAA8\uB4DC\uC5D0\uC11C\uB9CC \uC2A4\uD0C0\uC77C \uC801\uC6A9 (\uD504\uB85C\uB355\uC158 \uBAA8\uB4DC\uB294 \uBE4C\uB4DC\uB41C JS\uC5D0\uC11C \uC790\uB3D9 \uCC98\uB9AC)\r\n if (this.config.environment === 'development' && vueComponent._style) {\r\n this.applyStyle(vueComponent._style, routeName);\r\n }\r\n \r\n // \uC0C8\uB85C\uC6B4 Vue \uC571\uC744 \uC0C8 \uCEE8\uD14C\uC774\uB108\uC5D0 \uB9C8\uC6B4\uD2B8\r\n const { createApp } = Vue;\r\n const newVueApp = createApp(vueComponent);\r\n \r\n // Vue 3 \uC804\uC5ED \uC18D\uC131 \uC124\uC815\r\n newVueApp.config.globalProperties.$router = {\r\n navigateTo: (route, params) => this.navigateTo(route, params),\r\n getCurrentRoute: () => this.getCurrentRoute(),\r\n \r\n // \uD1B5\uD569\uB41C \uD30C\uB77C\uBBF8\uD130 \uAD00\uB9AC (\uB77C\uC6B0\uD305 + \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130)\r\n getParams: () => this.queryManager?.getAllParams() || {},\r\n getParam: (key, defaultValue) => this.queryManager?.getParam(key, defaultValue),\r\n \r\n // \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC804\uC6A9 \uBA54\uC11C\uB4DC (\uD558\uC704 \uD638\uD658\uC131)\r\n getQueryParams: () => this.queryManager?.getQueryParams() || {},\r\n getQueryParam: (key, defaultValue) => this.queryManager?.getQueryParam(key, defaultValue),\r\n setQueryParams: (params, replace) => this.queryManager?.setQueryParams(params, replace),\r\n removeQueryParams: (keys) => this.queryManager?.removeQueryParams(keys),\r\n \r\n // \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130 \uC804\uC6A9 \uBA54\uC11C\uB4DC\r\n getRouteParams: () => this.queryManager?.getRouteParams() || {},\r\n getRouteParam: (key, defaultValue) => this.queryManager?.getRouteParam(key, defaultValue),\r\n \r\n currentRoute: this.currentHash,\r\n currentQuery: this.queryManager?.getQueryParams() || {}\r\n };\r\n\r\n // \uBAA8\uBC14\uC77C \uBA54\uB274 \uC804\uC5ED \uD568\uC218 \uCD94\uAC00\r\n\r\n newVueApp.mount(`#${newPageContainer.id}`);\r\n\r\n // requestAnimationFrame\uC73C\uB85C \uC131\uB2A5 \uAC1C\uC120\r\n requestAnimationFrame(() => {\r\n this.cleanupPreviousPages();\r\n this.transitionInProgress = false;\r\n });\r\n\r\n // \uC774\uC804 \uC571 \uC815\uB9AC \uC900\uBE44\r\n if (this.currentVueApp) {\r\n this.previousVueApp = this.currentVueApp;\r\n }\r\n \r\n this.currentVueApp = newVueApp;\r\n }\r\n\r\n cleanupPreviousPages() {\r\n const appElement = document.getElementById('app');\r\n if (!appElement) return;\r\n\r\n // \uBC30\uCE58 DOM \uC870\uC791\uC73C\uB85C \uC131\uB2A5 \uAC1C\uC120\r\n const fragment = document.createDocumentFragment();\r\n const exitingContainers = appElement.querySelectorAll('.page-container.page-exiting');\r\n \r\n // \uD55C\uBC88\uC5D0 \uC81C\uAC70\r\n exitingContainers.forEach(container => container.remove());\r\n\r\n // \uC774\uC804 Vue \uC571 \uC815\uB9AC\r\n if (this.previousVueApp) {\r\n try {\r\n this.previousVueApp.unmount();\r\n } catch (error) {\r\n // \uBB34\uC2DC (\uC774\uBBF8 \uC5B8\uB9C8\uC6B4\uD2B8\uB41C \uACBD\uC6B0)\r\n }\r\n this.previousVueApp = null;\r\n }\r\n\r\n // \uB85C\uB529 \uC5D8\uB9AC\uBA3C\uD2B8 \uC81C\uAC70\r\n \r\n appElement.querySelector('.loading')?.remove();\r\n }\r\n\r\n applyStyle(css, routeName) {\r\n // \uAE30\uC874 \uC2A4\uD0C0\uC77C \uC81C\uAC70\r\n const existing = document.querySelector(`style[data-route=\"${routeName}\"]`);\r\n if (existing) existing.remove();\r\n\r\n if (css) {\r\n const style = document.createElement('style');\r\n style.textContent = css;\r\n style.setAttribute('data-route', routeName);\r\n document.head.appendChild(style);\r\n }\r\n }\r\n\r\n\r\n navigateTo(routeName, params = null) {\r\n // If routeName is an object, treat it as {route, params}\r\n if (typeof routeName === 'object') {\r\n params = routeName.params || null;\r\n routeName = routeName.route;\r\n }\r\n \r\n // Clear current query params if navigating to a different route\r\n if (routeName !== this.currentHash && this.queryManager) {\r\n this.queryManager.clearQueryParams();\r\n }\r\n \r\n // Set route parameters\r\n if (this.queryManager) {\r\n this.queryManager.setCurrentRouteParams(params);\r\n }\r\n \r\n // Update URL with new route and params\r\n this.updateURL(routeName, params);\r\n }\r\n\r\n getCurrentRoute() {\r\n return this.currentHash;\r\n }\r\n\r\n\r\n updateURL(route, params = null) {\r\n const queryParams = params || this.queryManager?.getQueryParams() || {};\r\n const queryString = this.queryManager?.buildQueryString(queryParams) || '';\r\n \r\n // URL \uBE4C\uB4DC \uCD5C\uC801\uD654\r\n const buildURL = (route, queryString, isHash = true) => {\r\n const base = route === 'home' ? '/' : `/${route}`;\r\n const url = queryString ? `${base}?${queryString}` : base;\r\n return isHash ? `#${url}` : url;\r\n };\r\n \r\n if (this.config.mode === 'hash') {\r\n const newHash = buildURL(route, queryString);\r\n \r\n // \uB3D9\uC77C\uD55C URL\uC774\uBA74 \uC5C5\uB370\uC774\uD2B8\uD558\uC9C0 \uC54A\uC74C (\uC131\uB2A5 \uCD5C\uC801\uD654)\r\n if (window.location.hash !== newHash) {\r\n window.location.hash = newHash;\r\n }\r\n } else {\r\n const newPath = buildURL(route, queryString, false);\r\n const isSameRoute = window.location.pathname === (route === 'home' ? '/' : `/${route}`);\r\n \r\n if (isSameRoute) {\r\n window.history.replaceState({}, '', newPath);\r\n } else {\r\n window.history.pushState({}, '', newPath);\r\n }\r\n this.handleRouteChange();\r\n }\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD130 \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70\r\n window.removeEventListener(\r\n this.config.mode === 'hash' ? 'hashchange' : 'popstate',\r\n this._boundHandleRouteChange\r\n );\r\n \r\n // \uD604\uC7AC Vue \uC571 \uC5B8\uB9C8\uC6B4\uD2B8\r\n if (this.currentVueApp) {\r\n this.currentVueApp.unmount();\r\n this.currentVueApp = null;\r\n }\r\n \r\n // \uC774\uC804 Vue \uC571 \uC5B8\uB9C8\uC6B4\uD2B8\r\n if (this.previousVueApp) {\r\n this.previousVueApp.unmount();\r\n this.previousVueApp = null;\r\n }\r\n \r\n // \uB9E4\uB2C8\uC800 \uC815\uB9AC\r\n Object.values(this).forEach(manager => {\r\n if (manager && typeof manager.destroy === 'function') {\r\n manager.destroy();\r\n }\r\n });\r\n \r\n // \uCE90\uC2DC \uD074\uB9AC\uC5B4\r\n this.cacheManager?.clearAll();\r\n \r\n // DOM \uC815\uB9AC\r\n const appElement = document.getElementById('app');\r\n if (appElement) {\r\n appElement.innerHTML = '';\r\n }\r\n \r\n this.log('info', 'Router destroyed');\r\n }\r\n}\r\n// \uC804\uC5ED \uB77C\uC6B0\uD130\uB294 index.html\uC5D0\uC11C \uD658\uACBD\uC124\uC815\uACFC \uD568\uAED8 \uC0DD\uC131\uB428"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["I18nManager", "router", "options", "error", "cachedLang", "lang", "language", "oldLanguage", "loadPromise", "messages", "cachedData", "i18nPath", "response", "cacheKey", "cachedItem", "data", "timestamp", "version", "now", "maxAge", "cacheItem", "key", "params", "message", "fallbackMessages", "fallbackMessage", "obj", "path", "current", "match", "count", "pluralKey", "event", "callback", "index", "date", "locale", "number", "level", "args", "cacheKeys", "info", "AuthManager", "router", "options", "level", "args", "routeName", "isAuthenticated", "error", "token", "payload", "authCookie", "prefix", "primaryCookie", "cookieName", "cookieValue", "name", "parts", "storage", "cookieOptions", "skipValidation", "secure", "sameSite", "path", "domain", "cookieString", "expireDate", "targetRoute", "redirectRoute", "eventType", "data", "event", "listener", "listeners", "index", "CacheManager", "router", "options", "level", "args", "key", "value", "now", "oldestKey", "existingIndex", "timestamp", "index", "pattern", "keysToDelete", "routeName", "patterns", "totalInvalidated", "componentPatterns", "totalCleared", "size", "expiredKeys", "estimatedBytes", "ratio", "categories", "interval", "QueryManager", "router", "options", "level", "args", "value", "sanitized", "sqlPatterns", "pattern", "key", "dangerousPatterns", "item", "queryString", "params", "pairs", "pair", "rawKey", "rawValue", "sanitizedValue", "arrayKey", "error", "paramCount", "limitedParams", "count", "newParams", "oldKeys", "newKeys", "defaultValue", "replace", "currentParams", "sanitizedParams", "keys", "keysToRemove", "route", "RouteLoader", "router", "options", "routeName", "script", "importPath", "error", "templatePath", "response", "template", "stylePath", "style", "layoutName", "layoutPath", "layout", "result", "cacheKey", "cached", "isProduction", "loadedComponents", "component", "route", "params", "key", "defaultValue", "target", "token", "storage", "name", "apiName", "data", "url", "dataURLs", "promises", "results", "successfulResults", "errors", "success", "form", "boundHandler", "e", "event", "action", "method", "successHandler", "errorHandler", "loadingHandler", "redirectTo", "formData", "actionTemplate", "processedAction", "paramMatches", "match", "paramName", "paramValue", "hasFile", "el", "headers", "body", "isValid", "input", "validationFunction", "value", "str", "word", "dataURL", "queryString", "fullURL", "level", "args", "ErrorHandler", "router", "options", "routeName", "error", "errorCode", "errorMessage", "fallbackError", "component", "errorComponent", "appElement", "fallbackHTML", "errorReport", "level", "args", "currentLevelValue", "messageLevelValue", "prefix", "timestamp", "ComponentLoader", "router", "options", "level", "args", "componentName", "loadPromise", "error", "componentPath", "component", "componentsPath", "componentsModule", "componentNames", "components", "name", "loadError", "ViewLogicRouter", "options", "currentOrigin", "config", "level", "args", "CacheManager", "RouteLoader", "QueryManager", "ErrorHandler", "I18nManager", "AuthManager", "ComponentLoader", "componentError", "error", "isHashMode", "initRoute", "route", "queryParams", "hashPath", "pathPart", "queryPart", "routeName", "component", "vueComponent", "appElement", "newPageContainer", "container", "createApp", "newVueApp", "params", "key", "defaultValue", "replace", "keys", "fragment", "css", "existing", "style", "queryString", "buildURL", "isHash", "base", "url", "newHash", "newPath", "manager"]
|
|
4
|
+
"sourcesContent": ["/**\r\n * ViewLogic Internationalization System\r\n * \uB2E4\uAD6D\uC5B4 \uC9C0\uC6D0 \uC2DC\uC2A4\uD15C\r\n */\r\nexport class I18nManager {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n enabled: options.useI18n !== undefined ? options.useI18n : true,\r\n defaultLanguage: options.defaultLanguage || 'ko',\r\n fallbackLanguage: options.defaultLanguage || 'ko',\r\n cacheKey: options.cacheKey || 'viewlogic_lang',\r\n dataCacheKey: options.dataCacheKey || 'viewlogic_i18n_data',\r\n cacheVersion: options.cacheVersion || '1.0.0',\r\n enableDataCache: options.enableDataCache !== false,\r\n debug: options.debug || false\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870 (\uD544\uC694\uC2DC \uC5B8\uC5B4 \uBCC0\uACBD \uC2DC \uB77C\uC6B0\uD130 \uC0C1\uD0DC \uC5C5\uB370\uC774\uD2B8)\r\n this.router = router;\r\n \r\n this.messages = new Map();\r\n this.currentLanguage = this.config.defaultLanguage;\r\n this.isLoading = false;\r\n this.loadPromises = new Map();\r\n \r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108\uB4E4\r\n this.listeners = {\r\n languageChanged: []\r\n };\r\n \r\n // \uBE44\uB3D9\uAE30 \uCD08\uAE30\uD654 \uC2DC\uC791 (constructor \uB0B4\uC5D0\uC11C\uB294 await \uBD88\uAC00)\r\n this.initPromise = this.init();\r\n }\r\n\r\n async init() {\r\n // i18n\uC774 \uBE44\uD65C\uC131\uD654\uB41C \uACBD\uC6B0 \uCD08\uAE30\uD654\uD558\uC9C0 \uC54A\uC74C\r\n if (!this.config.enabled) {\r\n this.log('info', 'I18n system disabled');\r\n return;\r\n }\r\n \r\n // \uCE90\uC2DC\uC5D0\uC11C \uC5B8\uC5B4 \uC124\uC815 \uB85C\uB4DC\r\n this.loadLanguageFromCache();\r\n \r\n // \uAC1C\uBC1C \uBAA8\uB4DC\uC5D0\uC11C\uB294 \uCE90\uC2DC \uBE44\uD65C\uC131\uD654\r\n if (this.config.debug) {\r\n this.config.enableDataCache = false;\r\n this.log('debug', 'Data cache disabled in debug mode');\r\n }\r\n \r\n // \uCD08\uAE30 \uC5B8\uC5B4 \uD30C\uC77C \uC790\uB3D9 \uB85C\uB4DC (\uC544\uC9C1 \uB85C\uB4DC\uB418\uC9C0 \uC54A\uC740 \uACBD\uC6B0\uC5D0\uB9CC)\r\n if (!this.messages.has(this.currentLanguage)) {\r\n try {\r\n await this.loadMessages(this.currentLanguage);\r\n } catch (error) {\r\n this.log('error', 'Failed to load initial language file:', error);\r\n // \uD3F4\uBC31\uC73C\uB85C \uBE48 \uBA54\uC2DC\uC9C0 \uAC1D\uCCB4 \uC124\uC815\uD558\uC5EC \uC2DC\uC2A4\uD15C\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D\r\n this.messages.set(this.currentLanguage, {});\r\n this.log('info', 'Using empty message object as fallback');\r\n }\r\n } else {\r\n this.log('debug', 'Language messages already loaded:', this.currentLanguage);\r\n }\r\n }\r\n\r\n /**\r\n * \uCE90\uC2DC\uC5D0\uC11C \uC5B8\uC5B4 \uC124\uC815 \uB85C\uB4DC\r\n */\r\n loadLanguageFromCache() {\r\n try {\r\n const cachedLang = localStorage.getItem(this.config.cacheKey);\r\n if (cachedLang && this.isValidLanguage(cachedLang)) {\r\n this.currentLanguage = cachedLang;\r\n this.log('debug', 'Language loaded from cache:', cachedLang);\r\n }\r\n } catch (error) {\r\n this.log('warn', 'Failed to load language from cache:', error);\r\n }\r\n }\r\n\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uC720\uD6A8\uC131 \uAC80\uC0AC\r\n */\r\n isValidLanguage(lang) {\r\n return typeof lang === 'string' && /^[a-z]{2}$/.test(lang);\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uC5B8\uC5B4 \uBC18\uD658\r\n */\r\n getCurrentLanguage() {\r\n return this.currentLanguage;\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uBCC0\uACBD\r\n */\r\n async setLanguage(language) {\r\n if (!this.isValidLanguage(language)) {\r\n this.log('warn', 'Invalid language code:', language);\r\n return false;\r\n }\r\n\r\n if (this.currentLanguage === language) {\r\n this.log('debug', 'Language already set to:', language);\r\n return true;\r\n }\r\n\r\n const oldLanguage = this.currentLanguage;\r\n this.currentLanguage = language;\r\n\r\n try {\r\n // \uC5B8\uC5B4 \uD30C\uC77C \uB85C\uB4DC (\uC2E4\uD328\uD574\uB3C4 \uBE48 \uAC1D\uCCB4\uB77C\uB3C4 \uBC1B\uC744 \uC218 \uC788\uB3C4\uB85D)\r\n await this.loadMessages(language);\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n this.saveLanguageToCache(language);\r\n \r\n // \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n this.emit('languageChanged', {\r\n from: oldLanguage,\r\n to: language,\r\n messages: this.messages.get(language)\r\n });\r\n \r\n this.log('info', 'Language changed successfully', { from: oldLanguage, to: language });\r\n return true;\r\n } catch (error) {\r\n // \uC2E4\uD328\uD574\uB3C4 \uC5B8\uC5B4\uB294 \uBCC0\uACBD\uD558\uB418, \uBE48 \uBA54\uC2DC\uC9C0 \uAC1D\uCCB4 \uC0AC\uC6A9\r\n this.log('error', 'Failed to load messages for language change, using empty messages:', error);\r\n this.messages.set(language, {});\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n this.saveLanguageToCache(language);\r\n \r\n // \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n this.emit('languageChanged', {\r\n from: oldLanguage,\r\n to: language,\r\n messages: {},\r\n error: true\r\n });\r\n \r\n this.log('warn', 'Language changed with empty messages', { from: oldLanguage, to: language });\r\n return true; // true \uBC18\uD658\uD558\uC5EC \uB77C\uC6B0\uD130\uAC00 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D\r\n }\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4\uB97C \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n */\r\n saveLanguageToCache(language) {\r\n try {\r\n localStorage.setItem(this.config.cacheKey, language);\r\n this.log('debug', 'Language saved to cache:', language);\r\n } catch (error) {\r\n this.log('warn', 'Failed to save language to cache:', error);\r\n }\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uBA54\uC2DC\uC9C0 \uD30C\uC77C \uB85C\uB4DC\r\n */\r\n async loadMessages(language) {\r\n // \uC774\uBBF8 \uB85C\uB4DC\uB41C \uACBD\uC6B0\r\n if (this.messages.has(language)) {\r\n this.log('debug', 'Messages already loaded for:', language);\r\n return this.messages.get(language);\r\n }\r\n\r\n // \uC774\uBBF8 \uB85C\uB529 \uC911\uC778 \uACBD\uC6B0\r\n if (this.loadPromises.has(language)) {\r\n this.log('debug', 'Messages loading in progress for:', language);\r\n return await this.loadPromises.get(language);\r\n }\r\n\r\n const loadPromise = this._loadMessagesFromFile(language);\r\n this.loadPromises.set(language, loadPromise);\r\n\r\n try {\r\n const messages = await loadPromise;\r\n this.messages.set(language, messages);\r\n this.loadPromises.delete(language);\r\n this.log('debug', 'Messages loaded successfully for:', language);\r\n return messages;\r\n } catch (error) {\r\n this.loadPromises.delete(language);\r\n // \uC2E4\uD328\uD574\uB3C4 \uBE48 \uAC1D\uCCB4 \uC124\uC815\uD558\uC5EC \uC2DC\uC2A4\uD15C\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D\r\n this.log('error', 'Failed to load messages, using empty fallback for:', language, error);\r\n const emptyMessages = {};\r\n this.messages.set(language, emptyMessages);\r\n return emptyMessages;\r\n }\r\n }\r\n\r\n /**\r\n * \uD30C\uC77C\uC5D0\uC11C \uBA54\uC2DC\uC9C0 \uB85C\uB4DC (\uCE90\uC2F1 \uC9C0\uC6D0)\r\n */\r\n async _loadMessagesFromFile(language) {\r\n // \uCE90\uC2DC\uC5D0\uC11C \uBA3C\uC800 \uC2DC\uB3C4\r\n if (this.config.enableDataCache) {\r\n const cachedData = this.getDataFromCache(language);\r\n if (cachedData) {\r\n this.log('debug', 'Messages loaded from cache:', language);\r\n return cachedData;\r\n }\r\n }\r\n \r\n try {\r\n // JSON \uD30C\uC77C\uB85C \uBCC0\uACBD - config\uC758 i18nPath \uC0AC\uC6A9\r\n const i18nPath = `${this.router.config.i18nPath}/${language}.json`;\r\n const response = await fetch(i18nPath);\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n const messages = await response.json();\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n if (this.config.enableDataCache) {\r\n this.saveDataToCache(language, messages);\r\n }\r\n \r\n return messages;\r\n } catch (error) {\r\n this.log('error', 'Failed to load messages file for:', language, error);\r\n \r\n // \uD3F4\uBC31 \uC5B8\uC5B4 \uC2DC\uB3C4\r\n if (language !== this.config.fallbackLanguage) {\r\n this.log('info', 'Trying fallback language:', this.config.fallbackLanguage);\r\n try {\r\n return await this._loadMessagesFromFile(this.config.fallbackLanguage);\r\n } catch (fallbackError) {\r\n this.log('error', 'Fallback language also failed:', fallbackError);\r\n // \uD3F4\uBC31\uB3C4 \uC2E4\uD328\uD558\uBA74 \uBE48 \uAC1D\uCCB4 \uBC18\uD658\uD558\uC5EC \uC2DC\uC2A4\uD15C\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D\r\n return {};\r\n }\r\n }\r\n \r\n // \uB9C8\uC9C0\uB9C9 \uD3F4\uBC31: \uBE48 \uAC1D\uCCB4 \uBC18\uD658\r\n this.log('warn', `No messages available for language: ${language}, using empty fallback`);\r\n return {};\r\n }\r\n }\r\n \r\n /**\r\n * \uC5B8\uC5B4 \uB370\uC774\uD130\uB97C \uCE90\uC2DC\uC5D0\uC11C \uAC00\uC838\uC624\uAE30\r\n */\r\n getDataFromCache(language) {\r\n try {\r\n const cacheKey = `${this.config.dataCacheKey}_${language}_${this.config.cacheVersion}`;\r\n const cachedItem = localStorage.getItem(cacheKey);\r\n \r\n if (cachedItem) {\r\n const { data, timestamp, version } = JSON.parse(cachedItem);\r\n \r\n // \uBC84\uC804 \uD655\uC778\r\n if (version !== this.config.cacheVersion) {\r\n this.log('debug', 'Cache version mismatch, clearing:', language);\r\n localStorage.removeItem(cacheKey);\r\n return null;\r\n }\r\n \r\n // TTL \uD655\uC778 (24\uC2DC\uAC04)\r\n const now = Date.now();\r\n const maxAge = 24 * 60 * 60 * 1000; // 24\uC2DC\uAC04\r\n \r\n if (now - timestamp > maxAge) {\r\n this.log('debug', 'Cache expired, removing:', language);\r\n localStorage.removeItem(cacheKey);\r\n return null;\r\n }\r\n \r\n return data;\r\n }\r\n } catch (error) {\r\n this.log('warn', 'Failed to read from cache:', error);\r\n }\r\n \r\n return null;\r\n }\r\n \r\n /**\r\n * \uC5B8\uC5B4 \uB370\uC774\uD130\uB97C \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n */\r\n saveDataToCache(language, data) {\r\n try {\r\n const cacheKey = `${this.config.dataCacheKey}_${language}_${this.config.cacheVersion}`;\r\n const cacheItem = {\r\n data,\r\n timestamp: Date.now(),\r\n version: this.config.cacheVersion\r\n };\r\n \r\n localStorage.setItem(cacheKey, JSON.stringify(cacheItem));\r\n this.log('debug', 'Data saved to cache:', language);\r\n } catch (error) {\r\n this.log('warn', 'Failed to save to cache:', error);\r\n }\r\n }\r\n\r\n /**\r\n * \uBA54\uC2DC\uC9C0 \uBC88\uC5ED\r\n */\r\n t(key, params = {}) {\r\n // i18n\uC774 \uBE44\uD65C\uC131\uD654\uB41C \uACBD\uC6B0 \uD0A4 \uC790\uCCB4\uB97C \uBC18\uD658\r\n if (!this.config.enabled) {\r\n return key;\r\n }\r\n \r\n const messages = this.messages.get(this.currentLanguage);\r\n if (!messages) {\r\n this.log('warn', 'No messages loaded for current language:', this.currentLanguage);\r\n return key;\r\n }\r\n\r\n const message = this.getNestedValue(messages, key);\r\n if (message === undefined) {\r\n this.log('warn', 'Translation not found for key:', key);\r\n \r\n // \uD3F4\uBC31 \uC5B8\uC5B4\uC5D0\uC11C \uCC3E\uAE30\r\n const fallbackMessages = this.messages.get(this.config.fallbackLanguage);\r\n if (fallbackMessages && this.currentLanguage !== this.config.fallbackLanguage) {\r\n const fallbackMessage = this.getNestedValue(fallbackMessages, key);\r\n if (fallbackMessage !== undefined) {\r\n return this.interpolate(fallbackMessage, params);\r\n }\r\n }\r\n \r\n return key;\r\n }\r\n\r\n return this.interpolate(message, params);\r\n }\r\n\r\n /**\r\n * \uC911\uCCA9\uB41C \uAC1D\uCCB4\uC5D0\uC11C \uAC12 \uAC00\uC838\uC624\uAE30\r\n */\r\n getNestedValue(obj, path) {\r\n return path.split('.').reduce((current, key) => {\r\n return current && current[key] !== undefined ? current[key] : undefined;\r\n }, obj);\r\n }\r\n\r\n /**\r\n * \uBB38\uC790\uC5F4 \uBCF4\uAC04 \uCC98\uB9AC\r\n */\r\n interpolate(message, params) {\r\n if (typeof message !== 'string') {\r\n return message;\r\n }\r\n\r\n return message.replace(/\\{(\\w+)\\}/g, (match, key) => {\r\n return params.hasOwnProperty(key) ? params[key] : match;\r\n });\r\n }\r\n\r\n /**\r\n * \uBCF5\uC218\uD615 \uCC98\uB9AC\r\n */\r\n plural(key, count, params = {}) {\r\n const pluralKey = count === 1 ? `${key}.singular` : `${key}.plural`;\r\n return this.t(pluralKey, { ...params, count });\r\n }\r\n\r\n /**\r\n * \uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uC5B8\uC5B4 \uBAA9\uB85D\r\n */\r\n getAvailableLanguages() {\r\n return ['ko', 'en']; // \uCD94\uD6C4 \uB3D9\uC801\uC73C\uB85C \uB85C\uB4DC\uD558\uB3C4\uB85D \uBCC0\uACBD \uAC00\uB2A5\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uBCC0\uACBD \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uB4F1\uB85D\r\n */\r\n on(event, callback) {\r\n if (this.listeners[event]) {\r\n this.listeners[event].push(callback);\r\n }\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4 \uBCC0\uACBD \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70\r\n */\r\n off(event, callback) {\r\n if (this.listeners[event]) {\r\n const index = this.listeners[event].indexOf(callback);\r\n if (index > -1) {\r\n this.listeners[event].splice(index, 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n */\r\n emit(event, data) {\r\n if (this.listeners[event]) {\r\n this.listeners[event].forEach(callback => {\r\n try {\r\n callback(data);\r\n } catch (error) {\r\n this.log('error', 'Error in event listener:', error);\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uC5B8\uC5B4\uC758 \uBAA8\uB4E0 \uBA54\uC2DC\uC9C0 \uBC18\uD658\r\n */\r\n getMessages() {\r\n return this.messages.get(this.currentLanguage) || {};\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4\uBCC4 \uB0A0\uC9DC \uD3EC\uB9F7\uD305\r\n */\r\n formatDate(date, options = {}) {\r\n const locale = this.currentLanguage === 'ko' ? 'ko-KR' : 'en-US';\r\n return new Intl.DateTimeFormat(locale, options).format(new Date(date));\r\n }\r\n\r\n /**\r\n * \uC5B8\uC5B4\uBCC4 \uC22B\uC790 \uD3EC\uB9F7\uD305\r\n */\r\n formatNumber(number, options = {}) {\r\n const locale = this.currentLanguage === 'ko' ? 'ko-KR' : 'en-US';\r\n return new Intl.NumberFormat(locale, options).format(number);\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'I18nManager', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * i18n \uD65C\uC131\uD654 \uC5EC\uBD80 \uD655\uC778\r\n */\r\n isEnabled() {\r\n return this.config.enabled;\r\n }\r\n \r\n /**\r\n * \uCD08\uAE30 \uB85C\uB529\uC774 \uC644\uB8CC\uB418\uC5C8\uB294\uC9C0 \uD655\uC778\r\n */\r\n async isReady() {\r\n if (!this.config.enabled) {\r\n return true;\r\n }\r\n \r\n try {\r\n await this.initPromise;\r\n return true;\r\n } catch (error) {\r\n this.log('error', 'I18n initialization failed:', error);\r\n // \uC2E4\uD328\uD574\uB3C4 \uB77C\uC6B0\uD130\uAC00 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D true \uBC18\uD658\r\n this.log('info', 'I18n system ready with fallback behavior');\r\n return true;\r\n }\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC \uCD08\uAE30\uD654 (\uBC84\uC804 \uBCC0\uACBD \uC2DC \uC0AC\uC6A9)\r\n */\r\n clearCache() {\r\n try {\r\n const keys = Object.keys(localStorage);\r\n const cacheKeys = keys.filter(key => key.startsWith(this.config.dataCacheKey));\r\n \r\n cacheKeys.forEach(key => {\r\n localStorage.removeItem(key);\r\n });\r\n \r\n this.log('debug', 'Cache cleared, removed', cacheKeys.length, 'items');\r\n } catch (error) {\r\n this.log('warn', 'Failed to clear cache:', error);\r\n }\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC \uC0C1\uD0DC \uD655\uC778\r\n */\r\n getCacheInfo() {\r\n const info = {\r\n enabled: this.config.enableDataCache,\r\n version: this.config.cacheVersion,\r\n languages: {}\r\n };\r\n \r\n try {\r\n const keys = Object.keys(localStorage);\r\n const cacheKeys = keys.filter(key => key.startsWith(this.config.dataCacheKey));\r\n \r\n cacheKeys.forEach(key => {\r\n const match = key.match(new RegExp(`${this.config.dataCacheKey}_(\\w+)_(.+)`));\r\n if (match) {\r\n const [, language, version] = match;\r\n const cachedItem = JSON.parse(localStorage.getItem(key));\r\n \r\n info.languages[language] = {\r\n version,\r\n timestamp: cachedItem.timestamp,\r\n age: Date.now() - cachedItem.timestamp\r\n };\r\n }\r\n });\r\n } catch (error) {\r\n this.log('warn', 'Failed to get cache info:', error);\r\n }\r\n \r\n return info;\r\n }\r\n \r\n /**\r\n * \uC2DC\uC2A4\uD15C \uCD08\uAE30\uD654 (\uD604\uC7AC \uC5B8\uC5B4\uC758 \uBA54\uC2DC\uC9C0 \uB85C\uB4DC)\r\n */\r\n async initialize() {\r\n if (!this.config.enabled) {\r\n this.log('info', 'I18n system is disabled, skipping initialization');\r\n return true;\r\n }\r\n \r\n try {\r\n // \uCD08\uAE30 \uC124\uC815\uC774 \uC644\uB8CC\uB420 \uB54C\uAE4C\uC9C0 \uB300\uAE30\r\n await this.initPromise;\r\n this.log('info', 'I18n system fully initialized');\r\n return true;\r\n } catch (error) {\r\n this.log('error', 'Failed to initialize I18n system:', error);\r\n // \uC2E4\uD328\uD574\uB3C4 \uC2DC\uC2A4\uD15C\uC740 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D true \uBC18\uD658\r\n this.log('info', 'I18n system will continue with fallback behavior');\r\n return true;\r\n }\r\n }\r\n}", "/**\r\n * ViewLogic Authentication Management System\r\n * \uC778\uC99D \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class AuthManager {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n enabled: options.authEnabled || false,\r\n loginRoute: options.loginRoute || 'login',\r\n protectedRoutes: options.protectedRoutes || [],\r\n protectedPrefixes: options.protectedPrefixes || [],\r\n publicRoutes: options.publicRoutes || ['login', 'register', 'home'],\r\n checkAuthFunction: options.checkAuthFunction || null,\r\n redirectAfterLogin: options.redirectAfterLogin || 'home',\r\n // \uCFE0\uD0A4/\uC2A4\uD1A0\uB9AC\uC9C0 \uC124\uC815\r\n authCookieName: options.authCookieName || 'authToken',\r\n authFallbackCookieNames: options.authFallbackCookieNames || ['accessToken', 'token', 'jwt'],\r\n authStorage: options.authStorage || 'cookie',\r\n authCookieOptions: options.authCookieOptions || {},\r\n authSkipValidation: options.authSkipValidation || false,\r\n debug: options.debug || false\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870 (\uD544\uC218 \uC758\uC874\uC131)\r\n this.router = router;\r\n \r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108\uB4E4\r\n this.eventListeners = new Map();\r\n \r\n this.log('info', 'AuthManager initialized', { enabled: this.config.enabled });\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'AuthManager', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD2B8 \uC778\uC99D \uD655\uC778\r\n */\r\n async checkAuthentication(routeName) {\r\n // \uC778\uC99D \uC2DC\uC2A4\uD15C\uC774 \uBE44\uD65C\uC131\uD654\uB41C \uACBD\uC6B0\r\n if (!this.config.enabled) {\r\n return { allowed: true, reason: 'auth_disabled' };\r\n }\r\n\r\n this.log('debug', `\uD83D\uDD10 Checking authentication for route: ${routeName}`);\r\n\r\n // \uACF5\uAC1C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n if (this.isPublicRoute(routeName)) {\r\n return { allowed: true, reason: 'public_route' };\r\n }\r\n\r\n // \uBCF4\uD638\uB41C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n const isProtected = this.isProtectedRoute(routeName);\r\n if (!isProtected) {\r\n return { allowed: true, reason: 'not_protected' };\r\n }\r\n\r\n // \uC0AC\uC6A9\uC790 \uC815\uC758 \uC778\uC99D \uCCB4\uD06C \uD568\uC218\uAC00 \uC788\uB294 \uACBD\uC6B0\r\n if (typeof this.config.checkAuthFunction === 'function') {\r\n try {\r\n const isAuthenticated = await this.config.checkAuthFunction(routeName);\r\n return {\r\n allowed: isAuthenticated, \r\n reason: isAuthenticated ? 'custom_auth_success' : 'custom_auth_failed',\r\n routeName\r\n };\r\n } catch (error) {\r\n this.log('error', 'Custom auth function failed:', error);\r\n return { allowed: false, reason: 'custom_auth_error', error };\r\n }\r\n }\r\n\r\n // \uAE30\uBCF8 \uC778\uC99D \uD655\uC778\r\n const isAuthenticated = this.isUserAuthenticated();\r\n return {\r\n allowed: isAuthenticated, \r\n reason: isAuthenticated ? 'authenticated' : 'not_authenticated',\r\n routeName\r\n };\r\n }\r\n\r\n /**\r\n * \uC0AC\uC6A9\uC790 \uC778\uC99D \uC0C1\uD0DC \uD655\uC778\r\n */\r\n isUserAuthenticated() {\r\n this.log('debug', '\uD83D\uDD0D Checking user authentication status');\r\n\r\n // 1. localStorage \uD655\uC778\r\n const token = localStorage.getItem('authToken') || localStorage.getItem('accessToken');\r\n if (token) {\r\n try {\r\n if (token.includes('.')) {\r\n const payload = JSON.parse(atob(token.split('.')[1]));\r\n if (payload.exp && Date.now() >= payload.exp * 1000) {\r\n this.log('debug', 'localStorage token expired, removing...');\r\n localStorage.removeItem('authToken');\r\n localStorage.removeItem('accessToken');\r\n return false;\r\n }\r\n }\r\n this.log('debug', '\u2705 Valid token found in localStorage');\r\n return true;\r\n } catch (error) {\r\n this.log('warn', 'Invalid token in localStorage:', error);\r\n }\r\n }\r\n\r\n // 2. sessionStorage \uD655\uC778\r\n const sessionToken = sessionStorage.getItem('authToken') || sessionStorage.getItem('accessToken');\r\n if (sessionToken) {\r\n this.log('debug', '\u2705 Token found in sessionStorage');\r\n return true;\r\n }\r\n\r\n // 3. \uCFE0\uD0A4 \uD655\uC778\r\n const authCookie = this.getAuthCookie();\r\n if (authCookie) {\r\n try {\r\n if (authCookie.includes('.')) {\r\n const payload = JSON.parse(atob(authCookie.split('.')[1]));\r\n if (payload.exp && Date.now() >= payload.exp * 1000) {\r\n this.log('debug', 'Cookie token expired, removing...');\r\n this.removeAuthCookie();\r\n return false;\r\n }\r\n }\r\n this.log('debug', '\u2705 Valid token found in cookies');\r\n return true;\r\n } catch (error) {\r\n this.log('warn', 'Cookie token validation failed:', error);\r\n }\r\n }\r\n\r\n // 4. \uC804\uC5ED \uBCC0\uC218 \uD655\uC778 (\uB808\uAC70\uC2DC \uC9C0\uC6D0)\r\n if (window.user || window.isAuthenticated) {\r\n this.log('debug', '\u2705 Global authentication variable found');\r\n return true;\r\n }\r\n\r\n this.log('debug', '\u274C No valid authentication found');\r\n return false;\r\n }\r\n\r\n /**\r\n * \uACF5\uAC1C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n */\r\n isPublicRoute(routeName) {\r\n return this.config.publicRoutes.includes(routeName);\r\n }\r\n\r\n /**\r\n * \uBCF4\uD638\uB41C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n */\r\n isProtectedRoute(routeName) {\r\n // \uD2B9\uC815 \uB77C\uC6B0\uD2B8\uAC00 \uBCF4\uD638\uB41C \uB77C\uC6B0\uD2B8 \uBAA9\uB85D\uC5D0 \uC788\uB294\uC9C0 \uD655\uC778\r\n if (this.config.protectedRoutes.includes(routeName)) {\r\n return true;\r\n }\r\n\r\n // prefix\uB85C \uBCF4\uD638\uB41C \uB77C\uC6B0\uD2B8\uC778\uC9C0 \uD655\uC778\r\n for (const prefix of this.config.protectedPrefixes) {\r\n if (routeName.startsWith(prefix)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uCFE0\uD0A4 \uAC00\uC838\uC624\uAE30\r\n */\r\n getAuthCookie() {\r\n // \uC8FC \uCFE0\uD0A4 \uC774\uB984 \uD655\uC778\r\n const primaryCookie = this.getCookieValue(this.config.authCookieName);\r\n if (primaryCookie) {\r\n return primaryCookie;\r\n }\r\n\r\n // \uB300\uCCB4 \uCFE0\uD0A4 \uC774\uB984\uB4E4 \uD655\uC778\r\n for (const cookieName of this.config.authFallbackCookieNames) {\r\n const cookieValue = this.getCookieValue(cookieName);\r\n if (cookieValue) {\r\n this.log('debug', `Found auth token in fallback cookie: ${cookieName}`);\r\n return cookieValue;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * \uCFE0\uD0A4 \uAC12 \uAC00\uC838\uC624\uAE30\r\n */\r\n getCookieValue(name) {\r\n const value = `; ${document.cookie}`;\r\n const parts = value.split(`; ${name}=`);\r\n if (parts.length === 2) {\r\n return decodeURIComponent(parts.pop().split(';').shift());\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uCFE0\uD0A4 \uC81C\uAC70\r\n */\r\n removeAuthCookie() {\r\n const cookiesToRemove = [this.config.authCookieName, ...this.config.authFallbackCookieNames];\r\n \r\n cookiesToRemove.forEach(cookieName => {\r\n // \uD604\uC7AC \uACBD\uB85C\uC640 \uB8E8\uD2B8 \uACBD\uB85C\uC5D0\uC11C \uBAA8\uB450 \uC81C\uAC70\r\n document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;\r\n document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${window.location.pathname};`;\r\n });\r\n \r\n this.log('debug', 'Auth cookies removed');\r\n }\r\n\r\n /**\r\n * \uC561\uC138\uC2A4 \uD1A0\uD070 \uAC00\uC838\uC624\uAE30\r\n */\r\n getAccessToken() {\r\n // localStorage \uD655\uC778\r\n let token = localStorage.getItem('authToken') || localStorage.getItem('accessToken');\r\n if (token) return token;\r\n\r\n // sessionStorage \uD655\uC778\r\n token = sessionStorage.getItem('authToken') || sessionStorage.getItem('accessToken');\r\n if (token) return token;\r\n\r\n // \uCFE0\uD0A4 \uD655\uC778\r\n token = this.getAuthCookie();\r\n if (token) return token;\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * \uC561\uC138\uC2A4 \uD1A0\uD070 \uC124\uC815\r\n */\r\n setAccessToken(token, options = {}) {\r\n if (!token) {\r\n this.log('warn', 'Empty token provided');\r\n return false;\r\n }\r\n\r\n const {\r\n storage = this.config.authStorage,\r\n cookieOptions = this.config.authCookieOptions,\r\n skipValidation = this.config.authSkipValidation\r\n } = options;\r\n\r\n try {\r\n // JWT \uD1A0\uD070 \uAC80\uC99D (\uC635\uC158)\r\n if (!skipValidation && token.includes('.')) {\r\n try {\r\n const payload = JSON.parse(atob(token.split('.')[1]));\r\n if (payload.exp && Date.now() >= payload.exp * 1000) {\r\n this.log('warn', '\u274C Token is expired');\r\n return false;\r\n }\r\n this.log('debug', '\u2705 JWT token validated');\r\n } catch (error) {\r\n this.log('warn', '\u26A0\uFE0F JWT validation failed, but proceeding:', error.message);\r\n }\r\n }\r\n\r\n // \uC2A4\uD1A0\uB9AC\uC9C0\uBCC4 \uC800\uC7A5\r\n switch (storage) {\r\n case 'localStorage':\r\n localStorage.setItem('authToken', token);\r\n this.log('debug', 'Token saved to localStorage');\r\n break;\r\n\r\n case 'sessionStorage':\r\n sessionStorage.setItem('authToken', token);\r\n this.log('debug', 'Token saved to sessionStorage');\r\n break;\r\n\r\n case 'cookie':\r\n this.setAuthCookie(token, cookieOptions);\r\n break;\r\n\r\n default:\r\n // \uAE30\uBCF8\uAC12: localStorage\r\n localStorage.setItem('authToken', token);\r\n this.log('debug', 'Token saved to localStorage (default)');\r\n }\r\n\r\n this.emitAuthEvent('token_set', { \r\n storage,\r\n tokenLength: token.length,\r\n hasExpiration: token.includes('.')\r\n });\r\n\r\n return true;\r\n\r\n } catch (error) {\r\n this.log('Failed to set token:', error);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uCFE0\uD0A4 \uC124\uC815\r\n */\r\n setAuthCookie(token, options = {}) {\r\n const {\r\n cookieName = this.config.authCookieName,\r\n secure = window.location.protocol === 'https:',\r\n sameSite = 'Strict',\r\n path = '/',\r\n domain = null\r\n } = options;\r\n\r\n let cookieString = `${cookieName}=${encodeURIComponent(token)}; path=${path}`;\r\n\r\n if (secure) {\r\n cookieString += '; Secure';\r\n }\r\n\r\n if (sameSite) {\r\n cookieString += `; SameSite=${sameSite}`;\r\n }\r\n\r\n if (domain) {\r\n cookieString += `; Domain=${domain}`;\r\n }\r\n\r\n // JWT\uC5D0\uC11C \uB9CC\uB8CC \uC2DC\uAC04 \uCD94\uCD9C\r\n try {\r\n if (token.includes('.')) {\r\n try {\r\n const payload = JSON.parse(atob(token.split('.')[1]));\r\n if (payload.exp) {\r\n const expireDate = new Date(payload.exp * 1000);\r\n cookieString += `; Expires=${expireDate.toUTCString()}`;\r\n }\r\n } catch (error) {\r\n this.log('Could not extract expiration from JWT token');\r\n }\r\n }\r\n } catch (error) {\r\n this.log('Token processing error:', error);\r\n }\r\n\r\n document.cookie = cookieString;\r\n this.log(`Auth cookie set: ${cookieName}`);\r\n }\r\n\r\n /**\r\n * \uD1A0\uD070 \uC81C\uAC70\r\n */\r\n removeAccessToken(storage = 'all') {\r\n switch (storage) {\r\n case 'localStorage':\r\n localStorage.removeItem('authToken');\r\n localStorage.removeItem('accessToken');\r\n break;\r\n\r\n case 'sessionStorage':\r\n sessionStorage.removeItem('authToken');\r\n sessionStorage.removeItem('accessToken');\r\n break;\r\n\r\n case 'cookie':\r\n this.removeAuthCookie();\r\n break;\r\n\r\n case 'all':\r\n default:\r\n localStorage.removeItem('authToken');\r\n localStorage.removeItem('accessToken');\r\n sessionStorage.removeItem('authToken');\r\n sessionStorage.removeItem('accessToken');\r\n this.removeAuthCookie();\r\n break;\r\n }\r\n\r\n this.emitAuthEvent('token_removed', { storage });\r\n this.log(`Token removed from: ${storage}`);\r\n }\r\n\r\n /**\r\n * \uB85C\uADF8\uC778 \uC131\uACF5 \uCC98\uB9AC\r\n */\r\n handleLoginSuccess(targetRoute = null) {\r\n const redirectRoute = targetRoute || this.config.redirectAfterLogin;\r\n \r\n this.log(`\uD83C\uDF89 Login success, redirecting to: ${redirectRoute}`);\r\n \r\n this.emitAuthEvent('login_success', { targetRoute: redirectRoute });\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4\uAC00 \uC788\uC73C\uBA74 \uC9C1\uC811 \uB124\uBE44\uAC8C\uC774\uC158\r\n if (this.router && typeof this.router.navigateTo === 'function') {\r\n this.router.navigateTo(redirectRoute);\r\n }\r\n \r\n return redirectRoute;\r\n }\r\n\r\n /**\r\n * \uB85C\uADF8\uC544\uC6C3 \uCC98\uB9AC\r\n */\r\n handleLogout() {\r\n this.log('\uD83D\uDC4B Logging out user');\r\n \r\n // \uBAA8\uB4E0 \uC800\uC7A5\uC18C\uC5D0\uC11C \uD1A0\uD070 \uC81C\uAC70\r\n this.removeAccessToken();\r\n \r\n // \uC804\uC5ED \uBCC0\uC218 \uC815\uB9AC\r\n if (window.user) window.user = null;\r\n if (window.isAuthenticated) window.isAuthenticated = false;\r\n \r\n this.emitAuthEvent('logout', {});\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4\uAC00 \uC788\uC73C\uBA74 \uC9C1\uC811 \uB124\uBE44\uAC8C\uC774\uC158\r\n if (this.router && typeof this.router.navigateTo === 'function') {\r\n this.router.navigateTo(this.config.loginRoute);\r\n }\r\n \r\n return this.config.loginRoute;\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n */\r\n emitAuthEvent(eventType, data) {\r\n const event = new CustomEvent('router:auth', {\r\n detail: {\r\n type: eventType,\r\n timestamp: Date.now(),\r\n ...data\r\n }\r\n });\r\n \r\n document.dispatchEvent(event);\r\n \r\n // \uB0B4\uBD80 \uB9AC\uC2A4\uB108\uB4E4\uC5D0\uAC8C\uB3C4 \uC54C\uB9BC\r\n if (this.eventListeners.has(eventType)) {\r\n this.eventListeners.get(eventType).forEach(listener => {\r\n try {\r\n listener(data);\r\n } catch (error) {\r\n this.log('Event listener error:', error);\r\n }\r\n });\r\n }\r\n \r\n this.log(`\uD83D\uDD14 Auth event emitted: ${eventType}`, data);\r\n }\r\n\r\n /**\r\n * \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uB4F1\uB85D\r\n */\r\n on(eventType, listener) {\r\n if (!this.eventListeners.has(eventType)) {\r\n this.eventListeners.set(eventType, []);\r\n }\r\n this.eventListeners.get(eventType).push(listener);\r\n }\r\n\r\n /**\r\n * \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70\r\n */\r\n off(eventType, listener) {\r\n if (this.eventListeners.has(eventType)) {\r\n const listeners = this.eventListeners.get(eventType);\r\n const index = listeners.indexOf(listener);\r\n if (index > -1) {\r\n listeners.splice(index, 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * \uC778\uC99D \uC0C1\uD0DC \uD1B5\uACC4\r\n */\r\n getAuthStats() {\r\n return {\r\n enabled: this.config.enabled,\r\n isAuthenticated: this.isUserAuthenticated(),\r\n hasToken: !!this.getAccessToken(),\r\n protectedRoutesCount: this.config.protectedRoutes.length,\r\n protectedPrefixesCount: this.config.protectedPrefixes.length,\r\n publicRoutesCount: this.config.publicRoutes.length,\r\n storage: this.config.authStorage,\r\n loginRoute: this.config.loginRoute\r\n };\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.eventListeners.clear();\r\n this.log('debug', 'AuthManager destroyed');\r\n }\r\n}", "/**\r\n * ViewLogic Cache Management System\r\n * \uCE90\uC2DC \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class CacheManager {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n cacheMode: options.cacheMode || 'memory', // 'memory' \uB610\uB294 'lru'\r\n cacheTTL: options.cacheTTL || 300000, // 5\uBD84 (\uBC00\uB9AC\uCD08)\r\n maxCacheSize: options.maxCacheSize || 50, // LRU \uCE90\uC2DC \uCD5C\uB300 \uD06C\uAE30\r\n debug: options.debug || false\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870 (\uD544\uC694\uC2DC \uB77C\uC6B0\uD130 \uC0C1\uD0DC \uD655\uC778\uC6A9)\r\n this.router = router;\r\n \r\n // \uCE90\uC2DC \uC800\uC7A5\uC18C\uB4E4\r\n this.cache = new Map();\r\n this.cacheTimestamps = new Map();\r\n this.lruOrder = []; // LRU \uC21C\uC11C \uCD94\uC801\r\n \r\n this.log('info', 'CacheManager initialized with config:', this.config);\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'CacheManager', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uCE90\uC2DC\uC5D0 \uAC12 \uC800\uC7A5\r\n */\r\n setCache(key, value) {\r\n const now = Date.now();\r\n \r\n if (this.config.cacheMode === 'lru') {\r\n // LRU \uCE90\uC2DC \uAD00\uB9AC\r\n if (this.cache.size >= this.config.maxCacheSize && !this.cache.has(key)) {\r\n const oldestKey = this.lruOrder.shift();\r\n if (oldestKey) {\r\n this.cache.delete(oldestKey);\r\n this.cacheTimestamps.delete(oldestKey);\r\n this.log('debug', `\uD83D\uDDD1\uFE0F LRU evicted cache key: ${oldestKey}`);\r\n }\r\n }\r\n \r\n // \uAE30\uC874 \uD0A4\uAC00 \uC788\uC73C\uBA74 LRU \uC21C\uC11C\uC5D0\uC11C \uC81C\uAC70\r\n const existingIndex = this.lruOrder.indexOf(key);\r\n if (existingIndex > -1) {\r\n this.lruOrder.splice(existingIndex, 1);\r\n }\r\n \r\n // \uCD5C\uC2E0 \uC21C\uC11C\uB85C \uCD94\uAC00\r\n this.lruOrder.push(key);\r\n }\r\n \r\n this.cache.set(key, value);\r\n this.cacheTimestamps.set(key, now);\r\n \r\n this.log('debug', `\uD83D\uDCBE Cached: ${key} (size: ${this.cache.size})`);\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC\uC5D0\uC11C \uAC12 \uAC00\uC838\uC624\uAE30\r\n */\r\n getFromCache(key) {\r\n const now = Date.now();\r\n const timestamp = this.cacheTimestamps.get(key);\r\n \r\n // TTL \uCCB4\uD06C\r\n if (timestamp && (now - timestamp) > this.config.cacheTTL) {\r\n this.cache.delete(key);\r\n this.cacheTimestamps.delete(key);\r\n \r\n if (this.config.cacheMode === 'lru') {\r\n const index = this.lruOrder.indexOf(key);\r\n if (index > -1) {\r\n this.lruOrder.splice(index, 1);\r\n }\r\n }\r\n \r\n this.log('debug', `\u23F0 Cache expired and removed: ${key}`);\r\n return null;\r\n }\r\n \r\n const value = this.cache.get(key);\r\n \r\n if (value && this.config.cacheMode === 'lru') {\r\n // LRU \uC21C\uC11C \uC5C5\uB370\uC774\uD2B8\r\n const index = this.lruOrder.indexOf(key);\r\n if (index > -1) {\r\n this.lruOrder.splice(index, 1);\r\n this.lruOrder.push(key);\r\n }\r\n }\r\n \r\n if (value) {\r\n this.log('debug', `\uD83C\uDFAF Cache hit: ${key}`);\r\n } else {\r\n this.log('debug', `\u274C Cache miss: ${key}`);\r\n }\r\n \r\n return value;\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC\uC5D0 \uD0A4\uAC00 \uC788\uB294\uC9C0 \uD655\uC778\r\n */\r\n hasCache(key) {\r\n return this.cache.has(key) && this.getFromCache(key) !== null;\r\n }\r\n \r\n /**\r\n * \uD2B9\uC815 \uD0A4 \uD328\uD134\uC758 \uCE90\uC2DC \uC0AD\uC81C\r\n */\r\n invalidateByPattern(pattern) {\r\n const keysToDelete = [];\r\n \r\n for (const key of this.cache.keys()) {\r\n if (key.includes(pattern) || key.startsWith(pattern)) {\r\n keysToDelete.push(key);\r\n }\r\n }\r\n \r\n keysToDelete.forEach(key => {\r\n this.cache.delete(key);\r\n this.cacheTimestamps.delete(key);\r\n \r\n if (this.config.cacheMode === 'lru') {\r\n const index = this.lruOrder.indexOf(key);\r\n if (index > -1) {\r\n this.lruOrder.splice(index, 1);\r\n }\r\n }\r\n });\r\n \r\n this.log('debug', `\uD83E\uDDF9 Invalidated ${keysToDelete.length} cache entries matching: ${pattern}`);\r\n return keysToDelete.length;\r\n }\r\n \r\n /**\r\n * \uD2B9\uC815 \uCEF4\uD3EC\uB10C\uD2B8 \uCE90\uC2DC \uBB34\uD6A8\uD654\r\n */\r\n invalidateComponentCache(routeName) {\r\n const patterns = [\r\n `component_${routeName}`,\r\n `script_${routeName}`,\r\n `template_${routeName}`,\r\n `style_${routeName}`,\r\n `layout_${routeName}`\r\n ];\r\n \r\n let totalInvalidated = 0;\r\n patterns.forEach(pattern => {\r\n totalInvalidated += this.invalidateByPattern(pattern);\r\n });\r\n \r\n this.log(`\uD83D\uDD04 Invalidated component cache for route: ${routeName} (${totalInvalidated} entries)`);\r\n return totalInvalidated;\r\n }\r\n \r\n /**\r\n * \uBAA8\uB4E0 \uCEF4\uD3EC\uB10C\uD2B8 \uCE90\uC2DC \uC0AD\uC81C\r\n */\r\n clearComponentCache() {\r\n const componentPatterns = ['component_', 'script_', 'template_', 'style_', 'layout_'];\r\n let totalCleared = 0;\r\n \r\n componentPatterns.forEach(pattern => {\r\n totalCleared += this.invalidateByPattern(pattern);\r\n });\r\n \r\n this.log(`\uD83E\uDDFD Cleared all component caches (${totalCleared} entries)`);\r\n return totalCleared;\r\n }\r\n \r\n /**\r\n * \uC804\uCCB4 \uCE90\uC2DC \uC0AD\uC81C\r\n */\r\n clearCache() {\r\n const size = this.cache.size;\r\n this.cache.clear();\r\n this.cacheTimestamps.clear();\r\n this.lruOrder = [];\r\n \r\n this.log(`\uD83D\uDD25 Cleared all cache (${size} entries)`);\r\n return size;\r\n }\r\n \r\n /**\r\n * \uB9CC\uB8CC\uB41C \uCE90\uC2DC \uD56D\uBAA9\uB4E4 \uC815\uB9AC\r\n */\r\n cleanExpiredCache() {\r\n const now = Date.now();\r\n const expiredKeys = [];\r\n \r\n for (const [key, timestamp] of this.cacheTimestamps.entries()) {\r\n if ((now - timestamp) > this.config.cacheTTL) {\r\n expiredKeys.push(key);\r\n }\r\n }\r\n \r\n expiredKeys.forEach(key => {\r\n this.cache.delete(key);\r\n this.cacheTimestamps.delete(key);\r\n \r\n if (this.config.cacheMode === 'lru') {\r\n const index = this.lruOrder.indexOf(key);\r\n if (index > -1) {\r\n this.lruOrder.splice(index, 1);\r\n }\r\n }\r\n });\r\n \r\n if (expiredKeys.length > 0) {\r\n this.log(`\u23F1\uFE0F Cleaned ${expiredKeys.length} expired cache entries`);\r\n }\r\n \r\n return expiredKeys.length;\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC \uD1B5\uACC4 \uC815\uBCF4\r\n */\r\n getCacheStats() {\r\n return {\r\n size: this.cache.size,\r\n maxSize: this.config.maxCacheSize,\r\n mode: this.config.cacheMode,\r\n ttl: this.config.cacheTTL,\r\n memoryUsage: this.getMemoryUsage(),\r\n hitRatio: this.getHitRatio(),\r\n categories: this.getCategorizedStats()\r\n };\r\n }\r\n \r\n /**\r\n * \uBA54\uBAA8\uB9AC \uC0AC\uC6A9\uB7C9 \uCD94\uC815\r\n */\r\n getMemoryUsage() {\r\n let estimatedBytes = 0;\r\n \r\n for (const [key, value] of this.cache.entries()) {\r\n // \uD0A4 \uD06C\uAE30\r\n estimatedBytes += key.length * 2; // UTF-16\r\n \r\n // \uAC12 \uD06C\uAE30 \uCD94\uC815\r\n if (typeof value === 'string') {\r\n estimatedBytes += value.length * 2;\r\n } else if (typeof value === 'object' && value !== null) {\r\n estimatedBytes += JSON.stringify(value).length * 2;\r\n } else {\r\n estimatedBytes += 8; // \uB300\uB7B5\uC801\uC778 \uD06C\uAE30\r\n }\r\n }\r\n \r\n return {\r\n bytes: estimatedBytes,\r\n kb: Math.round(estimatedBytes / 1024 * 100) / 100,\r\n mb: Math.round(estimatedBytes / (1024 * 1024) * 100) / 100\r\n };\r\n }\r\n \r\n /**\r\n * \uD788\uD2B8 \uBE44\uC728 \uACC4\uC0B0 (\uAC04\uB2E8\uD55C \uCD94\uC815)\r\n */\r\n getHitRatio() {\r\n // \uC2E4\uC81C \uD788\uD2B8/\uBBF8\uC2A4 \uCD94\uC801\uC744 \uC704\uD574\uC11C\uB294 \uBCC4\uB3C4\uC758 \uCE74\uC6B4\uD130\uAC00 \uD544\uC694\r\n // \uD604\uC7AC\uB294 \uCE90\uC2DC \uD06C\uAE30 \uAE30\uBC18 \uCD94\uC815\uCE58 \uBC18\uD658\r\n const ratio = this.cache.size > 0 ? Math.min(this.cache.size / this.config.maxCacheSize, 1) : 0;\r\n return Math.round(ratio * 100);\r\n }\r\n \r\n /**\r\n * \uCE74\uD14C\uACE0\uB9AC\uBCC4 \uCE90\uC2DC \uD1B5\uACC4\r\n */\r\n getCategorizedStats() {\r\n const categories = {\r\n components: 0,\r\n scripts: 0,\r\n templates: 0,\r\n styles: 0,\r\n layouts: 0,\r\n others: 0\r\n };\r\n \r\n for (const key of this.cache.keys()) {\r\n if (key.startsWith('component_')) categories.components++;\r\n else if (key.startsWith('script_')) categories.scripts++;\r\n else if (key.startsWith('template_')) categories.templates++;\r\n else if (key.startsWith('style_')) categories.styles++;\r\n else if (key.startsWith('layout_')) categories.layouts++;\r\n else categories.others++;\r\n }\r\n \r\n return categories;\r\n }\r\n \r\n /**\r\n * \uCE90\uC2DC \uD0A4 \uBAA9\uB85D \uBC18\uD658\r\n */\r\n getCacheKeys() {\r\n return Array.from(this.cache.keys());\r\n }\r\n \r\n /**\r\n * \uD2B9\uC815 \uD328\uD134\uC758 \uCE90\uC2DC \uD0A4\uB4E4 \uBC18\uD658\r\n */\r\n getCacheKeysByPattern(pattern) {\r\n return this.getCacheKeys().filter(key => \r\n key.includes(pattern) || key.startsWith(pattern)\r\n );\r\n }\r\n \r\n /**\r\n * \uC790\uB3D9 \uC815\uB9AC \uC2DC\uC791 (\uBC31\uADF8\uB77C\uC6B4\uB4DC\uC5D0\uC11C \uB9CC\uB8CC\uB41C \uCE90\uC2DC \uC815\uB9AC)\r\n */\r\n startAutoCleanup(interval = 60000) { // \uAE30\uBCF8 1\uBD84 \uAC04\uACA9\r\n if (this.cleanupInterval) {\r\n clearInterval(this.cleanupInterval);\r\n }\r\n \r\n this.cleanupInterval = setInterval(() => {\r\n this.cleanExpiredCache();\r\n }, interval);\r\n \r\n this.log(`\uD83E\uDD16 Auto cleanup started (interval: ${interval}ms)`);\r\n }\r\n \r\n /**\r\n * \uC790\uB3D9 \uC815\uB9AC \uC911\uC9C0\r\n */\r\n stopAutoCleanup() {\r\n if (this.cleanupInterval) {\r\n clearInterval(this.cleanupInterval);\r\n this.cleanupInterval = null;\r\n this.log('debug', '\uD83D\uDED1 Auto cleanup stopped');\r\n }\r\n }\r\n \r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.stopAutoCleanup();\r\n this.clearCache();\r\n this.log('debug', 'CacheManager destroyed');\r\n }\r\n}", "/**\r\n * ViewLogic Query Management System\r\n * URL \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class QueryManager {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n enableParameterValidation: options.enableParameterValidation !== false,\r\n logSecurityWarnings: options.logSecurityWarnings !== false,\r\n maxParameterLength: options.maxParameterLength || 1000,\r\n maxArraySize: options.maxArraySize || 100,\r\n maxParameterCount: options.maxParameterCount || 50,\r\n allowedKeyPattern: options.allowedKeyPattern || /^[a-zA-Z0-9_\\-]+$/,\r\n debug: options.debug || false\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870\r\n this.router = router;\r\n \r\n // \uD604\uC7AC \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC0C1\uD0DC\r\n this.currentQueryParams = {};\r\n \r\n // \uD604\uC7AC \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130 \uC0C1\uD0DC (navigateTo\uB85C \uC804\uB2EC\uB41C params)\r\n this.currentRouteParams = {};\r\n \r\n this.log('info', 'QueryManager initialized with config:', this.config);\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'QueryManager', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uD30C\uB77C\uBBF8\uD130 \uAC12 sanitize (XSS, SQL Injection \uBC29\uC5B4)\r\n */\r\n sanitizeParameter(value) {\r\n if (typeof value !== 'string') return value;\r\n \r\n // XSS \uBC29\uC5B4: HTML \uD0DC\uADF8\uC640 \uC2A4\uD06C\uB9BD\uD2B8 \uC81C\uAC70\r\n let sanitized = value\r\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '') // script \uD0DC\uADF8 \uC81C\uAC70\r\n .replace(/<iframe\\b[^<]*(?:(?!<\\/iframe>)<[^<]*)*<\\/iframe>/gi, '') // iframe \uD0DC\uADF8 \uC81C\uAC70\r\n .replace(/<object\\b[^<]*(?:(?!<\\/object>)<[^<]*)*<\\/object>/gi, '') // object \uD0DC\uADF8 \uC81C\uAC70\r\n .replace(/<embed\\b[^<]*(?:(?!<\\/embed>)<[^<]*)*<\\/embed>/gi, '') // embed \uD0DC\uADF8 \uC81C\uAC70\r\n .replace(/<link\\b[^<]*>/gi, '') // link \uD0DC\uADF8 \uC81C\uAC70\r\n .replace(/<meta\\b[^<]*>/gi, '') // meta \uD0DC\uADF8 \uC81C\uAC70\r\n .replace(/javascript:/gi, '') // javascript: \uD504\uB85C\uD1A0\uCF5C \uC81C\uAC70\r\n .replace(/vbscript:/gi, '') // vbscript: \uD504\uB85C\uD1A0\uCF5C \uC81C\uAC70\r\n .replace(/data:/gi, '') // data: \uD504\uB85C\uD1A0\uCF5C \uC81C\uAC70\r\n .replace(/on\\w+\\s*=/gi, '') // \uC774\uBCA4\uD2B8 \uD578\uB4E4\uB7EC \uC81C\uAC70 (onclick, onload \uB4F1)\r\n .replace(/expression\\s*\\(/gi, '') // CSS expression \uC81C\uAC70\r\n .replace(/url\\s*\\(/gi, ''); // CSS url() \uC81C\uAC70\r\n \r\n // SQL Injection \uBC29\uC5B4: \uC704\uD5D8\uD55C SQL \uD0A4\uC6CC\uB4DC \uD544\uD130\uB9C1\r\n const sqlPatterns = [\r\n /(\\b(union|select|insert|update|delete|drop|create|alter|exec|execute|sp_|xp_)\\b)/gi,\r\n /(;|\\||&|\\*|%|<|>)/g, // \uC704\uD5D8\uD55C \uD2B9\uC218\uBB38\uC790\r\n /(--|\\/\\*|\\*\\/)/g, // SQL \uC8FC\uC11D\r\n /(\\bor\\b.*\\b=\\b|\\band\\b.*\\b=\\b)/gi, // OR/AND \uC870\uAC74\uBB38\r\n /('.*'|\".*\")/g, // \uB530\uC634\uD45C\uB85C \uB458\uB7EC\uC2F8\uC778 \uBB38\uC790\uC5F4\r\n /(\\\\\\w+)/g // \uBC31\uC2AC\uB798\uC2DC \uC774\uC2A4\uCF00\uC774\uD504\r\n ];\r\n \r\n for (const pattern of sqlPatterns) {\r\n sanitized = sanitized.replace(pattern, '');\r\n }\r\n \r\n // \uCD94\uAC00 \uBCF4\uC548: \uC5F0\uC18D\uB41C \uD2B9\uC218\uBB38\uC790 \uC81C\uAC70\r\n sanitized = sanitized.replace(/[<>'\"&]{2,}/g, '');\r\n \r\n // \uAE38\uC774 \uC81C\uD55C (DoS \uBC29\uC5B4)\r\n if (sanitized.length > this.config.maxParameterLength) {\r\n sanitized = sanitized.substring(0, this.config.maxParameterLength);\r\n }\r\n \r\n return sanitized.trim();\r\n }\r\n\r\n /**\r\n * \uD30C\uB77C\uBBF8\uD130 \uC720\uD6A8\uC131 \uAC80\uC99D\r\n */\r\n validateParameter(key, value) {\r\n // \uBCF4\uC548 \uAC80\uC99D\uC774 \uBE44\uD65C\uC131\uD654\uB41C \uACBD\uC6B0 \uD1B5\uACFC\r\n if (!this.config.enableParameterValidation) {\r\n return true;\r\n }\r\n \r\n // \uD30C\uB77C\uBBF8\uD130 \uD0A4 \uAC80\uC99D\r\n if (typeof key !== 'string' || key.length === 0) {\r\n return false;\r\n }\r\n \r\n // \uD0A4 \uC774\uB984 \uC81C\uD55C\r\n if (!this.config.allowedKeyPattern.test(key)) {\r\n if (this.config.logSecurityWarnings) {\r\n console.warn(`Invalid parameter key format: ${key}`);\r\n }\r\n return false;\r\n }\r\n \r\n // \uD0A4 \uAE38\uC774 \uC81C\uD55C\r\n if (key.length > 50) {\r\n if (this.config.logSecurityWarnings) {\r\n console.warn(`Parameter key too long: ${key}`);\r\n }\r\n return false;\r\n }\r\n \r\n // \uAC12 \uD0C0\uC785 \uAC80\uC99D\r\n if (value !== null && value !== undefined) {\r\n if (typeof value === 'string') {\r\n // \uBB38\uC790\uC5F4 \uAE38\uC774 \uC81C\uD55C\r\n if (value.length > this.config.maxParameterLength) {\r\n if (this.config.logSecurityWarnings) {\r\n console.warn(`Parameter value too long for key: ${key}`);\r\n }\r\n return false;\r\n }\r\n \r\n // \uC704\uD5D8\uD55C \uD328\uD134 \uAC10\uC9C0\r\n const dangerousPatterns = [\r\n /<script|<iframe|<object|<embed/gi,\r\n /javascript:|vbscript:|data:/gi,\r\n /union.*select|insert.*into|delete.*from/gi,\r\n /\\.\\.\\//g, // \uACBD\uB85C \uD0D0\uC0C9 \uACF5\uACA9\r\n /[<>'\"&]{3,}/g // \uC5F0\uC18D\uB41C \uD2B9\uC218\uBB38\uC790\r\n ];\r\n \r\n for (const pattern of dangerousPatterns) {\r\n if (pattern.test(value)) {\r\n if (this.config.logSecurityWarnings) {\r\n console.warn(`Dangerous pattern detected in parameter ${key}:`, value);\r\n }\r\n return false;\r\n }\r\n }\r\n } else if (Array.isArray(value)) {\r\n // \uBC30\uC5F4 \uAE38\uC774 \uC81C\uD55C\r\n if (value.length > this.config.maxArraySize) {\r\n if (this.config.logSecurityWarnings) {\r\n console.warn(`Parameter array too large for key: ${key}`);\r\n }\r\n return false;\r\n }\r\n \r\n // \uBC30\uC5F4 \uAC01 \uC694\uC18C \uAC80\uC99D\r\n for (const item of value) {\r\n if (!this.validateParameter(`${key}[]`, item)) {\r\n return false;\r\n }\r\n }\r\n }\r\n }\r\n \r\n return true;\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC\uC2A4\uD2B8\uB9C1 \uD30C\uC2F1\r\n */\r\n parseQueryString(queryString) {\r\n const params = {};\r\n if (!queryString) return params;\r\n \r\n const pairs = queryString.split('&');\r\n for (const pair of pairs) {\r\n try {\r\n const [rawKey, rawValue] = pair.split('=');\r\n if (!rawKey) continue;\r\n \r\n let key, value;\r\n try {\r\n key = decodeURIComponent(rawKey);\r\n value = rawValue ? decodeURIComponent(rawValue) : '';\r\n } catch (e) {\r\n this.log('warn', 'Failed to decode URI component:', pair);\r\n continue;\r\n }\r\n \r\n // \uBCF4\uC548 \uAC80\uC99D\r\n if (!this.validateParameter(key, value)) {\r\n this.log('warn', `Parameter rejected by security filter: ${key}`);\r\n continue;\r\n }\r\n \r\n // \uAC12 sanitize\r\n const sanitizedValue = this.sanitizeParameter(value);\r\n \r\n // \uBC30\uC5F4 \uD615\uD0DC\uC758 \uD30C\uB77C\uBBF8\uD130 \uCC98\uB9AC (\uC608: tags[]=a&tags[]=b)\r\n if (key.endsWith('[]')) {\r\n const arrayKey = key.slice(0, -2);\r\n \r\n // \uBC30\uC5F4 \uD0A4\uB3C4 \uAC80\uC99D\r\n if (!this.validateParameter(arrayKey, [])) {\r\n continue;\r\n }\r\n \r\n if (!params[arrayKey]) params[arrayKey] = [];\r\n \r\n // \uBC30\uC5F4 \uD06C\uAE30 \uC81C\uD55C\r\n if (params[arrayKey].length < this.config.maxArraySize) {\r\n params[arrayKey].push(sanitizedValue);\r\n } else {\r\n if (this.config.logSecurityWarnings) {\r\n console.warn(`Array parameter ${arrayKey} size limit exceeded`);\r\n }\r\n }\r\n } else {\r\n params[key] = sanitizedValue;\r\n }\r\n } catch (error) {\r\n this.log('error', 'Error parsing query parameter:', pair, error);\r\n }\r\n }\r\n \r\n // \uC804\uCCB4 \uD30C\uB77C\uBBF8\uD130 \uAC1C\uC218 \uC81C\uD55C\r\n const paramCount = Object.keys(params).length;\r\n if (paramCount > this.config.maxParameterCount) {\r\n if (this.config.logSecurityWarnings) {\r\n console.warn(`Too many parameters (${paramCount}). Limiting to first ${this.config.maxParameterCount}.`);\r\n }\r\n const limitedParams = {};\r\n let count = 0;\r\n for (const [key, value] of Object.entries(params)) {\r\n if (count >= this.config.maxParameterCount) break;\r\n limitedParams[key] = value;\r\n count++;\r\n }\r\n return limitedParams;\r\n }\r\n \r\n return params;\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC\uC2A4\uD2B8\uB9C1 \uC0DD\uC131\r\n */\r\n buildQueryString(params) {\r\n if (!params || Object.keys(params).length === 0) return '';\r\n \r\n const pairs = [];\r\n for (const [key, value] of Object.entries(params)) {\r\n if (Array.isArray(value)) {\r\n // \uBC30\uC5F4 \uD30C\uB77C\uBBF8\uD130 \uCC98\uB9AC\r\n for (const item of value) {\r\n pairs.push(`${encodeURIComponent(key)}[]=${encodeURIComponent(item)}`);\r\n }\r\n } else if (value !== undefined && value !== null) {\r\n pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\r\n }\r\n }\r\n return pairs.join('&');\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uBCC0\uACBD \uAC10\uC9C0\r\n */\r\n hasQueryParamsChanged(newParams) {\r\n if (!this.currentQueryParams && !newParams) return false;\r\n if (!this.currentQueryParams || !newParams) return true;\r\n \r\n const oldKeys = Object.keys(this.currentQueryParams);\r\n const newKeys = Object.keys(newParams);\r\n \r\n if (oldKeys.length !== newKeys.length) return true;\r\n \r\n for (const key of oldKeys) {\r\n if (JSON.stringify(this.currentQueryParams[key]) !== JSON.stringify(newParams[key])) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC804\uCCB4 \uAC00\uC838\uC624\uAE30\r\n */\r\n getQueryParams() {\r\n return { ...this.currentQueryParams };\r\n }\r\n\r\n /**\r\n * \uD2B9\uC815 \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uAC00\uC838\uC624\uAE30\r\n */\r\n getQueryParam(key, defaultValue = undefined) {\r\n const value = this.currentQueryParams ? this.currentQueryParams[key] : undefined;\r\n return value !== undefined ? value : defaultValue;\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC124\uC815\r\n */\r\n setQueryParams(params, replace = false) {\r\n if (!params || typeof params !== 'object') {\r\n console.warn('Invalid parameters object provided to setQueryParams');\r\n return;\r\n }\r\n \r\n const currentParams = replace ? {} : { ...this.currentQueryParams };\r\n const sanitizedParams = {};\r\n \r\n // \uD30C\uB77C\uBBF8\uD130 \uAC80\uC99D \uBC0F sanitize\r\n for (const [key, value] of Object.entries(params)) {\r\n // \uD0A4\uC640 \uAC12 \uAC80\uC99D\r\n if (!this.validateParameter(key, value)) {\r\n console.warn(`Parameter ${key} rejected by security filter`);\r\n continue;\r\n }\r\n \r\n // \uAC12 \uCC98\uB9AC\r\n if (value !== undefined && value !== null) {\r\n if (Array.isArray(value)) {\r\n sanitizedParams[key] = value.map(item => this.sanitizeParameter(item));\r\n } else {\r\n sanitizedParams[key] = this.sanitizeParameter(value);\r\n }\r\n }\r\n }\r\n \r\n // \uD604\uC7AC \uD30C\uB77C\uBBF8\uD130 \uC5C5\uB370\uC774\uD2B8\r\n Object.assign(currentParams, sanitizedParams);\r\n \r\n // undefined\uB098 null \uAC12 \uC81C\uAC70\r\n for (const [key, value] of Object.entries(currentParams)) {\r\n if (value === undefined || value === null || value === '') {\r\n delete currentParams[key];\r\n }\r\n }\r\n \r\n // \uCD5C\uB300 \uD30C\uB77C\uBBF8\uD130 \uAC1C\uC218 \uD655\uC778\r\n const paramCount = Object.keys(currentParams).length;\r\n if (paramCount > this.config.maxParameterCount) {\r\n if (this.config.logSecurityWarnings) {\r\n console.warn(`Too many parameters after update (${paramCount}). Some parameters may be dropped.`);\r\n }\r\n }\r\n \r\n this.currentQueryParams = currentParams;\r\n this.updateURL();\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC81C\uAC70\r\n */\r\n removeQueryParams(keys) {\r\n if (!keys) return;\r\n \r\n const keysToRemove = Array.isArray(keys) ? keys : [keys];\r\n for (const key of keysToRemove) {\r\n delete this.currentQueryParams[key];\r\n }\r\n \r\n this.updateURL();\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uCD08\uAE30\uD654\r\n */\r\n clearQueryParams() {\r\n this.currentQueryParams = {};\r\n this.updateURL();\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC124\uC815 (\uB77C\uC6B0\uD130\uC5D0\uC11C \uD638\uCD9C)\r\n */\r\n setCurrentQueryParams(params) {\r\n this.currentQueryParams = params || {};\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130 \uC124\uC815 (navigateTo\uC5D0\uC11C \uD638\uCD9C)\r\n */\r\n setCurrentRouteParams(params) {\r\n this.currentRouteParams = params || {};\r\n this.log('debug', 'Route params set:', this.currentRouteParams);\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569\uB41C \uD30C\uB77C\uBBF8\uD130 \uBC18\uD658 (\uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130 + \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130)\r\n */\r\n getAllParams() {\r\n return {\r\n ...this.currentRouteParams,\r\n ...this.currentQueryParams\r\n };\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569\uB41C \uD30C\uB77C\uBBF8\uD130\uC5D0\uC11C \uD2B9\uC815 \uD0A4 \uAC12 \uBC18\uD658\r\n */\r\n getParam(key, defaultValue = undefined) {\r\n // \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130\uAC00 \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130\uBCF4\uB2E4 \uC6B0\uC120\uC21C\uC704 \uB192\uC74C\r\n const value = this.currentQueryParams[key] !== undefined ? \r\n this.currentQueryParams[key] : \r\n this.currentRouteParams[key];\r\n return value !== undefined ? value : defaultValue;\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130\uB9CC \uBC18\uD658\r\n */\r\n getRouteParams() {\r\n return { ...this.currentRouteParams };\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130\uC5D0\uC11C \uD2B9\uC815 \uD0A4 \uAC12 \uBC18\uD658\r\n */\r\n getRouteParam(key, defaultValue = undefined) {\r\n const value = this.currentRouteParams[key];\r\n return value !== undefined ? value : defaultValue;\r\n }\r\n\r\n /**\r\n * URL \uC5C5\uB370\uC774\uD2B8 (\uB77C\uC6B0\uD130\uC758 updateURL \uBA54\uC18C\uB4DC \uD638\uCD9C)\r\n */\r\n updateURL() {\r\n if (this.router && typeof this.router.updateURL === 'function') {\r\n const route = this.router.currentHash || 'home';\r\n this.router.updateURL(route, this.currentQueryParams);\r\n }\r\n }\r\n\r\n /**\r\n * \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uD1B5\uACC4\r\n */\r\n getStats() {\r\n return {\r\n currentParams: Object.keys(this.currentQueryParams).length,\r\n maxAllowed: this.config.maxParameterCount,\r\n validationEnabled: this.config.enableParameterValidation,\r\n currentQueryString: this.buildQueryString(this.currentQueryParams)\r\n };\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.currentQueryParams = {};\r\n this.currentRouteParams = {};\r\n this.router = null;\r\n this.log('debug', 'QueryManager destroyed');\r\n }\r\n}", "/**\r\n * ViewLogic Route Loading System\r\n * \uB77C\uC6B0\uD2B8 \uB85C\uB529 \uBC0F \uCEF4\uD3EC\uB10C\uD2B8 \uAD00\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class RouteLoader {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n srcPath: options.srcPath || router.config.srcPath || '/src', // \uC18C\uC2A4 \uD30C\uC77C \uACBD\uB85C\r\n routesPath: options.routesPath || router.config.routesPath || '/routes', // \uD504\uB85C\uB355\uC158 \uB77C\uC6B0\uD2B8 \uACBD\uB85C\r\n environment: options.environment || 'development',\r\n useLayout: options.useLayout !== false,\r\n defaultLayout: options.defaultLayout || 'default',\r\n useComponents: options.useComponents !== false,\r\n debug: options.debug || false\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870\r\n this.router = router;\r\n this.log('debug', 'RouteLoader initialized with config:', this.config);\r\n }\r\n\r\n /**\r\n * \uC2A4\uD06C\uB9BD\uD2B8 \uD30C\uC77C \uB85C\uB4DC\r\n */\r\n async loadScript(routeName) {\r\n let script;\r\n try {\r\n if (this.config.environment === 'production') {\r\n // \uD504\uB85C\uB355\uC158 \uBAA8\uB4DC: routes \uD3F4\uB354\uC5D0\uC11C \uBE4C\uB4DC\uB41C JS \uB85C\uB4DC (\uC808\uB300 \uACBD\uB85C)\r\n const importPath = `${this.config.routesPath}/${routeName}.js`;\r\n this.log('debug', `Loading production route: ${importPath}`);\r\n const module = await import(importPath);\r\n script = module.default;\r\n } else {\r\n // \uAC1C\uBC1C \uBAA8\uB4DC: srcPath \uC0AC\uC6A9\uD558\uC5EC \uC18C\uC2A4 \uD30C\uC77C \uACBD\uB85C \uAD6C\uC131\r\n const importPath = `${this.config.srcPath}/logic/${routeName}.js`;\r\n this.log('debug', `Loading development route: ${importPath}`);\r\n const module = await import(importPath);\r\n script = module.default;\r\n }\r\n \r\n if (!script) {\r\n throw new Error(`Route '${routeName}' not found - no default export`);\r\n }\r\n \r\n } catch (error) {\r\n // import \uC5D0\uB7EC\uB97C 404\uB85C \uBD84\uB958\r\n if (error.message.includes('Failed to resolve') || \r\n error.message.includes('Failed to fetch') ||\r\n error.message.includes('not found') ||\r\n error.name === 'TypeError') {\r\n throw new Error(`Route '${routeName}' not found - 404`);\r\n }\r\n // \uB2E4\uB978 \uC5D0\uB7EC\uB294 \uADF8\uB300\uB85C \uC804\uD30C\r\n throw error;\r\n }\r\n \r\n return script;\r\n }\r\n\r\n /**\r\n * \uD15C\uD50C\uB9BF \uD30C\uC77C \uB85C\uB4DC (\uC2E4\uD328\uC2DC \uAE30\uBCF8\uAC12 \uBC18\uD658)\r\n */\r\n async loadTemplate(routeName) {\r\n try {\r\n const templatePath = `${this.config.srcPath}/views/${routeName}.html`;\r\n const response = await fetch(templatePath);\r\n if (!response.ok) throw new Error(`Template not found: ${response.status}`);\r\n const template = await response.text();\r\n this.log('debug', `Template '${routeName}' loaded successfully`);\r\n return template;\r\n } catch (error) {\r\n this.log('warn', `Template '${routeName}' not found, using default:`, error.message);\r\n // \uAE30\uBCF8 \uD15C\uD50C\uB9BF \uBC18\uD658\r\n return this.generateDefaultTemplate(routeName);\r\n }\r\n }\r\n\r\n /**\r\n * \uC2A4\uD0C0\uC77C \uD30C\uC77C \uB85C\uB4DC (\uC2E4\uD328\uC2DC \uBE48 \uBB38\uC790\uC5F4 \uBC18\uD658)\r\n */\r\n async loadStyle(routeName) {\r\n try {\r\n const stylePath = `${this.config.srcPath}/styles/${routeName}.css`;\r\n const response = await fetch(stylePath);\r\n if (!response.ok) throw new Error(`Style not found: ${response.status}`);\r\n const style = await response.text();\r\n this.log('debug', `Style '${routeName}' loaded successfully`);\r\n return style;\r\n } catch (error) {\r\n this.log('debug', `Style '${routeName}' not found, no styles applied:`, error.message);\r\n // \uC2A4\uD0C0\uC77C\uC774 \uC5C6\uC73C\uBA74 \uBE48 \uBB38\uC790\uC5F4 \uBC18\uD658\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * \uB808\uC774\uC544\uC6C3 \uD30C\uC77C \uB85C\uB4DC (\uC2E4\uD328\uC2DC null \uBC18\uD658)\r\n */\r\n async loadLayout(layoutName) {\r\n try {\r\n const layoutPath = `${this.config.srcPath}/layouts/${layoutName}.html`;\r\n const response = await fetch(layoutPath);\r\n if (!response.ok) throw new Error(`Layout not found: ${response.status}`);\r\n const layout = await response.text();\r\n \r\n this.log('debug', `Layout '${layoutName}' loaded successfully`);\r\n return layout;\r\n } catch (error) {\r\n this.log('debug', `Layout '${layoutName}' not found, no layout applied:`, error.message);\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * \uB808\uC774\uC544\uC6C3\uACFC \uD15C\uD50C\uB9BF \uBCD1\uD569\r\n */\r\n mergeLayoutWithTemplate(routeName, layout, template) {\r\n let result;\r\n // \uB808\uC774\uC544\uC6C3\uC5D0\uC11C <slot name=\"content\"> \uBD80\uBD84\uC744 \uD15C\uD50C\uB9BF\uC73C\uB85C \uAD50\uCCB4\r\n if (layout.includes('{{ content }}')) {\r\n result = layout.replace(\r\n /{{ content }}/s,\r\n template\r\n );\r\n }\r\n // slot\uC774 \uC5C6\uC73C\uBA74 main-content \uD074\uB798\uC2A4 \uB0B4\uC6A9 \uAD50\uCCB4\r\n else if (layout.includes('class=\"main-content\"')) {\r\n this.log('debug', 'Using main-content replacement');\r\n result = layout.replace(\r\n /(<div class=\"container\">).*?(<\\/div>\\s*<\\/main>)/s,\r\n `$1${template}$2`\r\n );\r\n }\r\n // \uB9C8\uC9C0\uB9C9 \uB300\uC548: \uC804\uCCB4 \uB808\uC774\uC544\uC6C3\uC744 \uD15C\uD50C\uB9BF\uC73C\uB85C \uAC10\uC2F8\uAE30\r\n else {\r\n this.log('debug', 'Wrapping template with layout');\r\n result = `${layout}\\n${template}`;\r\n }\r\n \r\n return result;\r\n }\r\n\r\n\r\n /**\r\n * Vue \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131\r\n */\r\n async createVueComponent(routeName) {\r\n // \uCE90\uC2DC\uB41C Vue \uCEF4\uD3EC\uB10C\uD2B8\uAC00 \uC788\uB294\uC9C0 \uD655\uC778\r\n const cacheKey = `component_${routeName}`;\r\n const cached = this.router.cacheManager?.getFromCache(cacheKey);\r\n if (cached) {\r\n return cached;\r\n }\r\n \r\n const script = await this.loadScript(routeName);\r\n const router = this.router;\r\n const isProduction = this.config.environment === 'production';\r\n \r\n // \uD658\uACBD\uBCC4 \uB9AC\uC18C\uC2A4 \uB85C\uB529\r\n let template, style = '', layout = null;\r\n \r\n if (isProduction) {\r\n // \uD504\uB85C\uB355\uC158: \uC2A4\uD06C\uB9BD\uD2B8\uC5D0 \uC788\uB294 \uD15C\uD50C\uB9BF \uC0AC\uC6A9 \uB610\uB294 \uAE30\uBCF8\uAC12\r\n template = script.template || this.generateDefaultTemplate(routeName);\r\n } else {\r\n // \uAC1C\uBC1C: \uAC1C\uBCC4 \uD30C\uC77C\uB4E4 \uB85C\uB4DC\r\n template = await this.loadTemplate(routeName);\r\n style = await this.loadStyle(routeName);\r\n layout = this.config.useLayout && script.layout !== null ? \r\n await this.loadLayout(script.layout || this.config.defaultLayout) : null;\r\n \r\n // \uB808\uC774\uC544\uC6C3\uACFC \uD15C\uD50C\uB9BF \uBCD1\uD569\r\n if (layout) {\r\n template = this.mergeLayoutWithTemplate(routeName, layout, template);\r\n }\r\n }\r\n \r\n // \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529 (\uC2E4\uD328\uD574\uB3C4 \uB77C\uC6B0\uD130\uB294 \uACC4\uC18D \uC791\uB3D9)\r\n let loadedComponents = {};\r\n if (this.config.useComponents && router.componentLoader) {\r\n try {\r\n loadedComponents = await router.componentLoader.loadAllComponents();\r\n this.log('debug', `Components loaded successfully for route: ${routeName}`);\r\n } catch (error) {\r\n this.log('warn', `Component loading failed for route '${routeName}', continuing without components:`, error.message);\r\n loadedComponents = {}; // \uBE48 \uAC1D\uCCB4\uB85C \uD3F4\uBC31\r\n }\r\n }\r\n\r\n // \uB2E8\uC77C \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131\r\n const component = {\r\n ...script,\r\n name: script.name || this.toPascalCase(routeName),\r\n template,\r\n components: loadedComponents,\r\n data() {\r\n const originalData = script.data ? script.data() : {};\r\n const commonData = {\r\n ...originalData,\r\n currentRoute: routeName,\r\n $query: router.queryManager?.getQueryParams() || {},\r\n $lang: (() => {\r\n try {\r\n return router.i18nManager?.getCurrentLanguage() || router.config.i18nDefaultLanguage || router.config.defaultLanguage || 'ko';\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', 'Failed to get current language:', error);\r\n return router.config.defaultLanguage || 'ko';\r\n }\r\n })(),\r\n $dataLoading: false\r\n };\r\n \r\n return commonData;\r\n },\r\n computed: {\r\n ...(script.computed || {}),\r\n // \uD558\uC704 \uD638\uD658\uC131\uC744 \uC704\uD574 params\uB294 \uC720\uC9C0\uD558\uB418 getAllParams \uC0AC\uC6A9\r\n params() {\r\n return router.queryManager?.getAllParams() || {};\r\n }\r\n },\r\n async mounted() {\r\n if (script.mounted) {\r\n await script.mounted.call(this);\r\n }\r\n if (script.dataURL) {\r\n if (typeof script.dataURL === 'string') {\r\n // \uAE30\uC874 \uB2E8\uC77C API \uBC29\uC2DD (\uD558\uC704 \uD638\uD658\uC131)\r\n await this.$fetchData();\r\n } else if (typeof script.dataURL === 'object') {\r\n // \uC0C8\uB85C\uC6B4 \uB2E4\uC911 API \uBC29\uC2DD\r\n await this.$fetchMultipleData();\r\n }\r\n }\r\n \r\n // \uD83C\uDD95 \uC790\uB3D9 \uD3FC \uBC14\uC778\uB529\r\n await this.$nextTick(); // DOM\uC774 \uC644\uC804\uD788 \uB80C\uB354\uB9C1\uB41C \uD6C4\r\n this.$bindAutoForms();\r\n },\r\n methods: {\r\n ...script.methods,\r\n // \uB77C\uC6B0\uD305 \uAD00\uB828\r\n navigateTo: (route, params) => router.navigateTo(route, params),\r\n getCurrentRoute: () => router.getCurrentRoute(),\r\n \r\n // \uD1B5\uD569\uB41C \uD30C\uB77C\uBBF8\uD130 \uAD00\uB9AC (\uB77C\uC6B0\uD305 + \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130)\r\n getParams: () => router.queryManager?.getAllParams() || {},\r\n getParam: (key, defaultValue) => router.queryManager?.getParam(key, defaultValue),\r\n \r\n // i18n \uAD00\uB828 (resilient - i18n \uC2E4\uD328\uD574\uB3C4 key \uBC18\uD658)\r\n $t: (key, params) => {\r\n try {\r\n return router.i18nManager?.t(key, params) || key;\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', 'i18n translation failed, returning key:', error);\r\n return key;\r\n }\r\n },\r\n\r\n // \uC778\uC99D \uAD00\uB828\r\n $isAuthenticated: () => router.authManager?.isUserAuthenticated() || false,\r\n $logout: () => router.authManager ? router.navigateTo(router.authManager.handleLogout()) : null,\r\n $loginSuccess: (target) => router.authManager ? router.navigateTo(router.authManager.handleLoginSuccess(target)) : null,\r\n $checkAuth: (route) => router.authManager ? router.authManager.checkAuthentication(route) : Promise.resolve({ allowed: true, reason: 'auth_disabled' }),\r\n $getToken: () => router.authManager?.getAccessToken() || null,\r\n $setToken: (token, options) => router.authManager?.setAccessToken(token, options) || false,\r\n $removeToken: (storage) => router.authManager?.removeAccessToken(storage) || null,\r\n $getAuthCookie: () => router.authManager?.getAuthCookie() || null,\r\n $getCookie: (name) => router.authManager?.getCookieValue(name) || null,\r\n \r\n // \uB370\uC774\uD130 fetch (\uB2E8\uC77C API \uB610\uB294 \uD2B9\uC815 API)\r\n async $fetchData(apiName) {\r\n if (!script.dataURL) return;\r\n \r\n this.$dataLoading = true;\r\n try {\r\n if (typeof script.dataURL === 'string') {\r\n // \uAE30\uC874 \uB2E8\uC77C API \uBC29\uC2DD\r\n const data = await router.routeLoader.fetchComponentData(script.dataURL);\r\n if (router.errorHandler) router.errorHandler.debug('RouteLoader', `Data fetched for ${routeName}:`, data);\r\n Object.assign(this, data);\r\n this.$emit('data-loaded', data);\r\n } else if (typeof script.dataURL === 'object' && apiName) {\r\n // \uD2B9\uC815 API\uB9CC \uC0C8\uB85C\uACE0\uCE68\r\n const url = script.dataURL[apiName];\r\n if (url) {\r\n const data = await router.routeLoader.fetchComponentData(url);\r\n if (router.errorHandler) router.errorHandler.debug('RouteLoader', `Data fetched for ${routeName}.${apiName}:`, data);\r\n this[apiName] = data;\r\n this.$emit('data-loaded', { [apiName]: data });\r\n }\r\n } else {\r\n // \uB2E4\uC911 API - \uC804\uCCB4 \uC0C8\uB85C\uACE0\uCE68\r\n await this.$fetchMultipleData();\r\n }\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Failed to fetch data for ${routeName}:`, error);\r\n this.$emit('data-error', error);\r\n } finally {\r\n this.$dataLoading = false;\r\n }\r\n },\r\n\r\n // \uB2E4\uC911 API \uB370\uC774\uD130 fetch\r\n async $fetchMultipleData() {\r\n if (!script.dataURL || typeof script.dataURL !== 'object') return;\r\n \r\n const dataURLs = script.dataURL;\r\n this.$dataLoading = true;\r\n \r\n try {\r\n // \uBCD1\uB82C\uB85C \uBAA8\uB4E0 API \uD638\uCD9C\r\n const promises = Object.entries(dataURLs).map(async ([key, url]) => {\r\n try {\r\n const data = await router.routeLoader.fetchComponentData(url);\r\n return { key, data, success: true };\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Failed to fetch ${key} for ${routeName}:`, error);\r\n return { key, error, success: false };\r\n }\r\n });\r\n \r\n const results = await Promise.all(promises);\r\n const successfulResults = {};\r\n const errors = {};\r\n \r\n // \uACB0\uACFC \uCC98\uB9AC\r\n results.forEach(({ key, data, error, success }) => {\r\n if (success) {\r\n this[key] = data;\r\n successfulResults[key] = data;\r\n } else {\r\n errors[key] = error;\r\n }\r\n });\r\n \r\n if (router.errorHandler) router.errorHandler.debug('RouteLoader', `Multiple data fetched for ${routeName}:`, successfulResults);\r\n \r\n // \uC774\uBCA4\uD2B8 \uBC1C\uC0DD\r\n if (Object.keys(successfulResults).length > 0) {\r\n this.$emit('data-loaded', successfulResults);\r\n }\r\n if (Object.keys(errors).length > 0) {\r\n this.$emit('data-error', errors);\r\n }\r\n \r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Failed to fetch multiple data for ${routeName}:`, error);\r\n this.$emit('data-error', error);\r\n } finally {\r\n this.$dataLoading = false;\r\n }\r\n },\r\n\r\n // \uC804\uCCB4 \uB370\uC774\uD130 \uC0C8\uB85C\uACE0\uCE68 (\uBA85\uC2DC\uC801 \uBA54\uC11C\uB4DC)\r\n async $fetchAllData() {\r\n if (typeof script.dataURL === 'string') {\r\n await this.$fetchData();\r\n } else if (typeof script.dataURL === 'object') {\r\n await this.$fetchMultipleData();\r\n }\r\n },\r\n\r\n // \uD83C\uDD95 \uC790\uB3D9 \uD3FC \uBC14\uC778\uB529 \uBA54\uC11C\uB4DC\r\n $bindAutoForms() {\r\n const forms = document.querySelectorAll('form.auto-form, form[action]');\r\n \r\n forms.forEach(form => {\r\n // \uAE30\uC874 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70 (\uC911\uBCF5 \uBC29\uC9C0)\r\n form.removeEventListener('submit', form._boundSubmitHandler);\r\n \r\n // \uC0C8 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uCD94\uAC00\r\n const boundHandler = (e) => this.$handleFormSubmit(e);\r\n form._boundSubmitHandler = boundHandler;\r\n form.addEventListener('submit', boundHandler);\r\n \r\n if (router.errorHandler) router.errorHandler.debug('RouteLoader', `Form auto-bound: ${form.getAttribute('action')}`);\r\n });\r\n },\r\n\r\n // \uD83C\uDD95 \uD3FC \uC11C\uBE0C\uBC0B \uD578\uB4E4\uB7EC\r\n async $handleFormSubmit(event) {\r\n event.preventDefault();\r\n \r\n const form = event.target;\r\n let action = form.getAttribute('action');\r\n const method = form.getAttribute('method') || 'POST';\r\n \r\n // \uD578\uB4E4\uB7EC \uD568\uC218\uB4E4 \uAC00\uC838\uC624\uAE30\r\n const successHandler = form.getAttribute('data-success-handler');\r\n const errorHandler = form.getAttribute('data-error-handler'); \r\n const loadingHandler = form.getAttribute('data-loading-handler');\r\n const redirectTo = form.getAttribute('data-redirect');\r\n\r\n try {\r\n // \uB85C\uB529 \uC2DC\uC791\r\n if (loadingHandler && this[loadingHandler]) {\r\n this[loadingHandler](true, form);\r\n }\r\n\r\n // \uD83C\uDD95 \uC561\uC158 URL\uC5D0 \uAC00\uBCC0 \uD30C\uB77C\uBBF8\uD130 \uCC98\uB9AC (\uAC04\uB2E8\uD55C \uD15C\uD50C\uB9BF \uCE58\uD658)\r\n action = this.$processActionParams(action);\r\n\r\n // \uD074\uB77C\uC774\uC5B8\uD2B8 \uC0AC\uC774\uB4DC \uAC80\uC99D\r\n if (!this.$validateForm(form)) {\r\n return;\r\n }\r\n\r\n // FormData \uC0DD\uC131\r\n const formData = new FormData(form);\r\n const data = Object.fromEntries(formData.entries());\r\n\r\n if (router.errorHandler) router.errorHandler.debug('RouteLoader', `Form submitting to: ${action}`, data);\r\n\r\n // API \uD638\uCD9C\r\n const response = await this.$submitFormData(action, method, data, form);\r\n \r\n // \uC131\uACF5 \uD578\uB4E4\uB7EC \uD638\uCD9C\r\n if (successHandler && this[successHandler]) {\r\n this[successHandler](response, form);\r\n }\r\n\r\n // \uC790\uB3D9 \uB9AC\uB2E4\uC774\uB809\uD2B8\r\n if (redirectTo) {\r\n setTimeout(() => {\r\n this.navigateTo(redirectTo);\r\n }, 1000); // 1\uCD08 \uD6C4 \uB9AC\uB2E4\uC774\uB809\uD2B8\r\n }\r\n\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Form submission error:`, error);\r\n \r\n // \uC5D0\uB7EC \uD578\uB4E4\uB7EC \uD638\uCD9C\r\n if (errorHandler && this[errorHandler]) {\r\n this[errorHandler](error, form);\r\n } else {\r\n console.error('Form submission error:', error);\r\n }\r\n } finally {\r\n // \uB85C\uB529 \uC885\uB8CC\r\n if (loadingHandler && this[loadingHandler]) {\r\n this[loadingHandler](false, form);\r\n }\r\n }\r\n },\r\n\r\n // \uD83C\uDD95 \uC561\uC158 \uD30C\uB77C\uBBF8\uD130 \uCC98\uB9AC \uBA54\uC11C\uB4DC (\uAC04\uB2E8\uD55C \uD15C\uD50C\uB9BF \uCE58\uD658)\r\n $processActionParams(actionTemplate) {\r\n let processedAction = actionTemplate;\r\n \r\n // {paramName} \uD328\uD134 \uCC3E\uAE30\r\n const paramMatches = actionTemplate.match(/\\{([^}]+)\\}/g);\r\n \r\n if (paramMatches) {\r\n paramMatches.forEach(match => {\r\n const paramName = match.slice(1, -1); // {id} -> id\r\n \r\n try {\r\n // \uCEF4\uD3EC\uB10C\uD2B8\uC758 data\uB098 computed, methods\uC5D0\uC11C \uAC12 \uCC3E\uAE30\r\n let paramValue = null;\r\n \r\n // 1. \uBA3C\uC800 getParam\uC73C\uB85C \uB77C\uC6B0\uD2B8 \uD30C\uB77C\uBBF8\uD130\uC5D0\uC11C \uCC3E\uAE30\r\n paramValue = this.getParam(paramName);\r\n \r\n // 2. \uCEF4\uD3EC\uB10C\uD2B8 data\uC5D0\uC11C \uCC3E\uAE30\r\n if (paramValue === null || paramValue === undefined) {\r\n paramValue = this[paramName];\r\n }\r\n \r\n // 3. computed \uC18D\uC131\uC5D0\uC11C \uCC3E\uAE30\r\n if (paramValue === null || paramValue === undefined) {\r\n if (this.$options.computed && this.$options.computed[paramName]) {\r\n paramValue = this[paramName];\r\n }\r\n }\r\n \r\n if (paramValue !== null && paramValue !== undefined) {\r\n // \uD15C\uD50C\uB9BF \uB300\uCCB4: {id} -> \uC2E4\uC81C\uAC12\r\n processedAction = processedAction.replace(\r\n match, \r\n encodeURIComponent(paramValue)\r\n );\r\n \r\n if (router.errorHandler) router.errorHandler.debug('RouteLoader', `Parameter resolved: ${paramName} = ${paramValue}`);\r\n } else {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Parameter '${paramName}' not found in component data, computed, or route params`);\r\n // \uD30C\uB77C\uBBF8\uD130\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC73C\uBA74 \uC6D0\uBCF8 \uADF8\uB300\uB85C \uC720\uC9C0\r\n }\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Error processing parameter '${paramName}':`, error);\r\n // \uC5D0\uB7EC\uAC00 \uBC1C\uC0DD\uD574\uB3C4 \uC6D0\uBCF8 \uADF8\uB300\uB85C \uC720\uC9C0\r\n }\r\n });\r\n }\r\n \r\n return processedAction;\r\n },\r\n\r\n\r\n // \uD83C\uDD95 \uD3FC \uB370\uC774\uD130 \uC11C\uBE0C\uBC0B\r\n async $submitFormData(action, method, data, form) {\r\n // \uD30C\uC77C \uC5C5\uB85C\uB4DC \uCCB4\uD06C\r\n const hasFile = Array.from(form.elements).some(el => el.type === 'file' && el.files.length > 0);\r\n \r\n const headers = {\r\n 'Accept': 'application/json',\r\n // \uC778\uC99D \uD1A0\uD070 \uC790\uB3D9 \uCD94\uAC00\r\n ...(this.$getToken() && {\r\n 'Authorization': `Bearer ${this.$getToken()}`\r\n })\r\n };\r\n\r\n let body;\r\n if (hasFile) {\r\n // \uD30C\uC77C\uC774 \uC788\uC73C\uBA74 FormData \uADF8\uB300\uB85C \uC804\uC1A1\r\n body = new FormData(form);\r\n // Content-Type\uC744 \uC124\uC815\uD558\uC9C0 \uC54A\uC74C (\uBE0C\uB77C\uC6B0\uC800\uAC00 \uC790\uB3D9\uC73C\uB85C multipart/form-data\uB85C \uC124\uC815)\r\n } else {\r\n // JSON\uC73C\uB85C \uC804\uC1A1\r\n headers['Content-Type'] = 'application/json';\r\n body = JSON.stringify(data);\r\n }\r\n\r\n const response = await fetch(action, {\r\n method: method.toUpperCase(),\r\n headers,\r\n body\r\n });\r\n\r\n if (!response.ok) {\r\n let error;\r\n try {\r\n error = await response.json();\r\n } catch (e) {\r\n error = { message: `HTTP ${response.status}: ${response.statusText}` };\r\n }\r\n throw new Error(error.message || `HTTP ${response.status}`);\r\n }\r\n\r\n try {\r\n return await response.json();\r\n } catch (e) {\r\n // \uC751\uB2F5\uC774 JSON\uC774 \uC544\uB2CC \uACBD\uC6B0 (\uC608: 204 No Content)\r\n return { success: true };\r\n }\r\n },\r\n\r\n // \uD83C\uDD95 \uD074\uB77C\uC774\uC5B8\uD2B8 \uC0AC\uC774\uB4DC \uD3FC \uAC80\uC99D\r\n $validateForm(form) {\r\n let isValid = true;\r\n const inputs = form.querySelectorAll('input, textarea, select');\r\n\r\n inputs.forEach(input => {\r\n // \uAE30\uBCF8 HTML5 \uAC80\uC99D\r\n if (!input.checkValidity()) {\r\n isValid = false;\r\n input.classList.add('error');\r\n return;\r\n }\r\n\r\n // \uCEE4\uC2A4\uD140 \uAC80\uC99D \uD568\uC218 \uD655\uC778\r\n const validationFunction = input.getAttribute('data-validation');\r\n if (validationFunction) {\r\n const isInputValid = this.$validateInput(input, validationFunction);\r\n if (!isInputValid) {\r\n isValid = false;\r\n input.classList.add('error');\r\n } else {\r\n input.classList.remove('error');\r\n }\r\n } else {\r\n input.classList.remove('error');\r\n }\r\n });\r\n\r\n return isValid;\r\n },\r\n\r\n // \uD83C\uDD95 \uAC1C\uBCC4 \uC785\uB825 \uAC80\uC99D\r\n $validateInput(input, validationFunction) {\r\n const value = input.value;\r\n \r\n // \uCEE4\uC2A4\uD140 \uAC80\uC99D \uD568\uC218 \uD638\uCD9C\r\n if (typeof this[validationFunction] === 'function') {\r\n try {\r\n return this[validationFunction](value, input);\r\n } catch (error) {\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Validation function '${validationFunction}' error:`, error);\r\n return false;\r\n }\r\n }\r\n \r\n // \uD568\uC218\uAC00 \uC5C6\uC73C\uBA74 true \uBC18\uD658\r\n if (router.errorHandler) router.errorHandler.warn('RouteLoader', `Validation function '${validationFunction}' not found`);\r\n return true;\r\n }\r\n },\r\n _routeName: routeName\r\n };\r\n \r\n // \uAC1C\uBC1C \uBAA8\uB4DC\uC5D0\uC11C\uB9CC \uC2A4\uD0C0\uC77C \uBA54\uD0C0\uB370\uC774\uD130 \uC800\uC7A5 (\uB80C\uB354\uB9C1 \uC2DC \uC8FC\uC785\uC6A9)\r\n if (!isProduction && style) {\r\n component._style = style;\r\n }\r\n \r\n // \uCE90\uC2DC\uC5D0 \uC800\uC7A5\r\n this.router.cacheManager?.setCache(cacheKey, component);\r\n \r\n return component;\r\n }\r\n\r\n /**\r\n * \uBB38\uC790\uC5F4\uC744 PascalCase\uB85C \uBCC0\uD658\r\n */\r\n toPascalCase(str) {\r\n return str\r\n .split(/[-_\\s]+/) // \uD558\uC774\uD508, \uC5B8\uB354\uC2A4\uCF54\uC5B4, \uACF5\uBC31\uC73C\uB85C \uBD84\uB9AC\r\n .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\r\n .join('');\r\n }\r\n\r\n /**\r\n * \uAE30\uBCF8 \uD15C\uD50C\uB9BF \uC0DD\uC131\r\n */\r\n generateDefaultTemplate(routeName) {\r\n return `<div class=\"route-${routeName}\"><h1>Route: ${routeName}</h1></div>`;\r\n }\r\n\r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8 \uB370\uC774\uD130 \uAC00\uC838\uC624\uAE30\r\n */\r\n async fetchComponentData(dataURL) {\r\n try {\r\n // \uD604\uC7AC \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130\uB97C URL\uC5D0 \uCD94\uAC00\r\n const queryString = this.router.queryManager?.buildQueryString(this.router.queryManager?.getQueryParams()) || '';\r\n const fullURL = queryString ? `${dataURL}?${queryString}` : dataURL;\r\n \r\n this.log('debug', `Fetching data from: ${fullURL}`);\r\n \r\n const response = await fetch(fullURL, {\r\n method: 'GET',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json'\r\n }\r\n });\r\n \r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n \r\n const data = await response.json();\r\n \r\n // \uB370\uC774\uD130 \uC720\uD6A8\uC131 \uAC80\uC0AC\r\n if (typeof data !== 'object' || data === null) {\r\n throw new Error('Invalid data format: expected object');\r\n }\r\n \r\n return data;\r\n \r\n } catch (error) {\r\n this.log('error', 'Failed to fetch component data:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * \uCE90\uC2DC \uBB34\uD6A8\uD654\r\n */\r\n invalidateCache(routeName) {\r\n if (this.router.cacheManager) {\r\n this.router.cacheManager.invalidateComponentCache(routeName);\r\n }\r\n this.log('debug', `Cache invalidated for route: ${routeName}`);\r\n }\r\n\r\n /**\r\n * \uD1B5\uACC4 \uC815\uBCF4 \uBC18\uD658\r\n */\r\n getStats() {\r\n return {\r\n environment: this.config.environment,\r\n srcPath: this.config.srcPath,\r\n routesPath: this.config.routesPath,\r\n useLayout: this.config.useLayout,\r\n useComponents: this.config.useComponents\r\n };\r\n }\r\n\r\n /**\r\n * \uD398\uC774\uC9C0 \uC81C\uBAA9 \uC0DD\uC131\r\n */\r\n generatePageTitle(routeName) {\r\n return this.toPascalCase(routeName).replace(/([A-Z])/g, ' $1').trim();\r\n }\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'RouteLoader', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.log('debug', 'RouteLoader destroyed');\r\n this.router = null;\r\n }\r\n}", "/**\r\n * ViewLogic Error Handling System\r\n * \uB77C\uC6B0\uD2B8 \uBC0F \uC2DC\uC2A4\uD15C \uC5D0\uB7EC \uCC98\uB9AC \uC2DC\uC2A4\uD15C\r\n */\r\nexport class ErrorHandler {\r\n constructor(router, options = {}) {\r\n this.config = {\r\n enableErrorReporting: options.enableErrorReporting !== false,\r\n debug: options.debug || false,\r\n logLevel: options.logLevel || (options.debug ? 'debug' : 'info'),\r\n environment: options.environment || 'development'\r\n };\r\n \r\n // \uB77C\uC6B0\uD130 \uC778\uC2A4\uD134\uC2A4 \uCC38\uC870\r\n this.router = router;\r\n \r\n // \uB85C\uADF8 \uB808\uBCA8 \uB9E4\uD551\r\n this.logLevels = {\r\n error: 0,\r\n warn: 1, \r\n info: 2,\r\n debug: 3\r\n };\r\n \r\n this.log('info', 'ErrorHandler', 'ErrorHandler initialized with config:', this.config);\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD2B8 \uC5D0\uB7EC \uCC98\uB9AC\r\n */\r\n async handleRouteError(routeName, error) {\r\n let errorCode = 500;\r\n let errorMessage = '\uD398\uC774\uC9C0\uB97C \uB85C\uB4DC\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.';\r\n \r\n this.debug('ErrorHandler', '\uC5D0\uB7EC \uC0C1\uC138:', error.message, error.name);\r\n \r\n // \uC5D0\uB7EC \uD0C0\uC785 \uBD84\uC11D (\uB354 \uC815\uD655\uD55C 404 \uAC10\uC9C0)\r\n if (error.message.includes('not found') || \r\n error.message.includes('404') ||\r\n error.message.includes('Failed to resolve') ||\r\n error.message.includes('Failed to fetch') ||\r\n (error.name === 'TypeError' && error.message.includes('resolve'))) {\r\n errorCode = 404;\r\n errorMessage = `'${routeName}' \uD398\uC774\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`;\r\n } else if (error.message.includes('network') && !error.message.includes('not found')) {\r\n errorCode = 503;\r\n errorMessage = '\uB124\uD2B8\uC6CC\uD06C \uC5F0\uACB0\uC744 \uD655\uC778\uD574 \uC8FC\uC138\uC694.';\r\n } else if (error.message.includes('permission') || error.message.includes('403')) {\r\n errorCode = 403;\r\n errorMessage = '\uD398\uC774\uC9C0\uC5D0 \uC811\uADFC\uD560 \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.';\r\n }\r\n \r\n this.debug('ErrorHandler', `\uC5D0\uB7EC \uCF54\uB4DC \uACB0\uC815: ${errorCode} (\uB77C\uC6B0\uD2B8: ${routeName})`);\r\n \r\n // \uC5D0\uB7EC \uB9AC\uD3EC\uD305\r\n if (this.config.enableErrorReporting) {\r\n this.reportError(routeName, error, errorCode);\r\n }\r\n \r\n try {\r\n // 404 \uD398\uC774\uC9C0 \uC804\uC6A9 \uCC98\uB9AC\r\n if (errorCode === 404) {\r\n await this.load404Page();\r\n } else {\r\n // \uC77C\uBC18 \uC5D0\uB7EC \uD398\uC774\uC9C0\r\n await this.loadErrorPage(errorCode, errorMessage);\r\n }\r\n } catch (fallbackError) {\r\n this.error('ErrorHandler', '\uC5D0\uB7EC \uD398\uC774\uC9C0 \uB85C\uB529 \uC2E4\uD328:', fallbackError);\r\n // \uBAA8\uB4E0 \uC5D0\uB7EC \uD398\uC774\uC9C0\uAC00 \uC2E4\uD328\uD588\uC744 \uB54C \uCD5C\uD6C4\uC758 \uD3F4\uBC31 \uD398\uC774\uC9C0 \uD45C\uC2DC\r\n this.showFallbackErrorPage(errorCode, errorMessage);\r\n }\r\n }\r\n\r\n /**\r\n * 404 \uD398\uC774\uC9C0 \uB85C\uB529\r\n */\r\n async load404Page() {\r\n try {\r\n this.info('ErrorHandler', 'Loading 404 page...');\r\n const component = await this.createVueComponent('404');\r\n await this.renderComponentWithTransition(component, '404');\r\n this.info('ErrorHandler', '404 page loaded successfully');\r\n } catch (error) {\r\n this.error('ErrorHandler', '404 page loading failed:', error);\r\n // 404 \uD398\uC774\uC9C0\uB3C4 \uC5C6\uC73C\uBA74 \uAC04\uB2E8\uD55C \uC5D0\uB7EC \uBA54\uC2DC\uC9C0 \uD45C\uC2DC\r\n this.showFallbackErrorPage('404', '\uD398\uC774\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.');\r\n }\r\n }\r\n\r\n /**\r\n * \uC5D0\uB7EC \uD398\uC774\uC9C0 \uB85C\uB529\r\n */\r\n async loadErrorPage(errorCode, errorMessage) {\r\n try {\r\n this.info('ErrorHandler', `Loading error page for ${errorCode}...`);\r\n \r\n // \uC5D0\uB7EC \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131\r\n const errorComponent = await this.createErrorComponent(errorCode, errorMessage);\r\n await this.renderComponentWithTransition(errorComponent, 'error');\r\n this.info('ErrorHandler', `Error page ${errorCode} loaded successfully`);\r\n } catch (error) {\r\n this.error('ErrorHandler', `Error page ${errorCode} loading failed:`, error);\r\n // \uC5D0\uB7EC \uD398\uC774\uC9C0\uB3C4 \uB85C\uB529 \uC2E4\uD328\uD558\uBA74 \uD3F4\uBC31 \uD45C\uC2DC\r\n this.showFallbackErrorPage(errorCode, errorMessage);\r\n }\r\n }\r\n\r\n /**\r\n * \uC5D0\uB7EC \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131\r\n */\r\n async createErrorComponent(errorCode, errorMessage) {\r\n try {\r\n // \uC5D0\uB7EC \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uB3D9\uC801\uC73C\uB85C \uB85C\uB4DC\r\n const component = await this.createVueComponent('error');\r\n \r\n // \uC5D0\uB7EC \uC815\uBCF4\uB97C props\uB85C \uC804\uB2EC\r\n const errorComponent = {\r\n ...component,\r\n data() {\r\n const originalData = component.data ? component.data() : {};\r\n return {\r\n ...originalData,\r\n errorCode,\r\n errorMessage,\r\n showRetry: true,\r\n showGoHome: true\r\n };\r\n }\r\n };\r\n \r\n return errorComponent;\r\n } catch (error) {\r\n // \uC5D0\uB7EC \uCEF4\uD3EC\uB10C\uD2B8\uB3C4 \uB85C\uB4DC\uD560 \uC218 \uC5C6\uB294 \uACBD\uC6B0 \uAC04\uB2E8\uD55C \uC5D0\uB7EC \uD45C\uC2DC\r\n this.error('ErrorHandler', 'Error component load failed:', error);\r\n throw new Error(`Cannot load error page: ${error.message}`);\r\n }\r\n }\r\n\r\n /**\r\n * \uD3F4\uBC31 \uC5D0\uB7EC \uD398\uC774\uC9C0 \uD45C\uC2DC (\uBAA8\uB4E0 \uC5D0\uB7EC \uD398\uC774\uC9C0\uAC00 \uC2E4\uD328\uD588\uC744 \uB54C)\r\n */\r\n showFallbackErrorPage(errorCode, errorMessage) {\r\n const appElement = document.getElementById('app');\r\n if (!appElement) return;\r\n\r\n const fallbackHTML = `\r\n <div class=\"fallback-error-page\" style=\"\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n justify-content: center;\r\n min-height: 100vh;\r\n padding: 2rem;\r\n text-align: center;\r\n background: #f8f9fa;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\r\n \">\r\n <div style=\"\r\n background: white;\r\n padding: 3rem;\r\n border-radius: 12px;\r\n box-shadow: 0 4px 20px rgba(0,0,0,0.1);\r\n max-width: 500px;\r\n \">\r\n <h1 style=\"\r\n font-size: 4rem;\r\n margin: 0;\r\n color: #dc3545;\r\n font-weight: 300;\r\n \">${errorCode}</h1>\r\n <h2 style=\"\r\n margin: 1rem 0;\r\n color: #495057;\r\n font-weight: 400;\r\n \">${errorMessage}</h2>\r\n <p style=\"\r\n color: #6c757d;\r\n margin-bottom: 2rem;\r\n line-height: 1.5;\r\n \">\uC694\uCCAD\uD558\uC2E0 \uD398\uC774\uC9C0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.</p>\r\n <button onclick=\"window.location.hash = '#/'\" style=\"\r\n background: #007bff;\r\n color: white;\r\n border: none;\r\n padding: 12px 24px;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n font-size: 1rem;\r\n transition: background 0.2s;\r\n \" onmouseover=\"this.style.background='#0056b3'\" onmouseout=\"this.style.background='#007bff'\">\r\n \uD648\uC73C\uB85C \uB3CC\uC544\uAC00\uAE30\r\n </button>\r\n </div>\r\n </div>\r\n `;\r\n\r\n // \uAE30\uC874 \uCEE8\uD14C\uC774\uB108\uB4E4 \uC815\uB9AC\r\n appElement.innerHTML = fallbackHTML;\r\n \r\n this.info('ErrorHandler', `Fallback error page displayed for ${errorCode}`);\r\n }\r\n\r\n /**\r\n * \uC5D0\uB7EC \uB9AC\uD3EC\uD305\r\n */\r\n reportError(routeName, error, errorCode) {\r\n const errorReport = {\r\n route: routeName,\r\n errorCode,\r\n errorMessage: error.message,\r\n stack: error.stack,\r\n url: window.location.href,\r\n userAgent: navigator.userAgent,\r\n timestamp: new Date().toISOString(),\r\n routerConfig: {\r\n environment: this.router.config.environment,\r\n mode: this.router.config.mode\r\n }\r\n };\r\n \r\n this.error('ErrorHandler', '\uB77C\uC6B0\uD130 \uC5D0\uB7EC \uB9AC\uD3EC\uD2B8:', errorReport);\r\n \r\n // \uCD94\uD6C4 \uC5D0\uB7EC \uCD94\uC801 \uC11C\uBE44\uC2A4\uB85C \uC804\uC1A1\uD560 \uC218 \uC788\uC74C\r\n // \uC608: analytics.track('router_error', errorReport);\r\n }\r\n\r\n /**\r\n * Vue \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131 (RouteLoader \uC704\uC784)\r\n */\r\n async createVueComponent(routeName) {\r\n if (this.router.routeLoader) {\r\n return await this.router.routeLoader.createVueComponent(routeName);\r\n }\r\n throw new Error('RouteLoader not available');\r\n }\r\n\r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8 \uB80C\uB354\uB9C1 (ViewManager \uC704\uC784)\r\n */\r\n async renderComponentWithTransition(component, routeName) {\r\n if (this.router.renderComponentWithTransition) {\r\n return await this.router.renderComponentWithTransition(component, routeName);\r\n }\r\n throw new Error('Render function not available');\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569 \uB85C\uAE45 \uC2DC\uC2A4\uD15C\r\n * @param {string} level - \uB85C\uADF8 \uB808\uBCA8 (error, warn, info, debug)\r\n * @param {string} component - \uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984 (\uC120\uD0DD\uC801)\r\n * @param {...any} args - \uB85C\uADF8 \uBA54\uC2DC\uC9C0\r\n */\r\n log(level, component, ...args) {\r\n // \uD558\uC704 \uD638\uD658\uC131: \uAE30\uC874 \uBC29\uC2DD\uB3C4 \uC9C0\uC6D0\r\n if (typeof level !== 'string' || !this.logLevels.hasOwnProperty(level)) {\r\n args = [component, ...args];\r\n component = level;\r\n level = this.config.debug ? 'debug' : 'info';\r\n }\r\n \r\n // \uB85C\uADF8 \uB808\uBCA8 \uD655\uC778\r\n const currentLevelValue = this.logLevels[this.config.logLevel] || this.logLevels.info;\r\n const messageLevelValue = this.logLevels[level] || this.logLevels.info;\r\n \r\n if (messageLevelValue > currentLevelValue) {\r\n return; // \uD604\uC7AC \uC124\uC815\uB41C \uB808\uBCA8\uBCF4\uB2E4 \uB192\uC73C\uBA74 \uCD9C\uB825 \uC548\uD568\r\n }\r\n \r\n // \uD504\uB85C\uB355\uC158 \uD658\uACBD\uC5D0\uC11C\uB294 error\uC640 warn\uB9CC \uCD9C\uB825\r\n if (this.config.environment === 'production' && messageLevelValue > this.logLevels.warn) {\r\n return;\r\n }\r\n \r\n const prefix = component ? `[${component}]` : '[ViewLogic]';\r\n const timestamp = new Date().toISOString().substring(11, 23); // HH:MM:SS.mmm\r\n \r\n switch (level) {\r\n case 'error':\r\n console.error(`${timestamp} ${prefix}`, ...args);\r\n break;\r\n case 'warn':\r\n console.warn(`${timestamp} ${prefix}`, ...args);\r\n break;\r\n case 'info':\r\n console.info(`${timestamp} ${prefix}`, ...args);\r\n break;\r\n case 'debug':\r\n console.log(`${timestamp} ${prefix}`, ...args);\r\n break;\r\n default:\r\n console.log(`${timestamp} ${prefix}`, ...args);\r\n }\r\n }\r\n \r\n /**\r\n * \uC5D0\uB7EC \uB85C\uADF8 (\uD56D\uC0C1 \uCD9C\uB825)\r\n */\r\n error(component, ...args) {\r\n this.log('error', component, ...args);\r\n }\r\n \r\n /**\r\n * \uACBD\uACE0 \uB85C\uADF8\r\n */\r\n warn(component, ...args) {\r\n this.log('warn', component, ...args);\r\n }\r\n \r\n /**\r\n * \uC815\uBCF4 \uB85C\uADF8\r\n */\r\n info(component, ...args) {\r\n this.log('info', component, ...args);\r\n }\r\n \r\n /**\r\n * \uB514\uBC84\uADF8 \uB85C\uADF8\r\n */\r\n debug(component, ...args) {\r\n this.log('debug', component, ...args);\r\n }\r\n\r\n /**\r\n * \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n this.router = null;\r\n this.info('ErrorHandler', 'ErrorHandler destroyed');\r\n }\r\n}", "/**\r\n * ComponentLoader\r\n * \uB3D9\uC801\uC73C\uB85C \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uB85C\uB4DC\uD558\uACE0 \uB4F1\uB85D\uD558\uB294 \uC2DC\uC2A4\uD15C\r\n */\r\nexport class ComponentLoader {\r\n constructor(router = null, options = {}) {\r\n\r\n this.config = {\r\n componentsPath: options.componentsPath || '/components', // srcPath \uAE30\uC900 \uC0C1\uB300 \uACBD\uB85C\r\n debug: options.debug || false,\r\n environment: options.environment || 'development',\r\n ...options\r\n };\r\n \r\n this.router = router;\r\n this.loadingPromises = new Map();\r\n this.unifiedComponents = null;\r\n }\r\n \r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.router?.errorHandler) {\r\n this.router.errorHandler.log(level, 'ComponentLoader', ...args);\r\n }\r\n }\r\n \r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8\uB97C \uBE44\uB3D9\uAE30\uB85C \uB85C\uB4DC\r\n */\r\n async loadComponent(componentName) {\r\n if (!componentName || typeof componentName !== 'string') {\r\n throw new Error('Component name must be a non-empty string');\r\n }\r\n \r\n // \uC774\uBBF8 \uB85C\uB529 \uC911\uC778 \uACBD\uC6B0 \uAE30\uC874 Promise \uBC18\uD658\r\n if (this.loadingPromises.has(componentName)) {\r\n return this.loadingPromises.get(componentName);\r\n }\r\n \r\n const loadPromise = this._loadComponentFromFile(componentName);\r\n this.loadingPromises.set(componentName, loadPromise);\r\n \r\n try {\r\n const component = await loadPromise;\r\n return component;\r\n } catch (error) {\r\n throw error;\r\n } finally {\r\n this.loadingPromises.delete(componentName);\r\n }\r\n }\r\n \r\n /**\r\n * \uD30C\uC77C\uC5D0\uC11C \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB4DC\r\n */\r\n async _loadComponentFromFile(componentName) {\r\n // srcPath + componentsPath\uB97C \uC870\uD569\uD558\uC5EC \uCEF4\uD3EC\uB10C\uD2B8 \uACBD\uB85C \uC0DD\uC131\r\n const componentRelativePath = `${this.config.componentsPath}/${componentName}.js`;\r\n \r\n let componentPath;\r\n if (this.router && this.router.config.srcPath) {\r\n // srcPath\uB294 \uC774\uBBF8 \uC804\uCCB4 URL\uC774\uBBC0\uB85C \uC9C1\uC811 \uC870\uD569\r\n const srcPath = this.router.config.srcPath;\r\n if (srcPath.startsWith('http')) {\r\n // \uC774\uC911 \uC2AC\uB798\uC2DC \uBC29\uC9C0\r\n const cleanSrcPath = srcPath.endsWith('/') ? srcPath.slice(0, -1) : srcPath;\r\n const cleanComponentPath = componentRelativePath.startsWith('/') ? componentRelativePath : `/${componentRelativePath}`;\r\n componentPath = `${cleanSrcPath}${cleanComponentPath}`;\r\n } else {\r\n componentPath = this.router.resolvePath(`${srcPath}${componentRelativePath}`);\r\n }\r\n } else {\r\n // \uD3F4\uBC31: \uAE30\uBCF8 \uACBD\uB85C \uC0AC\uC6A9\r\n componentPath = this.router ? \r\n this.router.resolvePath(`/src${componentRelativePath}`) : \r\n `/src${componentRelativePath}`;\r\n }\r\n \r\n try {\r\n const module = await import(componentPath);\r\n const component = module.default;\r\n \r\n if (!component) {\r\n throw new Error(`Component '${componentName}' has no default export`);\r\n }\r\n \r\n if (!component.name) {\r\n component.name = componentName;\r\n }\r\n \r\n this.log('debug', `Component '${componentName}' loaded successfully`);\r\n return component;\r\n \r\n } catch (error) {\r\n this.log('error', `Failed to load component '${componentName}':`, error);\r\n throw new Error(`Component '${componentName}' not found: ${error.message}`);\r\n }\r\n }\r\n \r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8 \uBAA8\uB4C8 \uD074\uB9AC\uC5B4\r\n */\r\n clearComponents() {\r\n this.loadingPromises.clear();\r\n this.unifiedComponents = null;\r\n this.log('debug', 'All components cleared');\r\n }\r\n \r\n /**\r\n * \uD658\uACBD\uC5D0 \uB530\uB978 \uBAA8\uB4E0 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529 (\uCE90\uC2F1 \uC9C0\uC6D0)\r\n */\r\n async loadAllComponents() {\r\n // \uC774\uBBF8 \uB85C\uB4DC\uB41C unifiedComponents\uAC00 \uC788\uC73C\uBA74 \uBC18\uD658\r\n if (this.unifiedComponents) {\r\n this.log('debug', 'Using existing unified components');\r\n return this.unifiedComponents;\r\n }\r\n \r\n // \uC6B4\uC601 \uBAA8\uB4DC: \uD1B5\uD569 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529 \uC2DC\uB3C4\r\n if (this.config.environment === 'production') {\r\n return await this._loadProductionComponents();\r\n }\r\n \r\n // \uAC1C\uBC1C \uBAA8\uB4DC: \uAC1C\uBCC4 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529\r\n return await this._loadDevelopmentComponents();\r\n }\r\n \r\n /**\r\n * \uC6B4\uC601 \uBAA8\uB4DC: \uD1B5\uD569 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529\r\n */\r\n async _loadProductionComponents() {\r\n try {\r\n const componentsPath = `${this.router?.config?.routesPath || '/routes'}/_components.js`;\r\n this.log('info', '[PRODUCTION] Loading unified components from:', componentsPath);\r\n \r\n const componentsModule = await import(componentsPath);\r\n \r\n if (typeof componentsModule.registerComponents === 'function') {\r\n this.unifiedComponents = componentsModule.components || {};\r\n this.log('info', `[PRODUCTION] Unified components loaded: ${Object.keys(this.unifiedComponents).length} components`);\r\n return this.unifiedComponents;\r\n } else {\r\n throw new Error('registerComponents function not found in components module');\r\n }\r\n } catch (error) {\r\n this.log('warn', '[PRODUCTION] Failed to load unified components:', error.message);\r\n this.unifiedComponents = {};\r\n return {};\r\n }\r\n }\r\n \r\n /**\r\n * \uAC1C\uBC1C \uBAA8\uB4DC: \uAC1C\uBCC4 \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB529\r\n */\r\n async _loadDevelopmentComponents() {\r\n const componentNames = this._getComponentNames();\r\n const components = {};\r\n \r\n this.log('info', `[DEVELOPMENT] Loading individual components: ${componentNames.join(', ')}`);\r\n \r\n for (const name of componentNames) {\r\n try {\r\n const component = await this.loadComponent(name);\r\n if (component) {\r\n components[name] = component;\r\n }\r\n } catch (loadError) {\r\n this.log('warn', `[DEVELOPMENT] Failed to load component ${name}:`, loadError.message);\r\n }\r\n }\r\n \r\n this.unifiedComponents = components;\r\n this.log('info', `[DEVELOPMENT] Individual components loaded: ${Object.keys(components).length} components`);\r\n return components;\r\n }\r\n \r\n /**\r\n * \uCEF4\uD3EC\uB10C\uD2B8 \uC774\uB984 \uBAA9\uB85D \uAC00\uC838\uC624\uAE30\r\n */\r\n _getComponentNames() {\r\n if (Array.isArray(this.config.componentNames) && this.config.componentNames.length > 0) {\r\n return [...this.config.componentNames];\r\n }\r\n \r\n // \uD3F4\uBC31: \uAE30\uC874 \uD558\uB4DC\uCF54\uB529 \uBAA9\uB85D\r\n return [\r\n 'Button', 'Modal', 'Card', 'Toast', 'Input', 'Tabs',\r\n 'Checkbox', 'Alert', 'DynamicInclude', 'HtmlInclude'\r\n ];\r\n }\r\n \r\n /**\r\n * \uBA54\uBAA8\uB9AC \uC815\uB9AC\r\n */\r\n dispose() {\r\n this.clearComponents();\r\n this.log('debug', 'ComponentLoader disposed');\r\n this.router = null;\r\n }\r\n}", "// ViewLogic Router - ES6 Module\r\nimport { I18nManager } from './plugins/I18nManager.js';\r\nimport { AuthManager } from './plugins/AuthManager.js';\r\nimport { CacheManager } from './plugins/CacheManager.js';\r\nimport { QueryManager } from './plugins/QueryManager.js';\r\nimport { RouteLoader } from './core/RouteLoader.js';\r\nimport { ErrorHandler } from './core/ErrorHandler.js';\r\nimport { ComponentLoader } from './core/ComponentLoader.js';\r\n\r\nexport class ViewLogicRouter {\r\n constructor(options = {}) {\r\n // \uBC84\uC804 \uC815\uBCF4\r\n this.version = options.version || '1.0.0';\r\n \r\n // \uAE30\uBCF8 \uD658\uACBD\uC124\uC815 \uCD5C\uC801\uD654\r\n this.config = this._buildConfig(options);\r\n \r\n this.currentHash = '';\r\n this.currentVueApp = null;\r\n this.previousVueApp = null; // \uC774\uC804 Vue \uC571 (\uC804\uD658 \uD6A8\uACFC\uB97C \uC704\uD574 \uBCF4\uAD00)\r\n this.componentLoader = null; // \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB354 \uC778\uC2A4\uD134\uC2A4\r\n\r\n // LoadingManager\uAC00 \uC5C6\uC744 \uB54C\uB97C \uC704\uD55C \uAE30\uBCF8 \uC804\uD658 \uC0C1\uD0DC\r\n this.transitionInProgress = false;\r\n \r\n // \uCD08\uAE30\uD654 \uC900\uBE44 \uC0C1\uD0DC\r\n this.isReady = false;\r\n this.readyPromise = null;\r\n \r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uBC14\uC778\uB529 \uCD5C\uC801\uD654\r\n this._boundHandleRouteChange = this.handleRouteChange.bind(this);\r\n \r\n // \uBAA8\uB4E0 \uCD08\uAE30\uD654\uB97C \uD55C\uBC88\uC5D0 \uCC98\uB9AC\r\n this.readyPromise = this.initialize();\r\n }\r\n\r\n /**\r\n * \uC124\uC815 \uBE4C\uB4DC (\uBD84\uB9AC\uD558\uC5EC \uAC00\uB3C5\uC131 \uD5A5\uC0C1)\r\n */\r\n _buildConfig(options) {\r\n const currentOrigin = window.location.origin;\r\n \r\n const defaults = {\r\n basePath: '/', // \uC560\uD50C\uB9AC\uCF00\uC774\uC158 \uAE30\uBCF8 \uACBD\uB85C (\uC11C\uBE0C\uD3F4\uB354 \uBC30\uD3EC\uC6A9)\r\n srcPath: '/src', // \uC18C\uC2A4 \uD30C\uC77C \uACBD\uB85C\r\n mode: 'hash',\r\n cacheMode: 'memory',\r\n cacheTTL: 300000,\r\n maxCacheSize: 50,\r\n useLayout: true,\r\n defaultLayout: 'default',\r\n environment: 'development',\r\n routesPath: '/routes', // \uD504\uB85C\uB355\uC158 \uB77C\uC6B0\uD2B8 \uACBD\uB85C\r\n enableErrorReporting: true,\r\n useComponents: true,\r\n componentNames: ['Button', 'Modal', 'Card', 'Toast', 'Input', 'Tabs', 'Checkbox', 'Alert', 'DynamicInclude', 'HtmlInclude'],\r\n useI18n: false,\r\n defaultLanguage: 'ko',\r\n i18nPath: '/i18n', // \uB2E4\uAD6D\uC5B4 \uD30C\uC77C \uACBD\uB85C\r\n logLevel: 'info',\r\n authEnabled: false,\r\n loginRoute: 'login',\r\n protectedRoutes: [],\r\n protectedPrefixes: [],\r\n publicRoutes: ['login', 'register', 'home'],\r\n checkAuthFunction: null,\r\n redirectAfterLogin: 'home',\r\n authCookieName: 'authToken',\r\n authFallbackCookieNames: ['accessToken', 'token', 'jwt'],\r\n authStorage: 'cookie',\r\n authCookieOptions: {},\r\n authSkipValidation: false,\r\n enableParameterValidation: true,\r\n maxParameterLength: 1000,\r\n maxParameterCount: 50,\r\n maxArraySize: 100,\r\n allowedKeyPattern: /^[a-zA-Z0-9_-]+$/,\r\n logSecurityWarnings: true\r\n };\r\n \r\n const config = { ...defaults, ...options };\r\n \r\n // \uC808\uB300 \uACBD\uB85C\uB4E4\uC744 basePath \uAE30\uC900\uC73C\uB85C \uD574\uACB0\r\n config.srcPath = this.resolvePath(config.srcPath, config.basePath);\r\n config.routesPath = this.resolvePath(config.routesPath, config.basePath);\r\n config.i18nPath = this.resolvePath(config.i18nPath, config.basePath);\r\n \r\n return config;\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569 \uACBD\uB85C \uD574\uACB0 - \uC11C\uBE0C\uD3F4\uB354 \uBC30\uD3EC \uBC0F basePath \uC9C0\uC6D0\r\n */\r\n resolvePath(path, basePath = null) {\r\n const currentOrigin = window.location.origin;\r\n \r\n // HTTP URL\uC778 \uACBD\uC6B0 \uADF8\uB300\uB85C \uBC18\uD658\r\n if (path.startsWith('http')) {\r\n return path;\r\n }\r\n \r\n // \uC808\uB300 \uACBD\uB85C\uC778 \uACBD\uC6B0\r\n if (path.startsWith('/')) {\r\n // basePath \uC81C\uACF5\uB41C \uACBD\uC6B0 basePath\uC640 \uC870\uD569\r\n if (basePath && basePath !== '/') {\r\n // \uC774\uC911 \uC2AC\uB798\uC2DC \uBC29\uC9C0\r\n const cleanBasePath = basePath.endsWith('/') ? basePath.slice(0, -1) : basePath;\r\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\r\n const fullPath = `${cleanBasePath}${cleanPath}`;\r\n const fullUrl = `${currentOrigin}${fullPath}`;\r\n return fullUrl.replace(/([^:])\\/{2,}/g, '$1/');\r\n }\r\n // \uC77C\uBC18\uC801\uC778 \uC808\uB300 \uACBD\uB85C\r\n return `${currentOrigin}${path}`;\r\n }\r\n \r\n // \uC0C1\uB300 \uACBD\uB85C\uC778 \uACBD\uC6B0 \uD604\uC7AC \uACBD\uB85C \uAE30\uC900\uC73C\uB85C \uD574\uACB0\r\n const currentPathname = window.location.pathname;\r\n const currentBase = currentPathname.endsWith('/') \r\n ? currentPathname \r\n : currentPathname.substring(0, currentPathname.lastIndexOf('/') + 1);\r\n \r\n // \uC0C1\uB300 \uACBD\uB85C \uC815\uADDC\uD654\r\n const resolvedPath = this.normalizePath(currentBase + path);\r\n \r\n const fullUrl = `${currentOrigin}${resolvedPath}`;\r\n \r\n // HTTP URL\uC758 \uC774\uC911 \uC2AC\uB798\uC2DC \uC81C\uAC70\r\n return fullUrl.replace(/([^:])\\/{2,}/g, '$1/');\r\n }\r\n\r\n /**\r\n * URL \uACBD\uB85C \uC815\uADDC\uD654 (\uC774\uC911 \uC2AC\uB798\uC2DC \uC81C\uAC70 \uBC0F ../, ./ \uCC98\uB9AC)\r\n */\r\n normalizePath(path) {\r\n // \uC774\uC911 \uC2AC\uB798\uC2DC \uC81C\uAC70\r\n path = path.replace(/\\/+/g, '/');\r\n const parts = path.split('/').filter(part => part !== '' && part !== '.');\r\n const stack = [];\r\n \r\n for (const part of parts) {\r\n if (part === '..') {\r\n if (stack.length > 0 && stack[stack.length - 1] !== '..') {\r\n stack.pop();\r\n } else if (!path.startsWith('/')) {\r\n stack.push(part);\r\n }\r\n } else {\r\n stack.push(part);\r\n }\r\n }\r\n \r\n const normalized = '/' + stack.join('/');\r\n return normalized === '/' ? '/' : normalized;\r\n }\r\n\r\n\r\n /**\r\n * \uB85C\uAE45 \uB798\uD37C \uBA54\uC11C\uB4DC\r\n */\r\n log(level, ...args) {\r\n if (this.errorHandler) {\r\n this.errorHandler.log(level, 'Router', ...args);\r\n }\r\n }\r\n\r\n /**\r\n * \uD1B5\uD569 \uCD08\uAE30\uD654 - \uB9E4\uB2C8\uC800 \uC0DD\uC131 \u2192 \uBE44\uB3D9\uAE30 \uB85C\uB529 \u2192 \uB77C\uC6B0\uD130 \uC2DC\uC791\r\n */\r\n async initialize() {\r\n try {\r\n // 1. \uB9E4\uB2C8\uC800 \uCD08\uAE30\uD654 (\uB3D9\uAE30)\r\n // \uD56D\uC0C1 \uD544\uC694\uD55C \uB9E4\uB2C8\uC800\uB4E4\r\n this.cacheManager = new CacheManager(this, this.config);\r\n this.routeLoader = new RouteLoader(this, this.config);\r\n this.queryManager = new QueryManager(this, this.config);\r\n this.errorHandler = new ErrorHandler(this, this.config);\r\n \r\n // \uC870\uAC74\uBD80 \uB9E4\uB2C8\uC800\uB4E4\r\n if (this.config.useI18n) {\r\n try {\r\n this.i18nManager = new I18nManager(this, this.config);\r\n if (this.i18nManager.initPromise) {\r\n await this.i18nManager.initPromise;\r\n }\r\n this.log('info', 'I18nManager initialized successfully');\r\n } catch (i18nError) {\r\n this.log('warn', 'I18nManager initialization failed, continuing without i18n:', i18nError.message);\r\n this.i18nManager = null; // i18n \uB9E4\uB2C8\uC800 \uBE44\uD65C\uC131\uD654\r\n this.config.useI18n = false; // i18n \uBE44\uD65C\uC131\uD654\r\n }\r\n }\r\n \r\n if (this.config.authEnabled) {\r\n this.authManager = new AuthManager(this, this.config);\r\n }\r\n \r\n if (this.config.useComponents) {\r\n try {\r\n this.componentLoader = new ComponentLoader(this, {\r\n ...this.config,\r\n basePath: `${this.config.basePath}/components`,\r\n cache: true,\r\n componentNames: this.config.componentNames\r\n });\r\n await this.componentLoader.loadAllComponents();\r\n this.log('info', 'ComponentLoader initialized successfully');\r\n } catch (componentError) {\r\n this.log('warn', 'ComponentLoader initialization failed, continuing without components:', componentError.message);\r\n this.componentLoader = null; // \uCEF4\uD3EC\uB10C\uD2B8 \uB85C\uB354 \uBE44\uD65C\uC131\uD654\r\n }\r\n }\r\n \r\n // 2. \uB77C\uC6B0\uD130 \uC2DC\uC791\r\n this.isReady = true;\r\n this.init();\r\n \r\n } catch (error) {\r\n this.log('error', 'Router initialization failed:', error);\r\n // \uC2E4\uD328\uD574\uB3C4 \uB77C\uC6B0\uD130\uB294 \uC2DC\uC791 (graceful degradation)\r\n this.isReady = true;\r\n this.init();\r\n }\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD130\uAC00 \uC900\uBE44\uB420 \uB54C\uAE4C\uC9C0 \uB300\uAE30\r\n */\r\n async waitForReady() {\r\n if (this.isReady) return true;\r\n if (this.readyPromise) {\r\n await this.readyPromise;\r\n }\r\n return this.isReady;\r\n }\r\n\r\n\r\n init() {\r\n const isHashMode = this.config.mode === 'hash';\r\n \r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uB4F1\uB85D (\uBA54\uBAA8\uB9AC \uCD5C\uC801\uD654)\r\n window.addEventListener(\r\n isHashMode ? 'hashchange' : 'popstate',\r\n this._boundHandleRouteChange\r\n );\r\n \r\n // DOM \uB85C\uB4DC \uCC98\uB9AC \uD1B5\uD569\r\n const initRoute = () => {\r\n if (isHashMode && !window.location.hash) {\r\n window.location.hash = '#/';\r\n } else if (!isHashMode && window.location.pathname === '/') {\r\n this.navigateTo('home');\r\n } else {\r\n this.handleRouteChange();\r\n }\r\n };\r\n \r\n if (document.readyState === 'loading') {\r\n document.addEventListener('DOMContentLoaded', initRoute);\r\n } else {\r\n // requestAnimationFrame\uC73C\uB85C \uC131\uB2A5 \uAC1C\uC120\r\n requestAnimationFrame(initRoute);\r\n }\r\n }\r\n\r\n handleRouteChange() {\r\n const { route, queryParams } = this._parseCurrentLocation();\r\n \r\n // Store current query parameters in QueryManager\r\n this.queryManager?.setCurrentQueryParams(queryParams);\r\n \r\n // \uBCC0\uACBD\uC0AC\uD56D\uC774 \uC788\uC744 \uB54C\uB9CC \uB85C\uB4DC (\uC131\uB2A5 \uCD5C\uC801\uD654)\r\n if (route !== this.currentHash || this.queryManager?.hasQueryParamsChanged(queryParams)) {\r\n this.currentHash = route;\r\n this.loadRoute(route);\r\n }\r\n }\r\n\r\n /**\r\n * \uD604\uC7AC \uC704\uCE58 \uD30C\uC2F1 (\uBD84\uB9AC\uD558\uC5EC \uAC00\uB3C5\uC131 \uD5A5\uC0C1)\r\n */\r\n _parseCurrentLocation() {\r\n if (this.config.mode === 'hash') {\r\n const hashPath = window.location.hash.slice(1) || '/';\r\n const [pathPart, queryPart] = hashPath.split('?');\r\n \r\n // \uACBD\uB85C \uD30C\uC2F1 \uCD5C\uC801\uD654\r\n let route = 'home';\r\n if (pathPart && pathPart !== '/') {\r\n route = pathPart.startsWith('/') ? pathPart.slice(1) : pathPart;\r\n }\r\n \r\n return {\r\n route: route || 'home',\r\n queryParams: this.queryManager?.parseQueryString(queryPart || window.location.search.slice(1)) || {}\r\n };\r\n } else {\r\n // History Mode - \uC11C\uBE0C\uD3F4\uB354 \uBC30\uD3EC \uC9C0\uC6D0\r\n const fullPath = window.location.pathname;\r\n const basePath = this.config.basePath || '/';\r\n \r\n // base path \uC81C\uAC70\uD558\uC5EC \uC2E4\uC81C route \uCD94\uCD9C\r\n let route = fullPath;\r\n if (basePath !== '/' && fullPath.startsWith(basePath)) {\r\n route = fullPath.slice(basePath.length);\r\n }\r\n \r\n // \uB9E8 \uC55E\uC758 / \uC81C\uAC70\r\n if (route.startsWith('/')) {\r\n route = route.slice(1);\r\n }\r\n \r\n return {\r\n route: route || 'home',\r\n queryParams: this.queryManager?.parseQueryString(window.location.search.slice(1)) || {}\r\n };\r\n }\r\n }\r\n\r\n async loadRoute(routeName) {\r\n // \uC804\uD658\uC774 \uC9C4\uD589 \uC911\uC774\uBA74 \uBB34\uC2DC\r\n const inProgress = this.transitionInProgress;\r\n \r\n if (inProgress) {\r\n return;\r\n }\r\n\r\n try {\r\n this.transitionInProgress = true;\r\n \r\n // \uC778\uC99D \uCCB4\uD06C\r\n const authResult = this.authManager ? \r\n await this.authManager.checkAuthentication(routeName) :\r\n { allowed: true, reason: 'auth_disabled' };\r\n if (!authResult.allowed) {\r\n // \uC778\uC99D \uC2E4\uD328 \uC2DC \uB85C\uADF8\uC778 \uD398\uC774\uC9C0\uB85C \uB9AC\uB2E4\uC774\uB809\uD2B8\r\n if (this.authManager) {\r\n this.authManager.emitAuthEvent('auth_required', { \r\n originalRoute: routeName,\r\n loginRoute: this.config.loginRoute \r\n });\r\n \r\n // navigateTo\uB97C \uC0AC\uC6A9\uD558\uC5EC \uC774\uC804 \uD398\uC774\uC9C0\uB85C \uB3CC\uC544\uAC00\uAE30 \uC9C0\uC6D0\r\n if (routeName !== this.config.loginRoute) {\r\n this.navigateTo(this.config.loginRoute, { redirect: routeName });\r\n } else {\r\n this.navigateTo(this.config.loginRoute);\r\n }\r\n }\r\n return;\r\n }\r\n \r\n const appElement = document.getElementById('app');\r\n if (!appElement) {\r\n throw new Error('App element not found');\r\n }\r\n\r\n // Vue \uCEF4\uD3EC\uB10C\uD2B8 \uC0DD\uC131 (\uBC31\uADF8\uB77C\uC6B4\uB4DC\uC5D0\uC11C)\r\n const component = await this.routeLoader.createVueComponent(routeName);\r\n \r\n // \uC0C8\uB85C\uC6B4 \uD398\uC774\uC9C0\uB97C \uC624\uBC84\uB808\uC774\uB85C \uB80C\uB354\uB9C1\r\n await this.renderComponentWithTransition(component, routeName);\r\n \r\n // \uB85C\uB529 \uC644\uB8CC\r\n \r\n } catch (error) {\r\n this.log('error', `Route loading failed [${routeName}]:`, error.message);\r\n \r\n \r\n // \uC5D0\uB7EC \uD0C0\uC785\uC5D0 \uB530\uB978 \uCC98\uB9AC\r\n if (this.errorHandler) {\r\n await this.errorHandler.handleRouteError(routeName, error);\r\n } else {\r\n console.error('[Router] No error handler available');\r\n }\r\n } finally {\r\n // \uBAA8\uB4E0 \uCC98\uB9AC\uAC00 \uC644\uB8CC\uB41C \uD6C4 \uC804\uD658 \uC0C1\uD0DC \uB9AC\uC14B\r\n this.transitionInProgress = false;\r\n }\r\n }\r\n\r\n async renderComponentWithTransition(vueComponent, routeName) {\r\n const appElement = document.getElementById('app');\r\n if (!appElement) return;\r\n\r\n // \uC0C8\uB85C\uC6B4 \uD398\uC774\uC9C0 \uCEE8\uD14C\uC774\uB108 \uC0DD\uC131\r\n const newPageContainer = document.createElement('div');\r\n newPageContainer.className = 'page-container page-entered';\r\n newPageContainer.id = `page-${routeName}-${Date.now()}`;\r\n \r\n // \uAE30\uC874 \uCEE8\uD14C\uC774\uB108\uAC00 \uC788\uB2E4\uBA74 \uC989\uC2DC \uC228\uAE30\uAE30\r\n const existingContainers = appElement.querySelectorAll('.page-container');\r\n existingContainers.forEach(container => {\r\n container.classList.remove('page-entered');\r\n container.classList.add('page-exiting');\r\n });\r\n\r\n // \uC0C8 \uCEE8\uD14C\uC774\uB108\uB97C \uC571\uC5D0 \uCD94\uAC00\r\n appElement.appendChild(newPageContainer);\r\n\r\n // \uAC1C\uBC1C \uBAA8\uB4DC\uC5D0\uC11C\uB9CC \uC2A4\uD0C0\uC77C \uC801\uC6A9 (\uD504\uB85C\uB355\uC158 \uBAA8\uB4DC\uB294 \uBE4C\uB4DC\uB41C JS\uC5D0\uC11C \uC790\uB3D9 \uCC98\uB9AC)\r\n if (this.config.environment === 'development' && vueComponent._style) {\r\n this.applyStyle(vueComponent._style, routeName);\r\n }\r\n \r\n // \uC0C8\uB85C\uC6B4 Vue \uC571\uC744 \uC0C8 \uCEE8\uD14C\uC774\uB108\uC5D0 \uB9C8\uC6B4\uD2B8\r\n const { createApp } = Vue;\r\n const newVueApp = createApp(vueComponent);\r\n \r\n // Vue 3 \uC804\uC5ED \uC18D\uC131 \uC124\uC815\r\n newVueApp.config.globalProperties.$router = {\r\n navigateTo: (route, params) => this.navigateTo(route, params),\r\n getCurrentRoute: () => this.getCurrentRoute(),\r\n \r\n // \uD1B5\uD569\uB41C \uD30C\uB77C\uBBF8\uD130 \uAD00\uB9AC (\uB77C\uC6B0\uD305 + \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130)\r\n getParams: () => this.queryManager?.getAllParams() || {},\r\n getParam: (key, defaultValue) => this.queryManager?.getParam(key, defaultValue),\r\n \r\n // \uCFFC\uB9AC \uD30C\uB77C\uBBF8\uD130 \uC804\uC6A9 \uBA54\uC11C\uB4DC (\uD558\uC704 \uD638\uD658\uC131)\r\n getQueryParams: () => this.queryManager?.getQueryParams() || {},\r\n getQueryParam: (key, defaultValue) => this.queryManager?.getQueryParam(key, defaultValue),\r\n setQueryParams: (params, replace) => this.queryManager?.setQueryParams(params, replace),\r\n removeQueryParams: (keys) => this.queryManager?.removeQueryParams(keys),\r\n \r\n // \uB77C\uC6B0\uD305 \uD30C\uB77C\uBBF8\uD130 \uC804\uC6A9 \uBA54\uC11C\uB4DC\r\n getRouteParams: () => this.queryManager?.getRouteParams() || {},\r\n getRouteParam: (key, defaultValue) => this.queryManager?.getRouteParam(key, defaultValue),\r\n \r\n currentRoute: this.currentHash,\r\n currentQuery: this.queryManager?.getQueryParams() || {}\r\n };\r\n\r\n // \uBAA8\uBC14\uC77C \uBA54\uB274 \uC804\uC5ED \uD568\uC218 \uCD94\uAC00\r\n\r\n newVueApp.mount(`#${newPageContainer.id}`);\r\n\r\n // requestAnimationFrame\uC73C\uB85C \uC131\uB2A5 \uAC1C\uC120\r\n requestAnimationFrame(() => {\r\n this.cleanupPreviousPages();\r\n this.transitionInProgress = false;\r\n });\r\n\r\n // \uC774\uC804 \uC571 \uC815\uB9AC \uC900\uBE44\r\n if (this.currentVueApp) {\r\n this.previousVueApp = this.currentVueApp;\r\n }\r\n \r\n this.currentVueApp = newVueApp;\r\n }\r\n\r\n cleanupPreviousPages() {\r\n const appElement = document.getElementById('app');\r\n if (!appElement) return;\r\n\r\n // \uBC30\uCE58 DOM \uC870\uC791\uC73C\uB85C \uC131\uB2A5 \uAC1C\uC120\r\n const fragment = document.createDocumentFragment();\r\n const exitingContainers = appElement.querySelectorAll('.page-container.page-exiting');\r\n \r\n // \uD55C\uBC88\uC5D0 \uC81C\uAC70\r\n exitingContainers.forEach(container => container.remove());\r\n\r\n // \uC774\uC804 Vue \uC571 \uC815\uB9AC\r\n if (this.previousVueApp) {\r\n try {\r\n this.previousVueApp.unmount();\r\n } catch (error) {\r\n // \uBB34\uC2DC (\uC774\uBBF8 \uC5B8\uB9C8\uC6B4\uD2B8\uB41C \uACBD\uC6B0)\r\n }\r\n this.previousVueApp = null;\r\n }\r\n\r\n // \uB85C\uB529 \uC5D8\uB9AC\uBA3C\uD2B8 \uC81C\uAC70\r\n \r\n appElement.querySelector('.loading')?.remove();\r\n }\r\n\r\n applyStyle(css, routeName) {\r\n // \uAE30\uC874 \uC2A4\uD0C0\uC77C \uC81C\uAC70\r\n const existing = document.querySelector(`style[data-route=\"${routeName}\"]`);\r\n if (existing) existing.remove();\r\n\r\n if (css) {\r\n const style = document.createElement('style');\r\n style.textContent = css;\r\n style.setAttribute('data-route', routeName);\r\n document.head.appendChild(style);\r\n }\r\n }\r\n\r\n\r\n navigateTo(routeName, params = null) {\r\n // If routeName is an object, treat it as {route, params}\r\n if (typeof routeName === 'object') {\r\n params = routeName.params || null;\r\n routeName = routeName.route;\r\n }\r\n \r\n // Clear current query params if navigating to a different route\r\n if (routeName !== this.currentHash && this.queryManager) {\r\n this.queryManager.clearQueryParams();\r\n }\r\n \r\n // Set route parameters\r\n if (this.queryManager) {\r\n this.queryManager.setCurrentRouteParams(params);\r\n }\r\n \r\n // Update URL with new route and params\r\n this.updateURL(routeName, params);\r\n }\r\n\r\n getCurrentRoute() {\r\n return this.currentHash;\r\n }\r\n\r\n\r\n updateURL(route, params = null) {\r\n const queryParams = params || this.queryManager?.getQueryParams() || {};\r\n const queryString = this.queryManager?.buildQueryString(queryParams) || '';\r\n \r\n // URL \uBE4C\uB4DC \uCD5C\uC801\uD654 - \uC11C\uBE0C\uD3F4\uB354 \uBC30\uD3EC \uC9C0\uC6D0\r\n const buildURL = (route, queryString, isHash = true) => {\r\n let base = route === 'home' ? '/' : `/${route}`;\r\n \r\n // History Mode\uC5D0\uC11C basePath \uACBD\uB85C \uCD94\uAC00\r\n if (!isHash && this.config.basePath && this.config.basePath !== '/') {\r\n base = `${this.config.basePath}${base}`;\r\n }\r\n \r\n const url = queryString ? `${base}?${queryString}` : base;\r\n return isHash ? `#${url}` : url;\r\n };\r\n \r\n if (this.config.mode === 'hash') {\r\n const newHash = buildURL(route, queryString);\r\n \r\n // \uB3D9\uC77C\uD55C URL\uC774\uBA74 \uC5C5\uB370\uC774\uD2B8\uD558\uC9C0 \uC54A\uC74C (\uC131\uB2A5 \uCD5C\uC801\uD654)\r\n if (window.location.hash !== newHash) {\r\n window.location.hash = newHash;\r\n }\r\n } else {\r\n const newPath = buildURL(route, queryString, false);\r\n \r\n // \uC11C\uBE0C\uD3F4\uB354 \uBC30\uD3EC\uB97C \uACE0\uB824\uD55C \uACBD\uB85C \uBE44\uAD50\r\n let expectedPath = route === 'home' ? '/' : `/${route}`;\r\n if (this.config.basePath && this.config.basePath !== '/') {\r\n expectedPath = `${this.config.basePath}${expectedPath}`;\r\n }\r\n \r\n const isSameRoute = window.location.pathname === expectedPath;\r\n \r\n if (isSameRoute) {\r\n window.history.replaceState({}, '', newPath);\r\n } else {\r\n window.history.pushState({}, '', newPath);\r\n }\r\n this.handleRouteChange();\r\n }\r\n }\r\n\r\n /**\r\n * \uB77C\uC6B0\uD130 \uC815\uB9AC (\uBA54\uBAA8\uB9AC \uB204\uC218 \uBC29\uC9C0)\r\n */\r\n destroy() {\r\n // \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70\r\n window.removeEventListener(\r\n this.config.mode === 'hash' ? 'hashchange' : 'popstate',\r\n this._boundHandleRouteChange\r\n );\r\n \r\n // \uD604\uC7AC Vue \uC571 \uC5B8\uB9C8\uC6B4\uD2B8\r\n if (this.currentVueApp) {\r\n this.currentVueApp.unmount();\r\n this.currentVueApp = null;\r\n }\r\n \r\n // \uC774\uC804 Vue \uC571 \uC5B8\uB9C8\uC6B4\uD2B8\r\n if (this.previousVueApp) {\r\n this.previousVueApp.unmount();\r\n this.previousVueApp = null;\r\n }\r\n \r\n // \uB9E4\uB2C8\uC800 \uC815\uB9AC\r\n Object.values(this).forEach(manager => {\r\n if (manager && typeof manager.destroy === 'function') {\r\n manager.destroy();\r\n }\r\n });\r\n \r\n // \uCE90\uC2DC \uD074\uB9AC\uC5B4\r\n this.cacheManager?.clearAll();\r\n \r\n // DOM \uC815\uB9AC\r\n const appElement = document.getElementById('app');\r\n if (appElement) {\r\n appElement.innerHTML = '';\r\n }\r\n \r\n this.log('info', 'Router destroyed');\r\n }\r\n}\r\n// \uC804\uC5ED \uB77C\uC6B0\uD130\uB294 index.html\uC5D0\uC11C \uD658\uACBD\uC124\uC815\uACFC \uD568\uAED8 \uC0DD\uC131\uB428"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["I18nManager", "router", "options", "error", "cachedLang", "lang", "language", "oldLanguage", "loadPromise", "messages", "emptyMessages", "cachedData", "i18nPath", "response", "fallbackError", "cacheKey", "cachedItem", "data", "timestamp", "version", "now", "maxAge", "cacheItem", "key", "params", "message", "fallbackMessages", "fallbackMessage", "obj", "path", "current", "match", "count", "pluralKey", "event", "callback", "index", "date", "locale", "number", "level", "args", "cacheKeys", "info", "AuthManager", "router", "options", "level", "args", "routeName", "isAuthenticated", "error", "token", "payload", "authCookie", "prefix", "primaryCookie", "cookieName", "cookieValue", "name", "parts", "storage", "cookieOptions", "skipValidation", "secure", "sameSite", "path", "domain", "cookieString", "expireDate", "targetRoute", "redirectRoute", "eventType", "data", "event", "listener", "listeners", "index", "CacheManager", "router", "options", "level", "args", "key", "value", "now", "oldestKey", "existingIndex", "timestamp", "index", "pattern", "keysToDelete", "routeName", "patterns", "totalInvalidated", "componentPatterns", "totalCleared", "size", "expiredKeys", "estimatedBytes", "ratio", "categories", "interval", "QueryManager", "router", "options", "level", "args", "value", "sanitized", "sqlPatterns", "pattern", "key", "dangerousPatterns", "item", "queryString", "params", "pairs", "pair", "rawKey", "rawValue", "sanitizedValue", "arrayKey", "error", "paramCount", "limitedParams", "count", "newParams", "oldKeys", "newKeys", "defaultValue", "replace", "currentParams", "sanitizedParams", "keys", "keysToRemove", "route", "RouteLoader", "router", "options", "routeName", "script", "importPath", "error", "templatePath", "response", "template", "stylePath", "style", "layoutName", "layoutPath", "layout", "result", "cacheKey", "cached", "isProduction", "loadedComponents", "component", "route", "params", "key", "defaultValue", "target", "token", "storage", "name", "apiName", "data", "url", "dataURLs", "promises", "results", "successfulResults", "errors", "success", "form", "boundHandler", "e", "event", "action", "method", "successHandler", "errorHandler", "loadingHandler", "redirectTo", "formData", "actionTemplate", "processedAction", "paramMatches", "match", "paramName", "paramValue", "hasFile", "el", "headers", "body", "isValid", "input", "validationFunction", "value", "str", "word", "dataURL", "queryString", "fullURL", "level", "args", "ErrorHandler", "router", "options", "routeName", "error", "errorCode", "errorMessage", "fallbackError", "component", "errorComponent", "appElement", "fallbackHTML", "errorReport", "level", "args", "currentLevelValue", "messageLevelValue", "prefix", "timestamp", "ComponentLoader", "router", "options", "level", "args", "componentName", "loadPromise", "error", "componentRelativePath", "componentPath", "srcPath", "cleanSrcPath", "cleanComponentPath", "component", "componentsPath", "componentsModule", "componentNames", "components", "name", "loadError", "ViewLogicRouter", "options", "currentOrigin", "config", "path", "basePath", "cleanBasePath", "cleanPath", "fullPath", "currentPathname", "currentBase", "resolvedPath", "parts", "part", "stack", "normalized", "level", "args", "CacheManager", "RouteLoader", "QueryManager", "ErrorHandler", "I18nManager", "i18nError", "AuthManager", "ComponentLoader", "componentError", "error", "isHashMode", "initRoute", "route", "queryParams", "hashPath", "pathPart", "queryPart", "routeName", "component", "vueComponent", "appElement", "newPageContainer", "container", "createApp", "newVueApp", "params", "key", "defaultValue", "replace", "keys", "fragment", "css", "existing", "style", "queryString", "buildURL", "isHash", "base", "url", "newHash", "newPath", "expectedPath", "manager"]
|
|
7
7
|
}
|