1. 로컬 캐시와 레디스를 함께 사용하는 2-Level Cache(2계층 캐시) 구현하기아래의 내용을 제대로 이해하기 위해서는 스프링이 제공하는 Cache와 CacheManager에 대한 이해가 필요하다. 따라서 이전 포스팅을 먼저 참고하도록 하자. [ 요구사항 정리 ]이번에 구현하고자 하는 기능은 스프링의 @Cacheble을 활용하여 로컬 캐시와 분산 캐시를 함께 사용하는 2-Level Cache(2계층 캐시)를 구현하는 것이다. 2계층 캐시란 동일한 캐시 요청(EmailToNameCache)에 대해 먼저 로컬 캐시(LocalCacheManager)를 조회하여 있으면 반환하고, 없으면 분산 캐시(RedisCacheManager)를 조회하여 그 결과를 반환하는 것이다. 이를 통해 분산 캐시에 대한 트..
# 1. 스프링이 제공하는 Cache 관련 기능 파헤치기[ Cache Abstraction(캐시 추상화) ]스프링이 가장 잘하는 것 중 하나를 뽑으라면 추상화(Abstraction)를 빼놓을 수 없다. 대표적으로 스프링은 트랜잭션 관련 공통 사항을 담은 트랜잭션 추상화 기술을 제공하고 있다. 이를 통해 각 애플리케이션에서는 데이터베이스 접근 기술(JDBC, JPA 등)에 종속적이지 않고 일관되게 트랜잭션을 처리할 수 있도록 도와준다. 데이터베이스 접근 기술을 JDBC에서 JPA로 변경해도 우리의 코드는 안전한 것이다.캐시 역시 마찬가지다. 로컬 메모리에서 동작하는 caffeine 캐시, 분산 저장소를 활용하는 Redis 캐시 등 다양한 캐시 구현체가 존재한다. 해당 기술을 직접 의존하면 캐시 구현체가 변..
1. SpringBoot3에 추가된 Content-Disposition 헤더의 일반 filename 파라미터(Regular Parameters) [ Content-Disposition 헤더와 ContentDisposition 클래스 ] RFC-6266에 정의된 Content-Disposition 헤더는 서버가 클라이언트에게 전송되는 리소스(파일 등)의 처리 방법을 지정하는 데 사용되는 헤더이다. 주로 다운로드되는 파일의 이름 등을 지정하는 데 사용된다. 만약 서버가 다음과 같이 Content-Disposition 헤더를 전달하였다면, 브라우저는 example.txt라는 이름으로 파일을 다운로드하도록 요청을 처리한다. Content-Disposition: attachment; filename="exampl..
1. 스프링이 구현한 Aggregate Root(애그리거트 루트)와 도메인 이벤트 [ Aggregate(애그리거트)와 도메인 이벤트 ] 도메인을 중심으로 하는 애플리케이션을 개발할 때 등장하는 개념으로 애그리거트가 있다. 애그리거트(Aggregate)란 관련된 객체들을 모아둔 하나의 단위로, 값 객체(Value Object)와 엔티티(Entity)로 구성된다. 그리고 애그리거트의 중심에는 애그리거트 루트가 존재하는데, 이를 애그리거트 루트(Aggregate Root)라고 부른다. 객체들은 애그리거트 루트를 중심으로 관리된다. (해당 포스팅은 이러한 내용을 자세히 다루는 것이 주목적이 아니므로 간략히만 살펴보도록 하자.) 이를 주문 도메인을 기준으로 그려보면 다음과 같다. 애그리거트 루트가 영속화 될 때 ..
1. EmptyResultDataAccessException 예외가 발생한 SQL 쿼리와 파라미터 로깅하기 [ 요구 사항 ] 서비스를 개발하다 보면 존재하지 않는 리소스에 접근하여 EmptyResultDataAccessException 에러가 발생하는 경우가 있다. 하지만 EmptyResultDataAccessException를 통해서는 어떤 쿼리의 어떤 파라미터로 인해 문제가 발생했는지 정확한 파악이 어렵다. 만약 여러 개의 레포지토리에 접근하는 중에 리소스를 접근하고 있다면 더욱 파악이 어렵다. 따라서 에러가 발생한 쿼리를 로깅하여 에러 로그를 보완하도록 하자. [ 기능 추가 ] 쿼리와 파라미터를 저장하기 위한 컨텍스트 추가 파라미터를 컨텍스트에 저장하기 위한 AOP 추가 실행 쿼리를 컨텍스트에 저장..