글을 쓰게 된 이유
ssg.com 인턴 프로젝트 중에 추천해요의 개수를 업데이트할 때, 사용자는 여러 번 클릭할 수 있기 때문에 클릭할 때마다 업데이트 쿼리가 나가게 되면 성능이 매우 나빠질 수 있습니다. 그래서 이를 최적화하기 위해서 중간에 캐시를 둬서 주기적으로 배치를 통해 추천해요 개수를 업데이트해주는 게 어떨까라는 생각을 하게 됐습니다.
글로벌 캐시, 로컬 캐시의 차이를 공부하고 나서 프로젝트에는 어떤 캐시 플랫폼을 적용할지 알아보도록 하겠습니다.
글로벌 캐시 vs 로컬 캐시
글로벌 캐시
글로벌 캐시는 말 그대로 여러 서버에서 global하게 사용할 수 있는 캐시를 의미합니다.
즉, 캐시 서버(ex Redis)를 두고 여러 서버들이 캐시 서버를 참조하여 캐싱을 합니다.
글로벌 캐시의 장점은 여러 서버에서 캐시를 참조할 수 있기 때문에 서버 간 데이터 공유가 쉽지만,
당연히 단점으로는 네트워크를 타기 때문에 통신 비용이 발생하여 로컬 캐시보다는 느리게 됩니다.
글로벌 캐시에는 어떤 것들이 있을까?
글로벌 캐시의 종류로는 여러 가지가 있지만 대표적으로 Redis와 Memcached가 있습니다.
로컬 캐시
로컬 캐시는 서버마다 캐시를 저장하는 것입니다.
글로벌 캐시의 특징과 반대인 것이 로컬 캐시입니다. 글로벌 캐시는 캐시 서버를 따로 두지만 로컬 캐시는 로컬 서버의 리소스를 사용하며, 네트워크를 타지 않아서 속도가 빠릅니다.
하지만 글로벌 캐시에서 가능했던 다른 서버의 캐시를 참조하기 어렵습니다.
그렇다면 어떤 종류의 캐시를 사용해야할까?
현재 진행하고 있는 ssg 인턴 프로젝트에서는 단일 서버로 구성되어 있고, 애플리케이션의 규모가 그렇게 크지 않아서 글로벌 캐시를 적용하기에는 오버 엔지니어링으로 보일 수 있습니다. 그래서 저는 Spring이 제공하는 로컬 캐시를 사용하기로 했습니다.
캐시 검색 전략(cache retrieval strategy)
캐시 검색 전략이란 캐시가 데이터 요청을 처리하는 데 사용되는 방식을 결정하는 것입니다.
여러 가지 캐시 검색 전략이 있지만 크게 Read-through, Write-through, Write-back을 공부해 보겠습니다.
Read-through
우리가 일반적으로 캐시를 하면 떠오르는 검색 전략입니다.
서버 - 캐시 - DB와 같이 캐시가 애플리케이션과 DB 사이에 있으면서, 애플리케이션에서는 먼저 캐시에 데이터를 조회합니다.
만약 데이터가 캐시에 존재하지 않으면 이를 "cache miss"라 하고, DB에서 데이터를 조회하여 다음 검색을 위해 캐시에 저장하고 애플리케이션에 반환합니다.
만약 데이터가 캐시에 존재하면 이를 "cache hit"라 하고, 캐시에서 데이터를 조회해 옵니다.
그래서 cache hit가 여러 번 일어날 경우, DB 커넥션이 생기지 않기 때문에 애플리케이션 퍼포먼스가 향상됩니다.
Write-through
Write-through는 Read-through와 비슷하지만 write 연산 책임을 캐시에게 위임합니다.
즉, 서버에게 기존 데이터를 수정하거나 DB에 새로운 데이터를 추가할 때 먼저 캐시에 저장하고, 그다음 DB에 저장하게 됩니다.
그래서 캐시의 데이터는 항상 "최신" 상태로 유지할 수 있지만, 당연히 자주 쓰이지 않는 데이터에 대해서도 캐시에 저장되기 때문에 리소스가 낭비되는 단점을 가집니다.
Read-through, Write-through를 함께 사용하면 Read-through의 장점을 모두 가지면서 데이터 일관성이 보장될 수 있습니다.
Write-back
Write-back은 데이터가 "수정"될 때만 캐시에 기록됩니다. 그리고 캐시가 가득 차거나 데이터가 캐시에서 제거될 때 DB에 기록됩니다. 즉, 쓰기 지연이 생기게 됩니다.
해당 전략을 사용하게 되면 여러 번 update 될 때마다 쿼리를 날리지 않고, 모아서 한 번에 쿼리를 날릴 수 있기 때문에 DB 커넥션을 줄일 수 있습니다. 하지만 캐시가 제대로 관리되지 않는다면 데이터 손실 위험이 있습니다.
Write-through와 Write-back은 어떤 차이가 있나요?
두 전략의 공통점은 데이터 변경사항에 대해 처리하는 전략을 의미합니다.
Write-through는 캐시에 있는 데이터가 변경된다면 메인 메모리에 바로 업데이트하는 것이고,
Write-back은 캐시만 업데이트하다가 데이터가 캐시에서 삭제되거나 캐시가 가득 찰 경우 메모리에 데이터를 업데이트하는 전략입니다.
프로젝트에서는 어떻게 적용해야 할까?
현재 문제점은 추천해요 버튼을 누를 때마다 update 쿼리가 나가는 것을 해결해야 합니다.
캐시를 버퍼나 큐처럼 사용하기 위함이기 때문에 Write-back을 통해서 추천해요의 증감을 캐시에 저장하여, update 연산을 줄여주는 Write-back을 사용할 생각입니다.
결론
캐시의 종류에는 크게 글로벌 캐시, 로컬 캐시가 있는데 애플리케이션 특징에 따라서 적절한 캐시를 사용하는 것이 좋아 보입니다.
저는 규모가 작은 애플리케이션이기 때문에 로컬 캐시로도 충분히 가능할 것 같아서 spring에서 제공해 주는 로컬 캐시를 사용하려 합니다. 다음 글에서는 spring boot를 사용하여 local cache를 사용하는 방법에 대해서 학습해 보도록 하겠습니다.
REFERENCES
'Computer Network' 카테고리의 다른 글
세션 vs 쿠키 (0) | 2022.08.30 |
---|