PromleeBlog
sitemap
aboutMe

posting thumbnail
캐싱 전략 완벽 가이드 (Redis, CDN)
A Complete Guide to Caching Strategies (Redis, CDN)

📅

🚀

들어가기 전에 🔗

이번 시간에는 빠르고 쾌적한 웹 서비스를 만들기 위한 핵심 기술, 바로
캐싱(Caching)
에 대해 알아보겠습니다.
사용자가 어떤 요청을 했을 때, 그 결과를 어딘가에 '임시로 저장'해두고, 똑같은 요청이 다시 들어오면 저장해 둔 결과를 바로 돌려주는 것이 캐싱의 기본 아이디어입니다.

매번 비싼 계산을 하거나 멀리 있는 데이터를 가져오는 대신, 가까운 곳에 있는 복사본을 사용하여 응답 속도를 극적으로 향상시키는 기술입니다.
오늘은 현대 웹 아키텍처에서 가장 중요한 두 가지 캐싱 전략,
CDN
Redis
를 중심으로 캐시가 어떻게 우리의 서비스를 더 빠르게 만드는지 탐구해 보겠습니다.

🚀

반복되는 비싼 작업 🔗

캐시가 왜 필요할까요?
바로 모든 작업의 '비용'이 같지 않기 때문입니다.
어떤 작업들은 유난히 시간과 자원을 많이 소모합니다.
만약 수많은 사용자가 거의 변하지 않는 똑같은 데이터를 요청할 때마다, 우리는 이 비싼 작업을 계속해서 반복해야 합니다.

🚀

CDN (Content Delivery Network) 🔗

CDN(Content Delivery Network)
지리적으로 분산된 여러 서버
에 콘텐츠를 복사해 두고, 사용자와 가장 가까운 서버에서 콘텐츠를 제공하는 기술입니다.
주로 이미지, 동영상, CSS, JavaScript 파일과 같이 잘 변하지 않는
정적(Static) 콘텐츠
를 캐싱하는 데 사용됩니다.
비유하자면, 전 세계에 수많은 지점을 둔 거대한 프랜차이즈 카페와 같습니다.
한국에 있는 손님이 커피를 마시기 위해 미국 시애틀 본점까지 갈 필요 없이, 가까운 한국 지점에서 똑같은 품질의 커피를 바로 받아볼 수 있는 것입니다.
물리적인 거리를 단축시켜 응답 속도를 높이는 것이 핵심입니다.
동작 과정
  1. 사용자가 웹사이트의 이미지(my-image.jpg)를 요청합니다.
  2. 브라우저는 가장 가까운 CDN 서버(엣지 서버, Edge Server)로 요청을 보냅니다.
  3. 엣지 서버에 해당 이미지의 복사본(캐시)이 있으면, 즉시 사용자에게 전달합니다. (Cache Hit)
  4. 만약 복사본이 없으면, 엣지 서버가 원본 서버(Origin Server)까지 가서 이미지를 가져온 뒤, 자신에게 복사본을 저장하고 사용자에게 전달합니다. (Cache Miss)
이렇게 한 번 저장된 캐시는 다음 요청부터 빠르게 응답할 수 있게 됩니다.

🚀

Redis 🔗

CDN이 사용자와 가까운 곳에서 정적 콘텐츠를 캐싱한다면,
Redis
와 같은
인메모리(In-Memory) 캐시
는 애플리케이션(서버) 가까이에서
동적(Dynamic) 데이터
를 캐싱합니다.
Redis는 모든 데이터를 하드디스크가 아닌, 훨씬 빠른
메모리
에 저장하는 Key-Value 기반의 데이터 저장소입니다.
데이터베이스보다 월등히 빠르기 때문에, '비싼 데이터베이스 쿼리'의 결과를 임시로 저장해 두는 캐시 서버로 널리 사용됩니다.

Redis의 핵심 자료구조와 명령어 🔗

Redis는 단순한 Key-Value 저장소를 넘어, 여러 유용한 자료구조를 제공합니다.

캐시의 생명 관리: TTL (Time To Live) 🔗

