2024-08-08-TIL
2024-08-08-TIL
Today I Learned
Spring Boot Caching with Redis
Spring의 캐시 추상화는 @EnableCaching을 켜고 메서드에 @Cacheable, @CachePut, @CacheEvict를 붙이면, 실제 저장소와 상관없이 같은 방식으로 캐시를 적용하게 해 준다. 저장소는 CacheManager 구현으로 바꾼다. Redis를 쓰면 Spring Data Redis의 RedisCacheManager가 그 역할을 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(10))
.disableCachingNullValues()
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.build();
}
@Cacheable(cacheNames = "product", key = "#id")
public ProductResponse getProduct(Long id) { ... }
공식 문서에서 확인한 설정 포인트는 다음과 같다.
- 기본 직렬화: 키는
StringRedisSerializer, 값은JdkSerializationRedisSerializer다. JDK 직렬화는 클래스 정보에 묶이고 사람이 읽기 어려워서, JSON 직렬화로 바꾸는 경우가 많다. - TTL:
entryTtl로 캐시 항목의 만료 시간을 정한다. 캐시 이름마다 다른 설정을 줄 수도 있다. disableCachingNullValues():null결과를 캐시하지 않는다.- 캐시 writer: 기본은 락을 쓰지 않는 writer로 처리량이 좋고, 락을 쓰는 writer는
putIfAbsent같은 명령이 겹치지 않게 막는다.
@Cacheable도 프록시로 동작하므로 같은 클래스 안에서 호출하면 캐시가 적용되지 않는다는 점은 @Transactional과 같다.
Web Caching
웹 캐시는 브라우저, CDN, 중간 프록시처럼 여러 층에 있다. 각 층이 응답을 얼마나 오래 재사용할지는 HTTP 응답의 Cache-Control 헤더가 정한다. 토스 기술 블로그의 글이 이 동작을 잘 정리한다.
max-age: 캐시가 유효한 시간(초). 이 시간 동안은 서버에 묻지 않고 캐시를 쓴다.s-maxage: CDN 같은 공유 캐시에만 적용되는 유효 시간.no-cache: 캐시는 하되 쓸 때마다 서버에 재검증한다.max-age=0과 비슷하다.no-store: 아예 저장하지 않는다.
유효 시간이 지나도 캐시를 바로 버리지 않는다. 브라우저는 If-None-Match(ETag)나 If-Modified-Since를 붙여 조건부 요청을 보내고, 내용이 그대로면 서버는 본문 없이 304 Not Modified만 돌려준다.
토스는 HTML에는 max-age=0, s-maxage=31536000을 줘서 브라우저는 매번 재검증하고 CDN은 오래 캐시하게 하고, 빌드마다 URL이 바뀌는 JS와 CSS에는 긴 max-age를 준다. 배포하면 CDN 캐시만 무효화하면 된다. CDN 무효화로는 사용자 브라우저에 이미 저장된 캐시를 지울 수 없으므로, 처음부터 max-age를 신중하게 정해야 한다는 것이 글의 요점이다.
AWS의 캐싱 문서는 같은 원리를 애플리케이션 계층으로 넓혀 데이터베이스 캐싱, 세션 캐싱, 캐시 전략(Lazy Loading, Write-Through)과 TTL 설정을 다룬다.
@ControllerAdvice Internal
@ControllerAdvice는 여러 컨트롤러에 공통으로 적용할 @ExceptionHandler, @InitBinder, @ModelAttribute 메서드를 한곳에 모으는 컴포넌트다. @RestControllerAdvice는 여기에 @ResponseBody가 더해진 것이다.
동작은 대략 다음과 같다. 애플리케이션이 시작될 때 Spring MVC는 @ControllerAdvice 빈들을 찾아 그 안의 @ExceptionHandler 메서드를 예외 타입별로 정리해 둔다. 컨트롤러에서 예외가 나면 HandlerExceptionResolver 중 하나인 ExceptionHandlerExceptionResolver가 처리할 메서드를 찾는데, 먼저 예외가 난 컨트롤러 자신의 @ExceptionHandler를 보고, 없으면 advice 빈들을 순서대로 확인한다. 여러 advice가 있으면 @Order로 우선순위를 정하고, basePackages나 assignableTypes로 적용 대상 컨트롤러를 좁힐 수 있다.
1
2
3
4
5
6
7
8
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(IllegalArgumentException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse handle(IllegalArgumentException e) {
return new ErrorResponse("BAD_REQUEST", e.getMessage());
}
}
SSL/TLS Version Check
서버가 어떤 TLS 버전을 지원하는지는 클라이언트 쪽에서 특정 버전만으로 연결을 시도해 보면 확인할 수 있다. openssl s_client는 버전을 지정하는 옵션을 제공하고, 핸드셰이크가 실패하면 그 버전을 지원하지 않는다는 뜻이다. nmap의 ssl-enum-ciphers 스크립트는 지원하는 버전과 cipher suite를 한 번에 나열한다.
1
2
3
openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3
nmap --script ssl-enum-ciphers -p 443 example.com
TLS 1.0과 1.1은 RFC 8996으로 공식 폐기되었으므로, 서버에서는 TLS 1.2 이상만 허용하도록 설정하는 것이 일반적이다.
참고한 자료외부 출처 20
외부 출처
- Spring Boot caching with Redis
- Spring Boot Cache with Redis
- Insights
- Redis Cache
- A Guide to Using Redis in Spring Boot: Custom CacheManager
- medium.com/@aedemirsen/cache-structure-in-spring-boot-projects-with-redis-2c5751bca9eb
- Redis University
- How To Implement Redis Cache In Spring Boot? Step-by-Step Guide Redis Cache Spring Boot
- Spring Boot Redis CRUD Example LettuceConnectionFactory Tutorial
- machinet.net/tutorial-eng/efficient-caching-in-spring-boot-using-redis
- 웹 서비스 캐시 똑똑하게 다루기
- 캐싱 홈
- [캐싱이란? 웹 사이트는 어떻게 캐시될까요?] — Cloudflare
- 캐시(Cache)와 캐싱(Caching) 정리 from 10분 테크톡
- 웹사이트 캐싱: 속도와 효율성 향상
- Best Practicies
- medium.com/@jovannypcg/understanding-springs-controlleradvice-cd96a364033f
- controller advice
- hahwul.com/2023/07/08/various-ways-to-check-ssl-version-of-a-server
- How to check and/or change the TLS version
댓글
아직 댓글이 없습니다