Ruby on Rails 뷰 캐싱: 성능 최적화 전략

How View Caching in Rails Works (2020)

작성자
HackerNews
발행일
2020년 10월 13일

핵심 요약

  • 1 뷰 캐싱은 Rails 애플리케이션의 뷰 렌더링 속도를 향상시켜 데이터베이스 접근 및 복잡한 로직 실행 부담을 줄이는 핵심 기법입니다.
  • 2 `cache` 헬퍼 메서드를 사용하여 전체 뷰 또는 부분 뷰를 캐싱할 수 있으며, `updated_at` 타임스탬프와 `touch: true`를 활용하여 캐시 무효화를 효율적으로 관리합니다.
  • 3 러시안 인형 캐싱(Russian doll caching)과 `cached: true` 옵션을 통해 중첩된 부분 뷰의 캐싱을 최적화하고, 동적 콘텐츠는 JavaScript 또는 부분 캐싱으로 분리하여 처리합니다.

도입

캐싱은 코드 실행 결과를 저장하여 나중에 빠르게 재사용하는 일반적인 성능 최적화 기법입니다. Rails 개발자에게는 메모이제이션, 저수준 캐싱과 함께 뷰 캐싱이 중요한 형태로 다뤄집니다. 본문에서는 Rails가 뷰를 렌더링하는 방식과 뷰 성능 저하의 원인을 분석하고, 뷰 캐싱을 통해 이러한 문제를 해결하는 방법을 구체적인 예시와 함께 설명합니다. 특히, 뷰 렌더링 시간이 ActiveRecord 쿼리 시간보다 길어질 수 있는 상황에서 뷰 캐싱의 중요성을 강조합니다.

뷰 캐싱은 뷰가 생성하는 HTML을 저장하여 재사용하는 Rails의 강력한 기능입니다. 캐시 스토어로는 개발 환경에서는 memory_store가 편리하지만, 프로덕션 환경에서는 Memcached나 Redis와 같은 독립형 캐싱 서버를 사용하는 것이 일반적입니다.

뷰 캐싱 활성화 및 기본 사용

  • config.cache_store 설정을 통해 캐시 스토어를 지정할 수 있습니다.

  • rails dev:cache 명령어로 개발 환경에서 캐싱을 쉽게 켜고 끌 수 있습니다.

  • <% cache do %> ... <% end %> 블록을 사용하여 특정 코드 블록의 결과를 캐싱합니다. 첫 로딩 시에는 블록 내부가 실행되지만, 이후에는 캐시된 결과가 즉시 반환됩니다.

캐시 무효화 전략: cache(@object)

  • 단순히 cache do를 사용하는 경우, 데이터 변경 시 캐시가 무효화되지 않아 오래된 정보가 표시될 수 있습니다.

  • cache(@user) do와 같이 모델 객체를 cache 메서드에 전달하면, 해당 모델의 updated_at 속성을 기반으로 캐시 키가 생성됩니다. 모델이 업데이트될 때마다 캐시가 자동으로 무효화되어 최신 내용이 렌더링됩니다.

러시안 인형 캐싱 (Russian Doll Caching)

  • 중첩된 모델(예: User와 Post)의 경우, 상위 모델만 캐싱하면 하위 모델이 변경되어도 캐시가 무효화되지 않는 문제가 발생합니다.

  • 이를 해결하기 위해 cache(@user) do ... <% cache(post) do %> ... <% end %> ... <% end %>와 같이 캐시 블록 안에 또 다른 캐시 블록을 중첩하여 사용합니다. 이를 러시안 인형 캐싱이라고 합니다.

  • 하위 모델이 업데이트될 때 상위 모델의 updated_at을 자동으로 갱신하려면 belongs_to 관계에 touch: true 옵션을 추가해야 합니다 (예: belongs_to :user, touch: true).

컬렉션 캐싱의 효율성

  • <%= render partial: 'posts/post', collection: @posts, cached: true %> 구문은 컬렉션의 각 항목에 대해 캐싱을 적용하며, multiget 기능을 활용하여 캐시 스토어에 대한 단일 왕복으로 여러 키/값 쌍을 읽을 수 있어 효율적입니다.

동적 페이지 콘텐츠 처리

  • 일부 페이지는 전체 페이지보다 훨씬 빠르게 변경되는 동적 콘텐츠(예: 오늘의 요일, 활동 피드)를 포함할 수 있습니다.

  • 이러한 콘텐츠를 캐싱 블록에 포함하면 캐시 무효화 빈도가 높아져 캐싱의 이점이 상쇄될 수 있습니다.

  • 해결책으로는 JavaScript를 사용하여 동적 콘텐츠를 나중에 채우는 “JavaScript sprinkles” 방식이나, 동적 콘텐츠 부분을 캐싱 블록 외부로 분리하는 방법이 있습니다.

결론

뷰 캐싱은 Rails 애플리케이션의 성능을 크게 향상시킬 수 있는 강력한 도구이지만, 신중하게 접근해야 합니다. 특히 뷰는 시스템의 여러 데이터와 상호작용하는 경향이 있어, 캐시 무효화 시점을 명확히 계획하지 않으면 복잡성이 증가할 수 있습니다. 따라서 캐싱은 성능 문제가 명확히 드러나는 부분에만 전략적으로 적용하고, 가능한 한 최소한의 범위에서 사용하는 것이 중요합니다. 다음 글에서는 ActiveRecord의 기본 캐싱 기능과 카운터 캐시(counter cache)에 대해 다룰 예정입니다.

댓글 0

댓글 작성

0/1000
정중하고 건설적인 댓글을 작성해 주세요.

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!