[NestJS] 네이버 뉴스 카테고리 지정하기 (3)

2026. 3. 28. 16:11·Development/Back-end

마지막 시리즈가 될 것 같다.

이번 포스트에서는 Redis를 사용한 캐싱을 정리해볼 것이다.

 

전체 코드

@Injectable()
export class NewsCacheService {
  private readonly logger = new Logger(NewsCacheService.name);

  constructor(
    @Inject(CACHE_MANAGER) private readonly cacheManager: Cache,
    private readonly newsCrawlingService: NewsCrawlingService,
  ) {}

  private getCacheKey(category: Category): string {
    return `${CACHE_KEY_PREFIX}:${category}`;
  }

  async getByCategory(category: Category): Promise<NewsResponseDto[]> {
    const key = this.getCacheKey(category);
    const cached = await this.cacheManager.get<NewsResponseDto[]>(key);

    if (cached) {
      return cached;
    }

    await this.fetchAndCache(category);

    return (await this.cacheManager.get<NewsResponseDto[]>(key)) ?? [];
  }

  async fetchAndCache(category: Category): Promise<void> {
    const key = this.getCacheKey(category);
    const newsItems = await this.newsCrawlingService.fetchByCategory(category);
    const dtos = newsItems.map((item) => NewsResponseDto.fromNaverItem(item));
    await this.cacheManager.set(key, dtos, CACHE_TTL);
  }
}

 

크롤링 결과를 Redis 캐시에 저장/조회하는 기능을 구현하였다. 크롤링이 오래 걸리니 캐시 먼저 확인 후 없으면 크롤링 후 저장하는 구조로 구현했다.

 

const CACHE_TTL = 30 * 60 * 1000; // 30분 (ms)
const CACHE_KEY_PREFIX = 'news';

 

상수로 ttl와 key prefix를 분리해 관리하였다. v5+ 부터 ttl은 밀리세컨드를 사용한다.

 

constructor(
    @Inject(CACHE_MANAGER) private readonly cacheManager: Cache,
    private readonly newsCrawlingService: NewsCrawlingService,
  ) {}

 

@Inject(CACHE_MANAGER) 는 NestJS가 캐시 모듈을 주입할 때 쓰는 토큰이다. 일반 @Injectable()과 달리 토큰 기반 주입이라 @Inject가 필요하다.

 

private getCacheKey(category: Category): string {
  return `${CACHE_KEY_PREFIX}:${category}`;
}

 

카테고리별로 독립된 캐시를 가진다. 예를 들어 category가 'politics' 면,  키: "news:politics" 이다.

 

async getByCategory(category: Category): Promise<NewsResponseDto[]> {
  const key = this.getCacheKey(category);
  const cached = await this.cacheManager.get<NewsResponseDto[]>(key);

  if (cached) {
    return cached; // 캐시 히트 → 즉시 반환
  }

  // 캐시 미스 → 크롤링 후 캐시 저장
  await this.fetchAndCache(category);

  return (await this.cacheManager.get<NewsResponseDto[]>(key)) ?? [];
}

 

캐시를 확인하고 있으면 데이터를 반환한다. 없다면 fetchAndCache를 실행한 후 다시 조회하여 반환한다. 

 

async fetchAndCache(category: Category): Promise<void> {
  const key = this.getCacheKey(category);
  const newsItems = await this.newsCrawlingService.fetchByCategory(category);
  const dtos = newsItems.map((item) => NewsResponseDto.fromNaverItem(item));
  await this.cacheManager.set(key, dtos, CACHE_TTL);
}

 

fetchByCategory()를 호출하여 크롤링한 네이버 뉴스 데이터를 수집하고, Redis에 30분 TTL로 저장한다.

 

잔여 한계

TTL 만료 후 첫 요청은 크롤링 시간만큼 지연이 발생한다. 트래픽 증가 시 TTL 만료 전 백그라운드 갱신 스케줄러 도입을 검토할 수 있으나, 현재 규모에서는 API 비용과 서버 부하를 고려해 현행 방식을 유지하려고 한다.!

 

감사합니다 (^^ゞ

'Development > Back-end' 카테고리의 다른 글

[NestJS] 네이버 뉴스 카테고리 지정하기 (2)  (0) 2026.03.28
[NestJS] 네이버 뉴스 카테고리 지정하기 (1)  (0) 2026.03.28
[NestJS] Pipe 사용하기  (1) 2026.02.26
[Spring Boot] 어댑터 패턴 구현하기(with. JPA, Redis)  (0) 2025.12.26
[Spring Boot] @Data 알고 쓰기  (0) 2025.11.26
'Development/Back-end' 카테고리의 다른 글
  • [NestJS] 네이버 뉴스 카테고리 지정하기 (2)
  • [NestJS] 네이버 뉴스 카테고리 지정하기 (1)
  • [NestJS] Pipe 사용하기
  • [Spring Boot] 어댑터 패턴 구현하기(with. JPA, Redis)
knhye
knhye
  • 전체
    오늘
    어제
  • knhye
    3n1hye_
    knhye
  • 링크

    • GitHub
    • 분류 전체보기 (61)
      • Development (28)
        • Back-end (21)
        • DB (3)
        • CS (4)
      • Algorithm (6)
      • DevOps (10)
        • git (1)
        • Cloud Platform (5)
        • CICD (1)
        • Cloud Native (2)
      • Internet (2)
      • 매일메일 (6)
      • 회고 (5)
        • Capstone (2)
        • Hackathon (1)
        • 2025 (2)
      • 자격증 (1)
      • 블로그 리딩 (3)
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
knhye
[NestJS] 네이버 뉴스 카테고리 지정하기 (3)
상단으로

티스토리툴바