Redis 캐싱 전략 완벽 가이드: Look Aside부터 Write Back까지 (DB 부하 줄이기)

🎯 타겟 독자: 사용자가 몰릴 때마다 DB CPU가 100%를 치는 상황을 겪는 백엔드 개발자, Redis를 단순히 get/set으로만 쓰고 있는 주니어 엔지니어.


📝 요약: 캐시(Cache)는 성능 향상의 치트키지만, 잘못 쓰면 데이터 불일치(Inconsistency)라는 재앙을 부릅니다. 이 글에서는 가장 대중적인 Look Aside(Lazy Loading) 패턴과 쓰기 성능을 극대화하는 Write Back 패턴의 작동 원리, 장단점, 그리고 언제 무엇을 써야 하는지 명확한 기준을 제시합니다.

Redis 캐싱 전략 비교

1. 캐싱 패턴이 왜 중요한가요?

"그냥 Redis에 넣으면 되는 거 아닌가요?"라고 묻는다면 반은 맞고 반은 틀립니다. 캐시를 데이터베이스(DB)와 어떤 순서로 연동하느냐에 따라 시스템의 데이터 정합성성능이 완전히 달라지기 때문입니다.

2. 패턴 ① Look Aside (Lazy Loading) - 국룰 전략

현업에서 80% 이상 사용되는 가장 일반적인 읽기 전략입니다. 캐시를 옆(Aside)에 두고 필요할 때만 데이터를 가져옵니다.

작동 순서

  1. 앱이 데이터를 찾을 때 먼저 캐시(Redis)를 찌릅니다.
  2. 캐시에 데이터가 있으면(Cache Hit) 바로 반환합니다. (DB 부하 0)
  3. 없으면(Cache Miss) DB에서 조회하여 가져옵니다.
  4. 가져온 데이터를 캐시에 저장하고 반환합니다.
public User getUser(Long id) { // 1. 캐시 조회 User user = redisTemplate.opsForValue().get("user:" + id); if (user != null) { return user; } // 2. 캐시 미스 -> DB 조회 user = userRepository.findById(id).orElseThrow(); // 3. 캐시 저장 (TTL 설정 필수!) redisTemplate.opsForValue().set("user:" + id, user, 10, TimeUnit.MINUTES); return user; }

장점: Redis가 죽어도 DB에서 조회하면 되므로 서비스 장애로 이어지지 않음.
단점: 캐시 미스(Miss)가 발생하면 DB 조회가 일어나므로 초기 응답이 느릴 수 있음(Cache Warming 필요).

3. 패턴 ② Write Back (Write Behind) - 쓰기 성능 올인

쓰기 요청이 엄청나게 많은 서비스(예: 유튜브 조회수 카운팅, 로그 수집)에서 사용합니다.

작동 순서

  1. 모든 쓰기 작업을 캐시(Redis)에만 먼저 수행합니다.
  2. 캐시에 모인 데이터를 일정 주기(배치)로 DB에 한꺼번에 씁니다. (Bulk Insert)
⚠️ 주의: Redis가 데이터를 DB에 저장하기 전에 서버가 다운되면 데이터가 영구 소실될 수 있습니다. 절대 잃어버리면 안 되는 데이터(결제 정보 등)에는 사용하면 안 됩니다.

4. 전략 선택 가이드

패턴 적합한 상황 데이터 정합성
Look Aside 일반적인 웹 서비스 (게시판, 프로필) 높음 (결국 DB 기준)
Write Back 로그 수집, 조회수, 좋아요 수 낮음 (유실 가능성 있음)
Write Through 캐시와 DB를 동시에 씀 (데이터 일치 중요) 매우 높음 (쓰기 속도 느림)

5. 심화 문제: 캐시 쇄도(Thundering Herd)

Look Aside 패턴의 치명적인 약점입니다. 인기 있는 게시글(Hot Key)의 TTL(만료 시간)이 딱 끝나는 순간, 수천 개의 요청이 동시에 들어오면 어떻게 될까요?

수천 개의 요청이 동시에 "어? 캐시에 없네?" 하고 DB로 돌진합니다. 순간적으로 DB 부하가 폭증하여 서비스가 죽을 수 있습니다.

해결책

  • TTL 무작위화: 모든 캐시가 동시에 만료되지 않도록 TTL에 랜덤 값(Jitter)을 추가합니다.
  • Mutex Lock: 캐시 갱신은 한 번에 한 명만 하도록 락을 겁니다.

6. 결론

캐시는 잘 쓰면 약이지만 못 쓰면 독입니다. "일단 Redis에 넣자"고 하기 전에, 내 데이터가 실시간성이 중요한지(Write Back 불가), 읽기가 많은지 쓰기가 많은지를 먼저 파악하십시오. 대부분의 경우 Look Aside + 적절한 TTL 조합이면 충분합니다.

이 블로그의 인기 게시물

Docker 컨테이너 'Connection Refused' (Errno 111) 오류 해결 가이드

브라우저 렌더링 원리: Reflow와 Repaint 최적화 가이드 (CRP 심층 분석)