ConcurrentHashMap
- on-Heap JVM힙 내부에 저장된다는 뜻
- 단순한 캐시나 공유 맵
- 캐시 제어 기능 X
- GC대상
- ConcurrentHashMap은 그냥 키-값 저장소일 뿐이지 캐시 기능은 전혀 없음
Ehcache
- 온힙 + 오프힙 지원
- 고급 캐시 (TTL, 만료 등)
- 캐시 제어 기능 X (TTL, Eviction) 등
- Off Heap설정하면 GC영향 줄일 수 있음
- 분산환경에서 캐시 동기화는 Terracotta를 사용함
Caffine
- 고급 캐시 직접구현 x
- 크기 제한 직접구현 x
- 통계/모니터링 제공
- on-heap이지만 GC최적화 되어있음
- 예외/로드 실패 처리 CacheLoader로 핸들링 가능
- ConcurrentHashmap은 용량제한이없는데 Caffine은 용량제한 가능하다
Off-Heap이 중요한 이유?
Java 힙 메모리는 GC의 대상이 되기 때문에, 대용량 데이터를 ConcurrentHashMap에 담아두면 GC 지연이나 Full GC 발생 위험이 있어요.
반면 Ehcache는 데이터를 Off-Heap (JVM 외부 메모리) 에 저장할 수 있어서: GC로부터 자유롭고
메모리 사용량을 좀 더 명시적으로 제어할 수 있어요.
따라서 대규모 캐시를 다루거나, GC 영향을 최소화하고 싶을 때 Ehcache의 Off-Heap 설정은 큰 장점이다
하지만 장단점을 자세하게 비교해보자
그러나 Off Heap이면 속도가 On-Heap에 비해 떨어진다
- 🔄 직렬화/역직렬화 Off-Heap에 저장하려면 JVM 객체를 바이트 배열로 바꿔야 함 → 비용 발생
- 🚫 직접 접근 불가 On-Heap은 바로 객체 필드 접근 가능하지만, Off-Heap은 주소 계산 + 버퍼 접근 필요
- 🧵 복잡한 동기화 Off-Heap은 GC 영향을 안 받지만, 그만큼 개발자가 관리해야 할 부분이 많음
- 🐢 성능 최적화 한계 JIT 최적화가 Off-Heap 데이터엔 적용되지 않음 (Heap은 가능)
Off-Heap이 필요한 경우도 있어요
- ✅ 대용량 캐시 필요 수십~수백만 건 이상의 캐시를 다뤄야 할 때
- ✅ GC 지연 허용 불가 예: 거래 시스템, 실시간 API 서버 등
- ✅ 장기 저장 필요 데이터가 오랫동안 살아있어야 하는 경우
결론 정리
성능 = On-Heap (Caffeine)
대용량 안정성 = Off-Heap (Ehcache)
Caffeine + Redis 같은 구조로:
Caffeine을 대용량 캐시로 쓰면 아래 문제가 생길 수 있어요. 힙 메모리가 부족해지고
GC 시간 증가 → Stop-the-world
Caffine+Redis를 많이쓰는이유
EhCache+Redis는 왜 없을까? 라는 생각을 한다.
요즘은 클라우드 친화적이라 그런거 같다.
- Ehcache는 Redis 연동을 공식적으로 지원하지 않음
- Ehcache는 Off-Heap/디스크 기능이 장점인데, Redis를 쓸 거면 굳이 Off-Heap/디스크까지 갈 필요가 없음, 그리고 Redis 자체가 훨씬 강력한 캐시 + 분산 기능을 제공