캐시(cache) 는 저장소나 숨겨진 보관 장소를 의미하는 프랑스어에서 유래 되었습니다.
컴퓨터 과학에서 이 용어는 데이터를 임시로 저장하여 빠르게 접근할 수 있는 메커니즘을 설명하는데 사용 됩니다.
캐시는 서버, 컴퓨터, 애플리케이션, 웹 브라우저 등 다양한 환경에서 성능 향상을 위해 활용됩니다.
캐시는 편의점과 마트에서 물건을 사는 것과 유사한 역할을 합니다. 편의점은 가까운 곳에서 빠르게 물건을 구매할 수 있지만 가격이 높은 반면 마트는 더 저렴하지만 거리가 멀 수 있습니다. 이처럼 캐시 저장소는 비용이 비싸지만 사용자와 가까워 데이터를 빠르게 조회할 수 있습니다. 다음은 일반적인 캐시의 동작 과정입니다.
- 사용자가 데이터를 요청
- 서버는 캐시 저장소를 우선순위로 두고 데이터 조회
- 캐시 저장소에 조회된 데이터가 있다면 반환
- 캐시 저장소이 데이터가 없다면 원본 저장소에서 데이터를 조회
- 조회된 데이터를 캐시 저장소에 저장한 후 반환
CDN(Content Delivery Network)이란 구글이나 페이스북과 같은 대규모 서비스의 데이터를 사용자의 거주지와 가까운 서버에 임시 저장하여 제공하는 프록시 서버 네트워크를 의미합니다.
네트워크의 물리적 거리가 멀고 트래픽이 증가할수롣 데이터 응답 속도가 느려질 수 있습니다.
이를 해결하기 위해 CDN은 전 세계 여러 지역에 분산된 서버를 활용하여 웹 콘텐츠(이미지, 영상, CSS, JavaScript 등)를 사용자와 가까운 서버에서 제공함으로써 전송 속도를 향상시키고 서버 부하를 줄이며 사용자 경험을 개선하는 역할을 합니다.
CPU는 실행할 명령어를 RAM에서 가져오지만 속도가 상대적으로 느려 연산 효율이 떨어질 수 있습니다.
이를 해결하기 위해 CPU 캐시가 사용됩니다.
CPU 캐시는 자주 사용되는 명령어를 CPU 내부 메모리(SRAM) 에 저장해 두고 필요할 때 빠르게 가져와 처리합니다.
캐시 저장소는 CPU 코어와의 거리와 속도에 따라 여러 계층으로 나뉩니다.
일반적으로 L1, L2, L3 캐시로 구분되며 가까울수록 빠르지만 용량이 작고 멀어질수록 속도는 느리지만 용량이 커집니다.
웹 브라우저 캐시(Web Browser Cache)는 웹 페이지나 웹 자원의 일부 데이터를 브라우저에 저장해 두는 기능으로 사용자가 동일한 웹사이트를 다시 방문할 때 더 빠르게 페이지를 로드할 수 있도록 도와줍니다.
웹 브라우저는 자주 사용하는 이미지, HTML 파일, CSS, JavaScript 파일 등을 캐시에 저장해 두고 이러한 파일을 서버에서 다시 다운로드하는 대신 로컬에서 빠르게 로드합니다.
백엔드 서비스에서 가장 큰 비용을 차지하는 것은 데이터베이스와 외부 API 호출 등에서 발생하는 네트워크 비용입니다. 백엔드 캐시는 자주 변경되지 않는 외부 호출 데이터를 저장하여 관리함으로써 데이터베이스 부하를 줄이고 사용자 경험을 향상시킬 수 있습니다.
백엔드 캐시는 로컬 캐시와 전역 캐시로 구분됩니다.
로컬 캐시는 백엔드 서버에 캐시 저장소를 두는 방법입니다. ehCache와 Caffeine이 이에 해당하며 전역 캐시보다 네트워크 비용이 적어 더 높은 성능을 발휘합니다. 그러나 각 서버마다 별개의 캐시 저장소가 있어 분산된 서버의 데이터 정합성을 관리하기 어렵다는 단점이 있습니다.
대표적인 로컬 캐시로는 ehCache와 Caffeine이 있습니다.
ehCache는 JVM Heap, 메모리, 디스크 중 하나를 캐시 저장소로 선택할 수 있습니다. 기본값은 JVM Heap이며 JVM 영역 밖에서 캐시를 관리하고 싶다면 메모리를, 서비스가 종료 되어도 캐시를 유지하고 싶다면 디스크를 선택할 수 있습니다.
ehCache 3.x 기준으로 ReentrantReadWriteLock 을 사용하여 동시성 이슈를 처리하며 백그라운드 스레드 스케줄링을 통해 주기적으로 만료된 항목을 삭제하는 방식으로 동작합니다.
Caffeine 캐시는 JVM Heap에 캐시 저장소를 두는 방법입니다. ReentrantLock 을 사용하여 동시성 이슈를 해결하며 데이터에 접근할 때 TTL 을 체크하여 삭제하는 방식으로 동작합니다.
ReentrantReadWriteLock
Read Lock 과 Write Lock 을 분리하여 사용합니다.
Read Lock 을 여러 스레드가 동시에 사용할 수 있으며 Write Lock 은 하나의 스레드만 사용 가능합니다. Write Lock 을 획득한 스레드가 있다면 다른 스레드가 읽거나 쓸 수 없습니다.ReentrantLock
Read Lock 과 Write Lock 을 하나로 사용합니다.
한 번에 하나의 스레드만 락을 획득할 수 있습니다.
벤치마크 결과에 따르면 Caffeine이 ehCache 보다 높은 성능을 발휘 한다고 알려져 있습니다.
일반적으로 ReentrantReadWriteLock 이 ReentrantLock 보다 읽기 성능이 좋지만
Caffeine 이 락 메커니즘을 제외한 다양한 최적화 요소들(경량화, TTL 처리) 이 복합적으로 작용했기 때문입니다.
로컬 캐시 사용 예제는 Github Link 를 참고해주세요.
글로벌 캐시(Global Cache)는 여러 서버나 시스템에서 공유되는 캐시를 의미합니다.
이는 시스템 전체에서 접근할 수 있는 중앙화된 캐시로 여러 서버나 애플리케이션이 동일한 캐시 데이터를 사용할 수 있도록 합니다. 전역 캐시는 분산 시스템에서 데이터 일관성을 유지하고 성능을 향상시키는 데 중요한 역할을 합니다.대표적인 글로벌 캐시로 Redis 가 사용됩니다.
Redis 는 메모리에 데이터를 저장하므로 속도가 빠르고 싱글 스레드로 동작하여 동시성 이슈를 해결합니다.
단 캐시 서버 이슈가 발생할 경우 데이터가 삭제될 수 있으므로 서킷 브레이커 등을 고려하여 서버 이슈 발생에 대한 전략을 세워야 합니다.
참고 !
ehCache도 글로벌 캐시 옵션을 제공하지만
설정 및 관리가 복잡하고 확장성이 좋지 않기 때문에 잘 사용하지 않습니다