API Server를 개발 중에 로컬에서는 MySQL, 테스트 환경에서는 H2를 사용하고 있다테스트 환경에서 실제 사용할 DB가 아닌 인메모리 데이터베이스를 쓰는 것은 자칫 위험할 수 있다테스트를 돌리더라도 실제 DB와 상호작용을 한 것이 아니니 신뢰도가 100%라 할 수는 없을 것이다 그럼에도 실제 DB를 쓰지 않는 이유는 두 가지다1. 외부 의존성을 빼고 오프라인 상태에서도 돌아갈 수 있게끔 하기 위해2. 인메모리 데이터베이스를 이용해 전체 테스트를 빠르게 돌리기 위해 JPA, QueryDSL 사용 중이며 H2에서 BigDecimal를 다루다 만났다, 정확한 문제 상황은 다음과 같다MyEntity 안에 BigDecimal 타입으로 설정한 price를 case-when 절로 조회해 올 때 문제가 발생했..
이전 글에서 이어지는 내용으로 commitOrRollback의 세부 구현을 살펴보자 EventListener 구현체는 JpaEventListener를 구현하고 여기서는 공통 Transaction 작업만 처리해주면 된다 import java.util.function.Consumer; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.engine.spi.SharedSessionContractImplementor; public interface JpaEventListener { default void commitOrRollback( SharedSessionContractImplementor session, C..
도메인 주도 개발 혹은 MSA로 갈 때 연관 관계를 다루기 위해서는 객체 자체가 아닌 식별자를 저장하곤 한다 예시만 살짝 맛보기로 하기 위해 극단적으로 간단한 엔티티를 만들었다, Panda -> Bear에 대한 간접 참조를 갖는다 @Entity @NoArgsConstructor @Getter public class Panda { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private Long bearId; @Builder public Panda(String name, Long bearId) { this.name = name; this.bearId = bearId; } } @Entity ..
[Redis] HATEOAS와 @Cacheable - 2 [Redis] HATEOAS와 @Cacheable 이전 Redis 삽질기에서 해결법은 찾지 못 했으나 타협점을 찾았기 때문에 올린다 내가 의도 했던 것은 RestController 응답을 HATEOAS에 맞춰 ResponseEntity 또는 ResponseEntity.. ryumodrn.tistory.com 위 글에서 이어지는 글이다 2편에서의 문제점은 GenericJackson2JsonRedisSerializer를 사용했을 때 발생하던 아래 에러다 Caused by: java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class org.springframewo..
[Redis] HATEOAS와 @Cacheable 이전 Redis 삽질기에서 해결법은 찾지 못 했으나 타협점을 찾았기 때문에 올린다 내가 의도 했던 것은 RestController 응답을 HATEOAS에 맞춰 ResponseEntity 또는 ResponseEntity 로 내려주려고 했다 또한 응답. ryumodrn.tistory.com 위 글에서 이어지는 글이다 많은 우여곡절 끝에 HATEOAS를 적용한 PagedModel 형태에 캐시 추상화 @Cacheable을 접목했다 정확하게 말해 Page를 캐시하고 Controller 단에서 Page 형태의 캐시 데이터를 PagedModel로 변환하여 반환한다 지난 글에서의 문제점은 _links 가 깨진다는 점이었다 사실 위 문제를 해결하고도 PagedModel에..
[Redis] @Cacheable 삽질기 조회 성능 향상을 위해 Spring Data Redis를 도입했고 간단해 보이는 @Cacheable, @CachePut 등을 사용하기로 결정했다 그런데 LocalDateTime을 변환할 때 살짝 문제가 있었다 가장 쉬운 해결 방법은 아래와 같 ryumodrn.tistory.com 위 글에서 이어지는 글이다 해결은 금방 했는데 이제야 올리게 됐다 Redis를 사용하면서 @Cacheable로 데이터를 캐싱할 때 발생했던 문제다 LocalDateTime을 JSON 형태로 직렬화 / 역직렬화할 때 LocalDateTime이 풀어 헤쳐지던 문제인데 해결은 간단했다 @JsonFormat(pattern=어쩌구, timezone=저쩌고)로도 풀 수 있지만 이 애노테이션을 모든 ..
지난 글은 https://ryumodrn.tistory.com/23 참고 한동안은 Redis @Cacheable에 대해 마음을 내려놓고 있었다 프로젝트 막바지에 적용해보다가 정 안 되면 List 형태로 반환하던지 jwt token 인증을 하고 있고 token은 page 형태로 반환할 필요가 없으니 token service에만 적용시켜 봐야겠다하고 생각 중이었다 이후 HATEOAS에서의 EntityModel, PagedModel을 공부하고 PagedModel의 구현에서 Cache를 적용할 수 있는 영감을 얻었다 PagedModel은 EntityModel의 Page 형태 반환이다 PagedModel의 구현을 살펴보던 중 deprecate된 생성자 메서드를 대신하는 static method인 of를 살펴봤다 ..
이전 Redis 삽질기에서 해결법은 찾지 못 했으나 타협점을 찾았기 때문에 올린다 내가 의도 했던 것은 RestController 응답을 HATEOAS에 맞춰 ResponseEntity 또는 ResponseEntity로 내려주려고 했다 또한 응답 결과의 더 빠른 제공을 위해 spring-data-redis의 @Cacheable을 사용하려고 했다 그런데 EntityModel은 Serializable을 구현하지 않고, 독자적인 deserializer를 사용하고 있기 때문에 EntityModel에 @Cacheable을 사용한 방식으로 응답을 내려주면 아래와 같은 에러를 만날 수 있다 com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Type id ..
조회 성능 향상을 위해 Spring Data Redis를 도입했고 간편한 사용을 위해 캐시 추상화를 사용했다 @Cacheable, @CachePut 등을 사용한다 그런데 LocalDateTime을 변환할 때 살짝 문제가 있었다 가장 쉬운 해결 방법은 아래와 같이 변환될 형식을 지정해주는 것이다 LocalDateTime을 사용하는 모든 DTO에 annotation이 붙을 걸 생각하니 아찔해져 전역으로 형식을 바꿀 방법을 찾아봤다 아쉽게도 Redis, JacksonSerializer 에 대한 이해도가 낮아서 찾아본다고 했지만 아직 방법을 찾지 못했다 참고가 될 만한 블로그는 찾았는데 적용하지는 못 했다 Serializer / Deserializer를 Custom으로 만들어서 원하는 형식으로 파싱하고 Obje..