Web Programming/Ruby on Rails

Rails Cache 캐시

bale.yoon 2021. 5. 9. 12:27

Rails에서 제공하는 다양한 캐시 옵션들이 있다.

공식 문서에 이미 충분히 잘 정리되어 있지만, 그대로 읽어보고 공부하고자 한다.


Page Caching

Disk page cache가 아닌 Web page cache이다.

advtionpack-page_caching gem을 통해서 처리할 수 있으며, 파일로 처리한다.

  • 엔드포인트 E의 요청에 따라 WEB sever가 동적으로 제공하는 페이지 F를 File에다가 저장해둔다
  • 후에 E의 요청이 들어오면 Rails의 전체 stack을 거치지않고 저장한 페이지 F를 바로 제공한다.

Action Caching

Page Caching과 같은 동작을 처리하지만, Page Caching은 인증과 같은 필터 작업을 할 수 없는 반면에 Action Caching은 필터까지 같이 캐시해준다.


Fragment Caching

Dynamic Web에 대해서 특정 Fragment들에 대해서 캐시한다. 

<!-- 일반적인 캐시 -->
<% @products.each do |product| %>
  <% cache product do %>
    <%= render product %>
  <% end %>
<% end %>

<!-- 특정 조건에서의 캐시 -->
<% cache_if admin?, product do %>
  <%= render product %>
<% end %>

이렇게 저장되는 캐시들은 고유키 값을 통해 관리된다.

views/products/index:bea67108094918eeba42cd4a6e786901/products/1

 

 

Russian Doll Caching

Framgent caching 시에 모델이 가지고 있는 다른 모델들도 같이 캐시된다(마트료시카).

class Product < ApplicationRecord
  has_many :games
end

class Game < ApplicationRecord
  belongs_to :product, touch: true
end
<% cache product do %>
  <%= render product.games %>
<% end %>

 

Collection Caching

render를 사용 시, collection을 넘기게 되면 each 형태로 loop로 동작하는데, 템플릿을 캐시하여 처리할 수 있다.

<%= render partial: 'products/product', collection: @products, cached: true %>

 

Shared Partial Caching

다른 MIME type 파일 간에 캐싱한다. 

render(partial: 'hotels/hotel', collection: @hotels, cached: true)

Low Level Caching

쿼리 결과값이나, 특정 value 자체에 대해서도 캐시가 필요할 때가 있다(많은 듯 하다). 이럴 때 사용할 수 있는데, 가장 흔하고 자주 사용되는 방식이다.

class Product < ApplicationRecord
  def competing_price
    Rails.cache.fetch("#{cache_key_with_version}/competing_price", expires_in: 12.hours) do
      Competitor::API.find_price(id)
    end
  end
end

read는 key값으로 저장된  값을 읽어오고, write는 키 값으로 값을 저장한다.

fetch는 key값으로 저장된 값이 있으면 read를 수행하고, 없으면 block하여 write 한 후에 read를 수행한다.

# read
Rails.cache.read 'caching key'

# write
Rails.cache.write 'caching key', value_need_for_cache

# fetch
Rails.cache.fetch('caching key', expires_in: 10.minutes) do
  value_need_for_cache
end

참고