기타
[4차시] 캐싱 전략과 최적화 기법 : 속도와 자원을 동시에 잡는 방법
킨글
2025. 3. 18. 20:44
스프링 부트 어플리케이션 캐시 적용 방법과 기본 원리
- 캐시 활성화 : @EnableCaching 어노테이션 사용
- 주요 어노테이션
- @Cacheable : 캐시 저장
- 캐시된 데이터가 있을 경우 메서드 실행을 건너뛰고 캐시된 값 반환
- key 옵션 : 캐시에 저장될 키 값 지정 가능
- condition 옵션 : 조건에 맞는 경우에만 캐시 적용 가능
- @Cacheable : 캐시 저장
- 주요 어노테이션
- @CacheEvict : 캐시 삭제
- @CachePut : 캐시 업데이트
- 캐시 프로바이더 설정
- Ehcache : 로컬 캐시를 제공하는 강력한 캐시 라이브러리
- Caffeine : 높은 성능을 자랑하는 메모리 기반 캐시
- Redis : 네트워크 기반의 분산 캐시로, 여러 인스턴스에서 데이터를 공유 가능
- 캐시 사용 시 고려해야 할 성능 이슈
- 캐시 과다 사용 : 캐시가 너무 자주 갱신되면 오히려 성능에 악영향
- 캐시 적중률(Cache Hit Ratio) : 캐시가 얼마나 자주 유용한지 비율을 측정
- 캐시 만료와 갱신 빈도 : 캐시 데이터가 오래되면 성능 저하 발생
- 캐시 저장 공간과 메모리 제한 : 캐시 데이터가 메모리를 과도하게 사용하지 않도록 설정
- 캐시 병목 현상 해결 방법
- 캐시 쏠림 현상 : 한 번에 너무 많은 요청이 캐시에 집중될 때 발생
- 캐시 동시성 문제 : 다중 스레드에서 캐시 접근 시 성능 저하
- 해결 방법
- 동시성 관리 : 스레드 세이프한 캐시 설정 (예 : Caffeine의 동시성 관리)
- 캐시 파티셔닝 : 여러 캐시 서버로 요청 분산
- 배치 처리 : 데이터 갱신 시 배치 처리를 통해 부하 분산
- 로컬 캐시 vs 분산 캐시
- 로컬 캐시
- 단일 어플리케이션 인스턴스에서만 사용
- 빠르지만, 인스턴스 간 캐시 동기화가 어렵고, 확장성이 낮음
-> 적은 인스턴스에서 속도와 간편함이 중요한 경우
- 분산 캐시
- 여러 인스턴스가 동일한 데이터를 공유
- 확장성이 좋지만 네트워크 지연이 발생할 수 있음
-> 클라우드 환경이나 마이크로 서비스 구조에서 사용
- 로컬 캐시
스프링 부트 캐시 전략
- 캐시 전략의 필요성
- 무분별한 캐시 사용은 성능 저하와 메모리 사용 증가를 유발
- TTL, LRU, 캐시 크기 설정을 통해 최적화 필요
- TTL 설정의 개념과 필요성
- TTL 설정을 통해 최적의 캐시 관리 가능
- TTL 설정 방법
- LRU 전략의 개념
- 가장 오랫동안 사용되지 않은 데이터를 먼저 삭제
- 캐시가 꽉 찼을 때 새로운 데이터를 저장하기 위한 메모리 확보
- 자주 사용되는 데이터는 유지하고 사용 빈도가 낮은 데이터만 제거
- LRU 전략 적용 방법
캐시 무효화 및 일관성 전략
- 캐시 무효화 및 일관성 관리의 필요성
- 캐시 무효화
- 캐시 데이터가 유효하지 않게 되면 적절한 시점에 캐시를 제거
- 수동 무효화 : 개발자가 명시적으로 캐시를 무효화
- 자동 무효화 : TTL 설정을 통해 자동으로 캐시 무효화
- 일관성 관리
- 캐시와 원본 데이터의 일치를 유지
- 문제 발생
- 캐시된 데이터와 원본 데이터의 불일치 시 잘못된 정보 반환 가능
- 캐시 무효화
- 캐시 무효화 전략
- Write-through
- 데이터 업데이트 시 캐시와 DB를 동시에 갱신
- 실시간 트랜잭션 시스템에서 캐시와 DB를 동기화
- Write-around
- 데이터 업데이트 시 DB만 갱신, 캐시는 무효화
- 주로 읽기 작업이 많은 경우 사용
- Write-back
- 캐시를 먼저 업데이트하고 일정 시간 후 DB를 갱신
- 성능을 중시하는 시스템에서 캐시를 먼저 갱신하고, 이후에 비동기로 DB를 업데이트하여 쓰기 성능 최적화
- Write-through
- @CacheEvict로 캐시 무효화
- 캐시된 데이터를 명시적으로 삭제
- allEntries 옵션 : 캐시 내의 모든 항목을 무효화
- beforeInvocation 옵션 : 메서드 실행 전 무효화할지 여부 설정
- 캐시와 원본 데이터 간 일관성 관리 방법
- TTL 기반 자동 갱신
- TTL 설정을 통해 주기적으로 캐시를 갱신
- 데이터 변경 이벤트 기반 갱신
- 데이터가 변경되면 캐시도 즉시 갱신
- 주기적인 캐시 갱신
- 스케줄러를 사용해 정기적으로 캐시를 업데이트
- TTL 기반 자동 갱신
- Spring Boot에서 캐시 일관성 관리
- @CachePut : 메서드 실행 시 캐시를 자동 갱신
- 즉시 일관성을 제공하며, 데이터 수정 후 캐시가 자동으로 갱신됨
- @Cacheable과 함께 사용하여 데이터 갱신과 읽기를 분리 가능
API 및 DB 쿼리 캐싱을 통한 성능 최적화
- Spring Boot에서 API 캐싱 적용 방법
- @Cacheable 애노테이션을 사용하여 API 응답 캐싱
- 캐시 적용 시 key 설정을 통해 특정 요청에 대해 캐시 관리
- 캐시된 데이터는 TTL 설정을 통해 일정 시간 후 만료 가능
- Spring Boot에서 DB 쿼리 캐싱 적용 방법
- Spring Data JPA에서 쿼리 캐싱 적용
- @Cacheable을 사용하여 자주 사용하는 쿼리 캐시
- 캐시된 쿼리 결과는 TTL 또는 갱신 시점에 따라 무효화