Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- Intellij
- spring boot
- 멀티 모듈
- EC2
- Github Actions
- JPA
- algorithm
- AWS
- 테스트 코드
- JWT
- swagger
- 어노테이션
- 아키텍처
- DevOps
- docker
- querydls
- trouble shooting
- springboot
- CI/CD
- rabbitmq
- Til
- 객체지향원칙
- 유효성 검사
- testcode
- Kafka
- MSA
- Java
- Redis
- 프로그래머스
- aop
Archives
- Today
- Total
개발노트
25.03.07 Redis를 활용한 Spring Boot 캐싱 전략 본문
개요
Redis 사용이 처음이고 주로 캐싱에 사용할 것 같아 배운 내용을 정리해본다.
캐시( Cache ) 란 무엇인가?
캐시 ( Cache )란?
캐시(Cache)는 자주 사용하는 데이터를 미리 저장해두고 빠르게 제공하는 저장소를 의미한다. 데이터를 매번 원본 데이터베이스에서 가져오는 대신, 한 번 조회한 데이터를 캐시에 저장하여 이후 요청 시 빠르게 제공함으로써 성능을 최적화하는 방식이다.
캐시를 사용하는 이유
- 성능 향상
- 데이터베이스(DB)에서 데이터를 조회하는 것보다 캐시에서 데이터를 가져오는 속도가 훨씬 빠르다.
- 따라서 애플리케이션의 응답 속도가 향상되고, 사용자 경험(UX)이 개선된다.
- DB 부하 감소
- 같은 데이터에 대한 반복적인 조회 요청을 줄여서 DB 서버의 부담을 줄일 수 있다.
- 비용 절감
- 클라우드 환경에서 운영 시, DB 조회 요청이 많으면 추가 비용이 발생할 수 있다.
- 캐싱을 통해 불필요한 DB 요청을 줄이면 비용을 절감할 수 있다.
- 고가용성 (High Availability)
- DB 장애 발생 시, 캐시 데이터를 사용하면 일정 기간 동안 서비스를 지속적으로 운영할 수 있다.
Redis를 활용한 캐시 설정 방법 ( CacheConfig )
Redis는 메모리 기간의 저장소로, 빠른 속도를 자랑하는 NoSQL 데이터베이스이자 캐시로 많이 사용된다.
@Configuration
@EnableCaching // 스프링 캐시 활성화
public class CacheConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
// RedisCacheConfiguration을 활용하여 기본 캐시 설정을 구성
RedisCacheConfiguration configuration = RedisCacheConfiguration
.defaultCacheConfig()
.disableCachingNullValues() // null 값은 캐싱하지 않음
.entryTtl(Duration.ofSeconds(120)) // 캐시 TTL(유효시간) 120초 설정
.computePrefixWith(CacheKeyPrefix.simple()) // 캐시 키 접두어 설정
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json())); // JSON 형식 직렬화
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(configuration) // 기본 캐시 설정 적용
.build();
}
}
주요 설정 설명
- @EnableCaching
- Spring Boot에서 캐싱 기능을 활성화하는 어노테이션
- RedisCacheConfiguration.defaultCacheConfig()
- 기본 캐시 설정을 적용
- .disableCachingNullValues()
- null 값을 캐싱하지 않도록 설정
- .entryTtl(Duration.ofSeconds(120))
- **TTL(Time To Live, 만료 시간)**을 120초(2분)로 설정하여, 120초 이후 자동 삭제
- .computePrefixWith(CacheKeyPrefix.simple())
- Redis의 키에 **고유한 접두어(prefix)**를 붙여 충돌 방지
- .serializeValuesWith(RedisSerializer.json())
- JSON 형식으로 직렬화하여 저장
- Redis는 기본적으로 바이트 배열로 저장하므로, JSON 형식을 사용하면 가독성이 높아짐
.withInitialCacheConfigurations()의 역할과 사용법
여러 개의 캐시 설정을 적용해야 할 때
- RedisCacheManager를 설정할 때, 모든 캐시에 동일한 설정을 적용하는 경우는 cacheDefaults(configuration)를 사용하면 된다.
- 하지만 캐시마다 서로 다른 TTL(유효시간)이나 직렬화 방식이 필요하다면?
- 이때 .withInitialCacheConfigurations()을 활용하여 캐시별로 개별 설정을 적용할 수 있다.
자주 변하는 데이터와 거의 변하지 않는 데이터의 TTL을 다르게 설정하거나 엔드포인트별로 TTL을 다르게 설정해야할 때
캐시 설정을 다르게 사용하면 좋다.
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();
// 특정 캐시 이름에 대한 개별 설정 적용
cacheConfigurations.put("shortLivedCache", RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(60))); // TTL 60초 설정
cacheConfigurations.put("longLivedCache", RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(2))); // TTL 2시간 설정
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(30)) // 기본 TTL 30분
)
.withInitialCacheConfigurations(cacheConfigurations) // 개별 캐시 설정 적용
.build();
}
캐시 어노테이션
어노테이션 | 설명 |
@Cacheable | 캐시에서 데이터를 가져오고, 없으면 실행 후 저장 |
@CachePut | 실행 후 결과를 캐시에 업데이트 |
@CacheEvict | 특정 캐시 데이터를 삭제 |
@Caching | 여러 개의 캐시 관련 어노테이션을 함께 사용 |
@Cacheable
- 기존에 캐시된 값이 있으면 DB 조회 없이 캐시 데이터 반환
- 캐시에 값이 없으면 메서드를 실행한 후 결과를 저장
@Cacheable(cacheNames = "itemCache", key = "#id")
public ItemDto readOne(Long id) {
return itemRepository.findById(id)
.map(ItemDto::fromEntity)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
}
1. id 에 해당하는 데이터가 itemCache에 존재하는지 확인
2. 존재하면 DB 조회 없이 캐시 데이터를 반환
3. 존재하지 않으면 DB에서 조회 후 결과를 캐시에 저장
@CachePut
- 항상 실행 후 결과를 캐시에 저장 (업데이트 용도)
- 기존 데이터가 있어도 무조건 실행 후 새로운 값을 저장
@CachePut(cacheNames = "itemCache", key = "#result.id")
public ItemDto create(ItemDto dto) {
return ItemDto.fromEntity(itemRepository.save(Item.builder()
.name(dto.getName())
.description(dto.getDescription())
.price(dto.getPrice())
.build()));
}
1. create() 실행 후 새로운 ItemDto 생성
2. 결과(result.id)를 캐시에 저장하여 이후 조회 시 캐시 사용
@CacheEvict
- 특정 캐시 데이터를 삭제할 때 사용
@CacheEvict(cacheNames = "itemCache", key = "#id")
public void delete(Long id) {
itemRepository.deleteById(id);
}
1. id에 해당하는 데이터를 DB에서 삭제
2. 캐시에서도 해당 id의 데이터를 삭제
특정 메서드 지정
@CacheEvict(cacheNames = "itemAllCache", key = "'readAll'")
@Caching
- 여러 개의 캐시 관련 어노테이션을 동시에 적용
@Caching(evict = {
@CacheEvict(cacheNames = "itemCache", key = "#id"), // 개별 캐시 삭제
@CacheEvict(cacheNames = "itemAllCache", key = "'readAll'") // 전체 목록 캐시 삭제
})
public void delete(Long id) {
itemRepository.deleteById(id);
}
1. id에 해당하는 개별 캐시 삭제 (itemCache)
2. 전체 목록 캐시 삭제 (itemAllCache)
'Spring Boot' 카테고리의 다른 글
25.02.25 통합테스트 DB 환경 분리 (0) | 2025.02.25 |
---|---|
25.02.20 JWT 리팩토링 과 헥사고날 아키텍처 도입 (0) | 2025.02.20 |
25.02.19 QueryDSL (1) | 2025.02.19 |
25.02.17 JWT 검증 필터 와 테스트 코드 any() (0) | 2025.02.17 |
25.02.13 Spring Boot AOP (0) | 2025.02.13 |