캐시에 저장된 데이터는 언젠가 오래된 정보(Stale Data)가 될 수 있습니다.
이 데이터가 영원히 남아있다면, 원본 데이터베이스의 내용이 변경되어도 사용자는 계속 옛날 정보만 보게 될 것입니다.
TTL(Time To Live)
은 이 문제를 해결하기 위해 캐시 데이터에
수명 또는 유효 시간
을 설정하는 기능입니다.
설정된 시간이 지나면 해당 데이터는 Redis에서 자동으로 삭제됩니다.
TTL을 적절히 설정하는 것은 캐시 데이터의 신선도를 유지하고, 메모리를 효율적으로 관리하는 데 매우 중요합니다.

그래서 캐싱 코드는 어떻게 보일까요? 🔗

가장 널리 쓰이는
Look-aside Cache
패턴의 동작을 의사코드(Pseudo-code)로 표현하면 다음과 같습니다.
function getUserProfile(userId) {
    // 1. 먼저 캐시(Redis)를 확인합니다.
    cachedProfile = redis.get("user:" + userId + ":profile");
 
    if (cachedProfile is not null) {
        // 2. Cache Hit: 캐시에 데이터가 있으면, 바로 반환합니다.
        return cachedProfile;
    } else {
        // 3. Cache Miss: 캐시에 데이터가 없으면, 데이터베이스에서 조회합니다.
        dbProfile = database.query("SELECT * FROM users WHERE id = " + userId);
 
        // 4. 조회한 데이터를 다음을 위해 캐시에 저장합니다. (TTL 설정 포함)
        redis.setex("user:" + userId + ":profile", 3600, dbProfile); // 1시간 유효
 
        // 5. 사용자에게 데이터를 반환합니다.
        return dbProfile;
    }
}

🚀

주요 면접 예상 질문 🔗

캐싱은 시스템 성능과 직결되므로, 면접에서 그 이해도를 확인하는 질문이 자주 나옵니다.

1. CDN과 Redis(메모리 캐시)의 사용 목적은 어떻게 다른가요? 🔗

두 기술의 역할을 명확히 구분하여 설명해야 합니다.
CDN과 Redis는 해결하려는 문제의 영역이 다릅니다.
CDN
은 주로 이미지나 JS 파일 같은
정적 콘텐츠
를 사용자에게 지리적으로 가장 가까운 서버에 캐싱하여
네트워크 지연 시간을 줄이는 것
이 주 목적입니다.
반면,
Redis
는 주로 데이터베이스 조회 결과 같은
동적 데이터
를 애플리케이션 서버와 가까운 메모리에 캐싱하여,
백엔드 시스템의 처리 속도를 높이고 부하를 줄이는 것
이 주 목적입니다.

2. 캐시를 사용할 때 발생하는 데이터 불일치 문제를 어떻게 해결할 수 있나요? 🔗

캐싱의 트레이드오프와 구체적인 해결 전략을 이해하고 있는지 확인하는 심화 질문입니다.
캐시와 원본 데이터 간의 불일치 문제를
캐시 일관성
문제라고 합니다.
이를 해결하는 대표적인 전략은 두 가지가 있습니다.
첫째,
TTL(Time-To-Live)
을 사용하는 것입니다.
캐시 데이터에 유효 시간을 설정하여, 일정 시간이 지나면 자동으로 삭제되도록 만들어 데이터의 신선도를 어느 정도 보장하는 방식입니다.
둘째,
명시적 무효화(Cache Invalidation)
입니다.
데이터베이스의 원본 데이터가 변경될 때마다(UPDATE, DELETE), 관련된 캐시 데이터를 코드에서 직접 찾아 삭제하거나 갱신하는 방식입니다.
이 방식이 데이터 일관성을 더 확실하게 보장하지만, 구현이 더 복잡하다는 단점이 있습니다.

🚀

결론 🔗

오늘은 애플리케이션의 성능을 높이는 핵심 기술인 캐싱에 대해, 특히 Redis의 구체적인 활용법을 중심으로 알아보았습니다.

참고 🔗