refactor. LRU 캐시를 사용하여 API 응답 데이터 캐싱 로직 개선
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import { LRUCache } from 'lru-cache'
|
||||||
import { usePageDataStore } from '#layers/stores/usePageDataStore'
|
import { usePageDataStore } from '#layers/stores/usePageDataStore'
|
||||||
import { useLoadingStore } from '#layers/stores/useLoadingStore'
|
import { useLoadingStore } from '#layers/stores/useLoadingStore'
|
||||||
import { commonFetch } from '#layers/utils/apiUtil'
|
import { commonFetch } from '#layers/utils/apiUtil'
|
||||||
@@ -5,6 +6,12 @@ import { getGameDomain, getPathAfterLanguage } from '#layers/utils/urlUtil'
|
|||||||
import { DEFAULT_LOCALE_CODE } from '@/i18n.config'
|
import { DEFAULT_LOCALE_CODE } from '@/i18n.config'
|
||||||
import type { PageDataResponse } from '#layers/types/api/pageData'
|
import type { PageDataResponse } from '#layers/types/api/pageData'
|
||||||
|
|
||||||
|
/** 페이지 데이터 API 응답 LRU */
|
||||||
|
const pageDataResponseCache = new LRUCache<string, PageDataResponse>({
|
||||||
|
max: 100,
|
||||||
|
ttl: 1000 * 60,
|
||||||
|
})
|
||||||
|
|
||||||
export default defineNuxtRouteMiddleware(async (to, _from) => {
|
export default defineNuxtRouteMiddleware(async (to, _from) => {
|
||||||
const runtimeConfig = useRuntimeConfig()
|
const runtimeConfig = useRuntimeConfig()
|
||||||
|
|
||||||
@@ -64,9 +71,18 @@ export default defineNuxtRouteMiddleware(async (to, _from) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pageDataResponse = (await commonFetch('GET', apiUrl, {
|
const cacheKey = `${apiUrl}:${JSON.stringify(queryParams)}`
|
||||||
query: queryParams,
|
const cached = pageDataResponseCache.get(cacheKey)
|
||||||
})) as PageDataResponse | null
|
if (cached) {
|
||||||
|
pageDataResponse = cached
|
||||||
|
} else {
|
||||||
|
pageDataResponse = (await commonFetch('GET', apiUrl, {
|
||||||
|
query: queryParams,
|
||||||
|
})) as PageDataResponse | null
|
||||||
|
if (pageDataResponse?.code === 0 && 'value' in pageDataResponse) {
|
||||||
|
pageDataResponseCache.set(cacheKey, pageDataResponse)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console.log('🚀 ~ pageData.global response:', pageDataResponse)
|
console.log('🚀 ~ pageData.global response:', pageDataResponse)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -119,7 +135,7 @@ export default defineNuxtRouteMiddleware(async (to, _from) => {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return navigateTo(`/${currentLangCode}/home`)
|
return navigateTo(`/${currentLangCode}/home`, { external: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
// [TODO]
|
// [TODO]
|
||||||
|
|||||||
@@ -61,11 +61,16 @@ function setCacheHeaders(
|
|||||||
event.node.res.setHeader('Cache-Control', cacheControl)
|
event.node.res.setHeader('Cache-Control', cacheControl)
|
||||||
}
|
}
|
||||||
|
|
||||||
const cache = new LRUCache<string, WebInspectionData>({
|
const inspectionDataCache = new LRUCache<string, WebInspectionData>({
|
||||||
max: 100, // 캐시에 저장할 최대 항목 수
|
max: 100, // 캐시에 저장할 최대 항목 수
|
||||||
ttl: 1000 * 30, // 30초 동안 캐시 유지
|
ttl: 1000 * 30, // 30초 동안 캐시 유지
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const gameDataResponseCache = new LRUCache<string, GameDataResponse>({
|
||||||
|
max: 100,
|
||||||
|
ttl: 1000 * 60, // 60초
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locale Middleware 역할 함수
|
* Locale Middleware 역할 함수
|
||||||
* URL의 언어 코드를 최종 언어로 변경하거나 추가
|
* URL의 언어 코드를 최종 언어로 변경하거나 추가
|
||||||
@@ -152,14 +157,23 @@ export default defineEventHandler(async event => {
|
|||||||
game_domain: gameDomain || '',
|
game_domain: gameDomain || '',
|
||||||
lang_code: getPathLocale(event?.node.req.url),
|
lang_code: getPathLocale(event?.node.req.url),
|
||||||
}
|
}
|
||||||
const response = await $fetch<GameDataResponse>(gameApiUrl, {
|
const gameDataCacheKey = `${gameApiUrl}:${JSON.stringify(queryParams)}`
|
||||||
query: queryParams,
|
const cachedGameData = gameDataResponseCache.get(gameDataCacheKey)
|
||||||
})
|
if (cachedGameData) {
|
||||||
|
gameDataResponse = cachedGameData
|
||||||
|
} else {
|
||||||
|
const response = await $fetch<GameDataResponse>(gameApiUrl, {
|
||||||
|
query: queryParams,
|
||||||
|
})
|
||||||
|
gameDataResponse = response
|
||||||
|
if (gameDataResponse?.code === 0 && 'value' in gameDataResponse) {
|
||||||
|
gameDataResponseCache.set(gameDataCacheKey, gameDataResponse)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gameDataResponse = response
|
gameDataLangCodes = gameDataResponse?.value?.lang_codes || null
|
||||||
gameDataLangCodes = response?.value?.lang_codes || null
|
gameDataDefaultLangCode = gameDataResponse?.value?.default_lang_code || null
|
||||||
gameDataDefaultLangCode = response?.value?.default_lang_code || null
|
gameDataIntro = gameDataResponse?.value?.intro?.page_url || ''
|
||||||
gameDataIntro = response?.value?.intro?.page_url || ''
|
|
||||||
event.context.gameDomain = gameDomain
|
event.context.gameDomain = gameDomain
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
@@ -201,7 +215,7 @@ export default defineEventHandler(async event => {
|
|||||||
let inspectionData
|
let inspectionData
|
||||||
|
|
||||||
// 3. 캐시된 데이터가 없거나 만료되었을 때만 API 호출
|
// 3. 캐시된 데이터가 없거나 만료되었을 때만 API 호출
|
||||||
const cachedData = cache.get(cacheKey)
|
const cachedData = inspectionDataCache.get(cacheKey)
|
||||||
if (cachedData) {
|
if (cachedData) {
|
||||||
inspectionData = cachedData
|
inspectionData = cachedData
|
||||||
} else {
|
} else {
|
||||||
@@ -214,7 +228,7 @@ export default defineEventHandler(async event => {
|
|||||||
})
|
})
|
||||||
inspectionData = response?.value?.inspection as WebInspectionData
|
inspectionData = response?.value?.inspection as WebInspectionData
|
||||||
if (inspectionData) {
|
if (inspectionData) {
|
||||||
cache.set(cacheKey, inspectionData) // 캐시에 저장
|
inspectionDataCache.set(cacheKey, inspectionData) // 캐시에 저장
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user