Rails는 다양한 캐싱 메커니즘을 제공하여 개발자가 애플리케이션의 특정 부분을 효율적으로 최적화할 수 있도록 지원합니다.
1. Rails 캐싱 기본 설정
config/environments
파일을 통해 캐싱 활성화 여부를 설정하며, 프로덕션 환경에서는 기본적으로 활성화됩니다.- 캐시 스토어로는 Redis나 Memcached와 같은 분산 캐시 시스템을 활용하여 확장성을 확보할 수 있습니다.
2. 프래그먼트 캐싱 (Fragment Caching)
- 뷰의 특정 부분(예: 상품 카드, 사이드바)을 캐시하여 매번 렌더링하는 대신 저장된 결과를 재사용합니다.
- Rails 7+에서는 컬렉션 캐싱을 통해 여러 개의 부분 뷰를 한 번에 효율적으로 캐시할 수 있습니다.
cache_key_with_version
을 사용하여 레코드 업데이트 시 캐시가 자동으로 만료되도록 관리합니다.
3. 러시안 돌 캐싱 (Russian Doll Caching)
- 캐시된 프래그먼트 안에 또 다른 캐시된 프래그먼트를 중첩하는 기법입니다.
- 하위 요소가 변경될 때 상위 캐시 전체를 무효화하지 않고, 변경된 하위 요소만 업데이트하여 캐시 효율을 높입니다.
touch: true
옵션을 통해 부모 객체의 타임스탬프를 업데이트하여 캐시 의존성을 관리합니다.
4. 저수준 캐싱 (Low-Level Caching)
Rails.cache.fetch
메서드를 사용하여 뷰와 무관하게 모든 Ruby 객체(쿼리 결과, API 응답, 계산된 데이터)를 캐시합니다.- 비용이 많이 드는 계산, 외부 API 호출, 복잡한 보고서 생성 등에 유용하게 사용됩니다.
expires_in
으로 시간 기반 만료를 설정하고,race_condition_ttl
로 썬더링 허드(thundering herd) 문제를 방지할 수 있습니다.
5. 캐시 무효화 전략 (Cache Invalidation Strategies)
- 키 기반 만료: Rails의
cache_key_with_version
을 활용하여 데이터 변경 시 자동으로 캐시를 무효화합니다.touch: true
로 관련 객체에 변경 사항을 전파합니다. - 시간 기반 만료:
expires_in
옵션을 사용하여 특정 시간 후 캐시를 만료시킵니다. - 수동 무효화:
Rails.cache.delete
또는Rails.cache.delete_matched
를 사용하여 특정 캐시 키를 수동으로 삭제합니다. - 배포별 네임스페이스: 애플리케이션 버전별로 캐시 네임스페이스를 분리하여 배포 시 캐시 충돌을 방지합니다.
6. HTTP 캐싱 (HTTP Caching)
fresh_when
헬퍼를 사용하여 ETag 및 Last-Modified 헤더를 추가하여 브라우저나 CDN 레벨에서 캐싱을 활용합니다.
7. 테스트 및 모니터링
- 테스트 시
Rails.cache.clear
를 사용하여 캐싱 동작을 검증합니다. ActiveSupport::Notifications
를 통해 캐시 읽기/쓰기 이벤트를 모니터링하고, NewRelic, Skylight 같은 도구로 캐시 히트율을 추적합니다.