본문으로 건너뛰기

TimeMachine 도메인 캐싱 전략

개요

이 문서는 TimeMachine 도메인에서 Redis를 활용한 캐싱 전략을 설명합니다. 전체 캐싱 아키텍처와 설계 원칙은 Redis 캐싱 설계 가이드를 참조하세요.

캐싱 대상

TimeMachine 도메인에서는 다음 데이터를 캐싱 대상으로 합니다:

  • 사용자별 시간 오프셋: 사용자가 설정한 시간 조정값
  • 시간 컨텍스트 설정: 사용자별 시간 관련 설정
  • 시간 참조 데이터: 타임라인, 캘린더 등의 관련 데이터

캐싱 전략

1. 캐싱 패턴

TimeMachine 도메인은 Cache-Aside 패턴을 주로 사용합니다:

@Injectable()
export class TimeContextService {
constructor(
private readonly redisService: RedisService,
private readonly timeContextRepository: TimeContextRepository
) {}

async getTimeContext(userId: string): Promise<TimeContext | null> {
const cacheKey = `time:context:${userId}`;

// 캐시에서 시간 컨텍스트 조회
const cachedContext = await this.redisService.get<TimeContext>(cacheKey);
if (cachedContext) {
return cachedContext;
}

// DB에서 조회
const context = await this.timeContextRepository.findByUserId(userId);
if (!context) {
return null;
}

// 캐시에 저장 (24시간 유효)
await this.redisService.set(cacheKey, context, 86400);
return context;
}

async updateTimeContext(userId: string, context: TimeContext): Promise<void> {
// DB 업데이트
await this.timeContextRepository.save(context);

// 캐시 업데이트
const cacheKey = `time:context:${userId}`;
await this.redisService.set(cacheKey, context, 86400);
}
}

2. 키 구조

TimeMachine 도메인의 캐시 키는 다음 구조를 따릅니다:

time:context:{userId} - 사용자의 시간 컨텍스트 설정
time:offset:{userId} - 사용자의 시간 오프셋 값
time:references:{userId}:{refType} - 시간 참조 데이터

3. TTL 설정

데이터 유형TTL설명
시간 컨텍스트86400초 (24시간)사용자의 시간 설정은 자주 변경되지 않음
시간 오프셋43200초 (12시간)사용자의 시간 오프셋 값
참조 데이터3600초 (1시간)타임라인, 캘린더 등의 참조 데이터

구현 예시

시간 오프셋 관리

@Injectable()
export class TimeOffsetService {
constructor(private readonly redisService: RedisService) {}

async getTimeOffset(userId: string): Promise<number> {
const cacheKey = `time:offset:${userId}`;
const offset = await this.redisService.get(cacheKey);

// 기본값은 0 (오프셋 없음)
return offset ? parseInt(offset, 10) : 0;
}

async setTimeOffset(userId: string, offset: number): Promise<void> {
const cacheKey = `time:offset:${userId}`;
await this.redisService.set(cacheKey, offset.toString(), 43200);
}

async resetTimeOffset(userId: string): Promise<void> {
const cacheKey = `time:offset:${userId}`;
await this.redisService.del(cacheKey);
}
}

타임라인 데이터 캐싱

@Injectable()
export class TimelineService {
constructor(
private readonly redisService: RedisService,
private readonly timelineRepository: TimelineRepository
) {}

async getUserTimeline(userId: string, refType: string): Promise<TimelineData> {
const cacheKey = `time:references:${userId}:${refType}`;

// 캐시에서 조회
const cachedData = await this.redisService.get<TimelineData>(cacheKey);
if (cachedData) {
return cachedData;
}

// DB에서 조회
const timelineData = await this.timelineRepository.findUserTimeline(userId, refType);

// 캐시에 저장 (1시간)
await this.redisService.set(cacheKey, timelineData, 3600);

return timelineData;
}

async updateTimeline(userId: string, refType: string, data: TimelineData): Promise<void> {
// DB 업데이트
await this.timelineRepository.saveTimeline(userId, refType, data);

// 캐시 업데이트
const cacheKey = `time:references:${userId}:${refType}`;
await this.redisService.set(cacheKey, data, 3600);
}
}

성능 최적화

  • 최소 데이터 저장: 필요한 필드만 캐싱하여 메모리 사용량 최적화
  • 압축 활용: 대용량 타임라인 데이터의 경우 압축 알고리즘 사용
  • 느슨한 일관성: 시간 설정과 같이 자주 접근하지만 실시간성이 덜 중요한 데이터는 긴 TTL 설정

변경 이력

버전날짜작성자변경 내용
0.1.02025-04-08bok@weltcorp.com최초 작성
0.1.12025-04-08bok@weltcorp.com문서 위치 변경 (core-domains → supporting-domains)