재고 수량, 계좌 잔액처럼 정합성이 중요한 값을 캐시하면 오래된 값을 보여주는 사고로 이어집니다. 캐시 여부를 정하기 전에 "이 값이 잠깐 오래돼도 괜찮은가"를 먼저 물어봐야 합니다.
TTL 을 안 두면 원본 데이터가 바뀌어도 서버를 재시작할 때까지 옛날 값이 계속 나갑니다. 코드 테이블처럼 거의 안 바뀌는 데이터도 최소한의 TTL(예: 1시간)은 두는 편이 안전합니다.
사용자별·요청 파라미터별로 키가 계속 늘어나는 캐시에 크기 제한이 없으면 힙 메모리를 다 써버릴 수 있습니다. maximumSize 를 항상 TTL 과 함께 설정합니다.
인기 키가 만료되는 순간 동시 요청이 전부 DB 를 때리면, 트래픽이 많은 시스템에서는 DB 커넥션 풀이 순식간에 고갈됩니다. computeIfAbsent 류로 계산을 키당 한 번만 실행하도록 막아야 합니다.
같은 클래스 내부에서 this.메서드() 로 @Cacheable 메서드를 호출하면 프록시를 안 거쳐 캐시가 동작하지 않는데도 에러가 나지 않습니다. 캐시 적중률이 0%로 나온다면 self-invocation 을 가장 먼저 의심합니다.
update 나 delete 메서드에 @CacheEvict 를 빼먹으면, 조회 캐시가 수정 전 값을 계속 돌려줘 "분명히 고쳤는데 화면엔 옛날 값이 나온다"는 문의로 이어집니다. 쓰기 메서드마다 캐시 무효화가 필요한지 항상 점검합니다.
서버 A 에서 evict 해도 서버 B 의 로컬 캐시는 그대로입니다. 인스턴스가 여러 대인 시스템에서 로컬 캐시로 이 문제를 겪는다면 분산 캐시 전환을 검토해야 합니다.
주민등록번호, 계좌번호 같은 민감 정보를 캐시 값에 그대로 담으면 장애 분석용 힙 덤프에 그대로 남습니다. 캐시에는 마스킹된 값이나 식별자만 담고, 원본 조회는 필요할 때만 DB 로 가는 편이 안전합니다.