728x90
각 저장 방식의 특징
1. 캐시 (Memory Cache)
// 현재 구현한 방식
public usageDataCache: { [date: string]: DailyUsageData } = {};
- 가장 빠른 접근 속도 (메모리에서 직접 읽기)
- 페이지 새로고침 시 자동으로 초기화되어 최신 데이터 보장
- 구현이 간단하고 직관적
- 단점:
- 페이지를 벗어나면 데이터 손실
- 브라우저 메모리 사용량 증가
2. 로컬스토리지 (LocalStorage)
// 로컬스토리지 사용 예시
public saveToLocalStorage() {
localStorage.setItem('usageDataCache', JSON.stringify(this.usageDataCache));
}
public loadFromLocalStorage() {
const cached = localStorage.getItem('usageDataCache');
if (cached) {
this.usageDataCache = JSON.parse(cached);
}
}
- 장점:
- 브라우저를 닫아도 데이터 유지
- 용량이 큼 (5-10MB)
- 단점:
- 문자열로 변환/파싱 필요 (성능 저하)
- 오래된 데이터가 남아있을 수 있음
- 보안상 민감한 데이터 노출 위험
3. 세션스토리지 (SessionStorage)
// 세션스토리지 사용 예시
public saveToSessionStorage() {
sessionStorage.setItem('usageDataCache', JSON.stringify(this.usageDataCache));
}
- 장점:
- 탭을 닫을 때까지 데이터 유지
- 탭별로 독립적인 저장소
- 단점:
- 탭을 닫으면 데이터 손실
- 로컬스토리지와 동일한 성능 이슈
왜 캐시를 선택했는가?
1. 데이터 특성상 적합
// 사용량 데이터는 실시간성이 중요
public cacheExpiryTime: number = 5 * 60 * 1000; // 5분 만료
- 사용량 데이터는 실시간성이 중요함
- 5분만 지나도 데이터가 오래될 수 있음
- 페이지 새로고침 시 최신 데이터를 보여주는 것이 더 중요
2. 성능 최적화
// 메모리에서 직접 접근 - 매우 빠름
const cachedData = this.usageDataCache[selectedDateString];
if (cachedData) {
// 즉시 사용 가능
this.updateUsageDataForSelectedDate();
}
- 날짜 선택 시 즉시 반응 필요
- JSON 파싱/직렬화 오버헤드 없음
- 사용자 경험 향상
3. 구현 복잡도
- 복잡한 저장/로드 로직 불필요
- 에러 처리 단순화
- 디버깅 용이
다른 방식으로 구현한다면?
하이브리드 방식 (추천)
export default class ChatbotDashboardStore {
// 메모리 캐시 (빠른 접근용)
public usageDataCache: { [date: string]: DailyUsageData } = {};
// 로컬스토리지 백업 (지속성용)
public saveToLocalStorage() {
const dataToSave = {
cache: this.usageDataCache,
timestamp: Date.now(),
expiryTime: this.cacheExpiryTime
};
localStorage.setItem('usageDataCache', JSON.stringify(dataToSave));
}
public loadFromLocalStorage() {
const saved = localStorage.getItem('usageDataCache');
if (saved) {
const data = JSON.parse(saved);
const isExpired = Date.now() - data.timestamp > data.expiryTime;
if (!isExpired) {
this.usageDataCache = data.cache;
this.isCacheLoaded = true;
this.lastCacheUpdate = data.timestamp;
}
}
}
public *init() {
// 먼저 로컬스토리지에서 로드 시도
this.loadFromLocalStorage();
// 캐시가 없거나 만료되었으면 새로 로드
if (!this.isCacheLoaded || this.isCacheExpired()) {
yield this.loadWeeklyUsageData();
this.saveToLocalStorage(); // 백업 저장
}
yield this.loadUsageDataForDate();
yield this.loadUsageDataForToday();
}
}
IndexedDB 방식 (대용량 데이터용)
// IndexedDB 사용 예시 (복잡하지만 강력함)
public async saveToIndexedDB() {
const db = await this.openDB();
const tx = db.transaction(['usageData'], 'readwrite');
const store = tx.objectStore('usageData');
for (const [date, data] of Object.entries(this.usageDataCache)) {
await store.put({ date, data, timestamp: Date.now() });
}
}
세션스토리지 vs 로컬스토리지 vs 메모리 캐시 비교
구분 메모리 캐시 세션스토리지 로컬스토리지
| 구분 | 메모리 캐시 | 세션스토리지 | 로컬스토리지 |
| 저장 위치 | 메모리 | 브라우저 저장소 | 브라우저 저장소 |
| 지속성 | 페이지 새로고침 시 손실 | 탭 닫을 때까지 유지 | 브라우저 닫아도 유지 |
| 용량 | 메모리 한계 | 5-10MB | 5-10MB |
| 접근 속도 | 매우 빠름 | 빠름 | 빠름 |
| 탭 간 공유 | 불가능 | 불가능 | 가능 |
| 데이터 형식 | 객체 그대로 | 문자열 (JSON) | 문자열 (JSON) |
결론
현재 구현한 메모리 캐시가 선택된 이유:
- 사용 패턴: 사용자가 날짜를 자주 바꾸며 즉시 반응 필요
- 데이터 특성: 실시간성이 중요한 사용량 데이터
- 구현 단순성: 복잡한 저장/로드 로직 불필요
- 성능: 가장 빠른 접근 속도
만약 페이지 새로고침 후에도 데이터를 유지하고 싶다면, 위의 하이브리드 방식을 추천합니다. 이렇게 하면 메모리 캐시의 빠른 성능과 로컬스토리지의 지속성을 모두 얻을 수 있습니다.
현재 구현에서는 메모리 캐시가 가장 적합하지만, 만약 다중 탭 지원이나 페이지 새로고침 후 상태 복원이 필요하다면 세션스토리지가 좋은 선택이 될 수 있습니다.
728x90