캐싱
캐싱의 기본을 익혀 지연 시간을 줄이고, 부하를 낮추며, 대규모 환경에서 백엔드 성능을 향상시키세요.
캐싱이 존재하는 이유
캐싱은 자주 접근하는 데이터를 더 빠른 저장소에 저장하여 시스템 지연 시간과 데이터베이스 부하를 줄입니다.
- 데이터베이스는 반복해서 조회하기에는 상대적으로 느리고 비용이 많이 듭니다.
- 캐싱은 자주 접근하는 데이터를 메모리 같은 더 빠른 저장소에 저장합니다.
- 데이터가 캐시에 있으면 데이터베이스를 완전히 건너뛸 수 있습니다.
상세정보
백엔드 시스템에서는 사용자 프로필, 상품 목록, 설정 값처럼 같은 데이터를 반복해서 요청하는 경우가 많습니다. 매번 데이터베이스를 조회하면 불필요한 지연 시간이 발생하고 시스템 부하도 증가합니다.
캐싱은 자주 접근하는 데이터를 더 빠른 계층, 보통 메모리에 저장함으로써 이 문제를 해결합니다. 요청이 들어오면 시스템은 먼저 캐시를 확인합니다. 데이터가 이미 있으면 데이터베이스를 건드리지 않고 즉시 결과를 반환할 수 있습니다.
이렇게 하면 응답 시간이 크게 개선되고, 시스템에서 가장 비용이 많이 들고 제한적인 자원 중 하나인 데이터베이스에 가해지는 부담도 줄어듭니다.
높은 수준에서 보면 캐싱은 지름길처럼 동작합니다. 같은 데이터를 반복해서 다시 계산하거나 다시 가져오는 대신, 시스템은 이전에 가져온 결과를 재사용합니다.
캐시 히트 vs 캐시 미스
모든 캐시 조회는 히트(빠름) 또는 미스(데이터베이스 접근 필요) 중 하나로 끝납니다.
- 캐시 히트는 캐시에서 데이터를 즉시 반환합니다.
- 캐시 미스는 데이터베이스를 조회한 다음 결과를 저장해야 합니다.
- 시스템 성능은 높은 캐시 히트율을 달성하는 데 크게 좌우됩니다.
상세정보
요청이 도착하면 시스템은 먼저 요청된 데이터가 캐시에 있는지 확인합니다.
데이터가 발견되면 이를 캐시 히트라고 합니다. 데이터베이스 조회를 피할 수 있기 때문에 응답이 빠르게 반환됩니다. 데이터베이스 조회는 훨씬 더 느립니다.
데이터가 발견되지 않으면 이를 캐시 미스라고 합니다. 시스템은 데이터베이스를 조회해 데이터를 가져오고, 이를 캐시에 저장한 다음 응답을 반환해야 합니다.
이 패턴은 두 가지 서로 다른 경로를 만듭니다:
캐시 → 히트 → 빠른 응답
캐시 → 미스 → 데이터베이스 → 저장 → 응답
캐싱의 목표는 캐시 히트를 최대화하는 것입니다. 히트율이 높을수록 시스템은 더 빨라지고 데이터베이스의 부하도 더 낮아집니다.
수명 시간(Time-To-Live, TTL)
TTL은 데이터가 오래된 상태가 되지 않도록, 캐시에서 자동으로 제거되기 전까지 데이터가 얼마나 오래 유지되는지 제어합니다.
- TTL은 캐시된 항목의 수명을 정의합니다.
- TTL이 만료되면 데이터는 캐시에서 제거됩니다.
- 적절한 TTL은 데이터의 최신성과 성능 이점을 균형 있게 맞춥니다.
상세정보
캐시된 데이터는 영원히 남아 있을 수 없습니다. 기반 데이터가 변경될 수 있기 때문입니다. 캐시가 업데이트되지 않으면 시스템은 오래되었거나 잘못된 정보를 반환할 수 있습니다.
Time-To-Live (TTL)은 각 캐시 항목에 만료 시간을 부여하여 이 문제를 해결합니다. TTL 기간이 지나면 캐시는 데이터를 자동으로 제거합니다.
예를 들어, 상품 카탈로그는 5분 동안 캐시할 수 있고, 자주 변경되는 API 응답은 60초만 캐시할 수 있습니다.
올바른 TTL을 선택하는 것은 하나의 절충입니다. TTL이 길면 캐시 적중률이 높아져 성능이 좋아지지만, 오래된 데이터를 제공할 위험이 있습니다. TTL이 짧으면 데이터는 더 최신 상태로 유지되지만 데이터베이스 부하가 증가합니다.
TTL은 캐시의 정확성을 유지하기 위한 가장 단순하고 널리 사용되는 메커니즘 중 하나입니다.
캐시 무효화
캐시 무효화는 기본 데이터가 변경될 때 캐시된 데이터가 source of truth와 일관되게 유지되도록 보장합니다.
- 데이터베이스의 데이터가 변경되면 관련된 캐시 항목도 업데이트되거나 제거되어야 합니다.
- 무효화가 잘못되면 오래되었거나 일관되지 않은 데이터가 제공될 수 있습니다.
- 일반적인 전략에는 업데이트 후 캐시 항목을 삭제하거나 새로 고치는 방법이 포함됩니다.
상세정보
캐싱은 근본적인 문제를 도입합니다: 기본 데이터가 변경되면 캐시가 오래될 수 있습니다. 시스템이 계속 오래된 캐시 데이터를 제공하면 사용자는 잘못된 정보를 볼 수 있습니다.
캐시 무효화는 데이터베이스의 데이터가 업데이트될 때 해당 캐시 항목을 제거하거나 새로 고쳐서 이 문제를 해결합니다.
일반적인 방법은 데이터베이스 업데이트 직후 캐시 항목을 삭제하는 것입니다. 다음 요청에서는 캐시 미스가 발생하고, 데이터베이스에서 최신 데이터를 가져와 업데이트된 값을 캐시에 저장합니다.
또 다른 방법은 데이터베이스 변경과 동시에 캐시를 미리 업데이트하여 둘을 동기화 상태로 유지하는 것입니다.
어려운 점은 어떤 캐시 항목을 정확히 무효화해야 하는지 식별하는 데 있습니다. 이 과정의 실수는 분산 시스템에서 흔한 버그 원인입니다.
캐시 어사이드 패턴
캐시 어사이드 패턴은 애플리케이션이 데이터를 캐시에 언제 로드할지 직접 제어할 수 있게 해줍니다.
- 애플리케이션은 데이터베이스를 조회하기 전에 먼저 캐시를 확인합니다.
- 캐시 미스가 발생하면, 데이터는 데이터베이스에서 가져와 캐시에 저장됩니다.
- 이 방식은 캐싱 동작을 완전히 제어할 수 있게 해줍니다.
상세정보
캐시 어사이드 패턴에서는 애플리케이션이 캐시와 데이터베이스 모두와 상호작용할 책임을 집니다.
요청이 들어오면, 애플리케이션은 먼저 데이터가 캐시에 있는지 확인합니다. 있다면(캐시 히트), 데이터를 즉시 반환합니다.
데이터가 캐시에 없으면(캐시 미스), 애플리케이션은 데이터베이스를 조회해 결과를 가져오고, 이를 캐시에 저장한 다음 응답을 반환합니다.
이 방식은 단순하고 유연하기 때문에 널리 사용됩니다. 애플리케이션은 무엇을 캐시할지, 언제 캐시할지, 그리고 얼마나 오래 유지할지를 결정할 수 있습니다.
하지만 캐시가 데이터베이스와 자동으로 동기화되지 않기 때문에, 애플리케이션이 캐시 무효화와 일관성을 신중하게 처리해야 한다는 의미이기도 합니다.
Write-Through 캐싱
Write-through 캐싱은 모든 쓰기 작업마다 캐시와 데이터베이스를 함께 업데이트하여 둘을 동기화 상태로 유지합니다.
- 모든 쓰기 작업은 캐시와 데이터베이스를 모두 업데이트합니다.
- 이렇게 하면 캐시된 데이터가 항상 최신 상태로 유지됩니다.
- 대신 쓰기 지연 시간이 증가한다는 단점이 있습니다.
상세정보
write-through 캐싱에서는 데이터가 기록될 때마다 시스템이 먼저 캐시를 업데이트한 다음, 같은 데이터를 데이터베이스에 기록합니다. 이렇게 하면 두 계층이 항상 같은 값을 갖게 됩니다.
캐시가 즉시 업데이트되므로, 이후의 읽기 작업은 데이터베이스를 확인할 필요 없이 가장 최근 데이터를 반환합니다. 이는 읽기 로직을 단순하게 만들고 오래된 데이터 문제를 방지합니다.
대신 각 쓰기 작업을 두 번 수행해야 하므로 쓰기 작업이 더 느려집니다. 한 번은 캐시에, 한 번은 데이터베이스에 기록해야 하기 때문입니다. 이로 인해 지연 시간이 증가하고, 쓰기 작업이 많은 환경에서는 처리량이 감소할 수 있습니다.
또한 write-through 캐싱은 두 저장 계층을 모두 적극적으로 유지해야 하므로 더 많은 리소스를 사용할 수 있습니다. 그럼에도 불구하고 일관성이 매우 중요하고 예측 가능한 읽기 동작이 필요한 시스템에서는 유용합니다.
캐시 기술
다양한 캐싱 기술은 서로 다른 계층에서 동작하며, 지연 시간을 줄이고 백엔드 시스템의 부담을 덜어줍니다.
- Redis는 TTL 지원과 고급 데이터 구조를 갖춘 빠른 인메모리 저장소입니다.
- Memcached는 높은 처리량의 키-값 접근에 최적화된 경량 캐시입니다.
- CDN은 콘텐츠를 사용자에게 더 가까운 곳에 캐시하여 전 세계 네트워크 지연 시간을 줄입니다.
상세정보
캐싱은 시스템에서 어디에 위치하는지에 따라 서로 다른 기술을 사용해 구현됩니다.
Redis는 가장 널리 사용되는 캐싱 시스템 중 하나입니다. 데이터를 메모리에 저장하므로 매우 빠르며, TTL, 리스트, 세트 및 기타 데이터 구조 같은 기능을 지원합니다. 일반적으로 애플리케이션 수준 캐싱, 세션, 실시간 데이터에 사용됩니다.
Memcached도 또 다른 인메모리 캐시이지만, Redis보다 더 단순합니다. 빠른 키-값 저장에만 집중하며 높은 처리량에 최적화되어 있어 기본적인 캐싱 사용 사례에 효과적입니다.
더 높은 수준에서는 CDN(Content Delivery Networks)이 이미지, 비디오, HTML 같은 정적 콘텐츠를 전 세계에 분산된 서버에 캐시합니다. 이렇게 하면 데이터가 이동해야 하는 거리가 줄어들어 전 세계 사용자에게 더 나은 성능을 제공합니다.
많은 시스템에서는 이러한 기술들을 함께 사용합니다. 요청은 먼저 CDN에 도달하고, 그다음 Redis 같은 애플리케이션 캐시를 거치며, 필요할 때만 데이터베이스에 도달할 수 있습니다.
캐싱이 사용되는 곳
캐싱은 시스템의 여러 계층에 적용되어 지연 시간을 줄이고 더 깊은 구성 요소의 부하를 최소화합니다.
- 캐싱은 엣지(CDN), 애플리케이션 계층, 데이터베이스 계층에 존재합니다.
- 각 계층은 불필요한 더 깊은 요청을 막아 더 빠른 응답을 제공합니다.
- 캐시를 여러 겹으로 쌓으면 시스템 전반의 성능과 확장성이 향상됩니다.
상세정보
캐싱은 한 곳에만 국한되지 않으며, 백엔드 시스템의 여러 계층에서 사용됩니다.
엣지에서는 CDN이 정적 콘텐츠를 사용자 가까이에 캐시하여 네트워크 지연 시간을 줄입니다. 애플리케이션 계층에서는 Redis나 Memcached 같은 도구가 사용자 세션이나 API 응답처럼 자주 접근되는 데이터를 캐시합니다.
일부 데이터베이스에는 쿼리 캐싱도 포함되어 있어, 자주 실행되는 쿼리의 결과를 저장함으로써 재계산을 피합니다.
이러한 계층은 다음과 같은 계층 구조를 이룹니다:
클라이언트 → CDN → 애플리케이션 캐시 → 데이터베이스
각 계층은 요청 부하의 일부를 흡수하여, 데이터베이스는 필요한 경우에만 접근되도록 보장합니다. 이처럼 계층화된 접근 방식은 시스템을 효율적으로 확장하는 데 매우 중요합니다.
캐시의 트레이드오프
캐싱은 성능을 크게 향상시키지만, 데이터 일관성과 정확성에 대한 복잡성을 도입합니다.
- 캐싱은 지연 시간과 데이터베이스 부하를 줄여 시스템 확장성을 향상시킵니다.
- 오래된 데이터와 일관성 문제 같은 위험을 도입합니다.
- 캐시 무효화 관리는 시스템 설계에서 핵심 과제가 됩니다.
상세정보
캐싱은 시스템 성능을 개선하는 가장 효과적인 방법 중 하나입니다. 더 빠른 저장소에서 데이터를 제공함으로써, 시스템은 더 빠르게 응답할 수 있고 데이터베이스에 더 적은 부하를 주면서 훨씬 더 많은 트래픽을 처리할 수 있습니다.
하지만 이러한 성능 향상에는 트레이드오프가 따릅니다. 가장 큰 문제는 오래된 데이터입니다. 캐시된 값이 더 이상 데이터베이스의 최신 상태를 반영하지 않을 수 있습니다.
캐시와 데이터베이스 간의 일관성을 보장하려면 추가적인 복잡성이 생깁니다. 개발자는 데이터를 정확하게 유지하기 위해 무효화 전략을 신중하게 설계해야 합니다.
실무에서 캐싱은 균형의 문제입니다. 시스템은 속도와 확장성에서 큰 개선을 얻는 대신, 일정 수준의 일관성과 복잡성을 감수합니다.
질문 섹션
1 / 5
이 레슨은 프리미엄 콘텐츠입니다
프리미엄으로 업그레이드하여 흐림 효과를 없애고 전체 내용을 읽어 보세요.