목록Spring Boot (9)
훈훈훈
Introduction 사내에서 Local cache 라이브러리인 Caffeine cache 를 도입하게 되어 공부한 내용을 정리하게 되었다. Caffeine cache 를 사용하면서 EhCache 와의 차이점이 궁금하여 두 라이브러리를 비교 후 간단한 예제 코드를 살펴보려고 한다. 예제 코드는 깃헙에서 확인할 수 있다. Caffeine cache vs EhCache 3.xx 먼저 Caffeine cahce 에 대하여 살펴보자 Baeldung 에서는 Caffeine Cache 를 아래와 같이 소개하고 있다. Caffeine 깃헙 위키는 아래와 같이 소개하고 있다. 공통적으로 High Performance Java caching Library 라고 소개하고 있다. 문서를 읽어보면 캐시와 Concurrent..
Introduction WebClient 를 사용하여 외부 API 를 Mock 기반 테스트를 할 때, response 값에 대한 stub 객체를 만드는 방법에 대하여 정리해보려고 한다. 전체 코드는 Github 에서 확인할 수 있다. Problems 일반적으로 Mockito 를 사용할 때 아래와 같은 방법으로 stub 객체를 만들 수 있다. ( Mockito 는 BDD 방식을 지원하기 때문에 when( ) 대신 좀 더 가독성이 좋은 given ( ) 을 사용하였다. ) given(webClientWrapper.get() .uri("http://localhost:8080/test") .retrieve() .bodyToMono(String.class) .block() ).willReturn("ok"); 하지..
어느 날 땡땡이라는 API를 호출 시, 조건에 만족하는 모든 데이터를 뿌려주는 쿼리가 실행되는 것을 발견하였다. 프론트에서 모든 데이터를 받고 페이징을 처리하는 구조였던 것이다. 이런 구조는 데이터가 많이질수록 부하가 발생할 수 있는 구조이기 때문에 서버에서 페이징을 처리하는 구조로 변경하기로 했다. 페이징은 Offset과 limit을 사용하는 방식이 주로 사용되는데, 문제는 해당 API를 사용하는 웹 페이지에는 페이지 버튼이 존재하지 않았기 때문에 어떤 방법을 사용하여 페이징을 구현할까 고민을 하게 되었다. 현재 데이터를 보여주는 방식은 아래 사진처럼 화살표를 클릭하면 다음 데이터가 나오는 구조였다. 따라서 기존의 페이징 방식인 버튼(페이지 번호)을 사용하는 방식이 아닌 페이지 번호가 없는 No Off..
이번에 간단하게 Entity를 조회하는 API인데 성능이 생각보다 안좋은 이슈를 발견하게 되었다. 그래서 Entity를 확인해보니 OneToOne 관계를 사용하고 있었고 로그를 확인 했을 때 쿼리가 한 번이 발생하는 것이 아닌 무수히 많은 쿼리가 발생하는 것을 보았다. OneToOne 관계에서 지연로딩이 동작하지 않는다는 것은 인지하고 있지 못하였는데 이 기회에 한 번 정리해보려고 한다. (예제 언어는 자바가 아닌 필자에게 익숙한 코틀린으로 작성하였다. 자바 예제는 추후 추가할 예정이다.) 먼저 결론을 말하자면 JPA 구현체인 Hibernate 에서는 양방향 OneToOne 관계에서는 지연로딩이 동작하지 않는다. 정확하게는 테이블을 조회할 때 외래 키를 갖고 있는 테이블(연관 관계의 주인)에서는 지연로딩..
이번에는 스프링 부트와 Kotlin 그리고 JPA(Hibernate) 사용하면서 겪었던 N+1 이슈를 정리해보려고 한다. 여러 연관관계가 매핑되어 있는 테이블의 전체 데이터를 조회하는 API를 호출하였을 때, 한방 쿼리가 발생할 것으로 예상을 했지만.... 결과는 몇천만 건 이상 쿼리가 발생하는 이슈가 발견되었다. 해당 글에서는 문제를 해결하면서 알게된 사용한 기술들에서 발생한 문제점과 해결방안을 공유하려고 한다. Hibernate 하이버네이트는 지연로딩(Lazy Loading)을 할 때 Entity를 프록시 객체로 조회한다고 한다. 그리고 공식 문서를 확인해보면 Entity Class를 final 속성으로 선언하면 프록시 객체를 생성할 수 없기 때문에 지연로딩을 사용할 수 없다고 명시되어 있다. 코틀린..
Spring boot와 Kotlin(코틀린)으로 Application 개발 중에 Jackson 라이브러리에서 LocalDate 타입을 Deserialize(serialize)를 하면서 발생했던 이슈를 정리해보려고 한다. - 오류 메시지 Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.LocalDate` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value - 문제 상황 Applicat..
이번에는 Spring boot에서 Event Listener를 사용하는 것에 대하여 정리해보려고 한다. Event Listener를 사용하게된 계기는 Spring boot Application 시작 및 종료 시 특정 이벤트를 수행시키기 위해서 여러 방법을 찾던 중 가장 나은 방법으로 판단하게 되어 사용하게 되었다. 비슷한 기능으로는 @PostConstruct와 @PreDestory가 있지만 해당 기능은 Bean이 생성 시점에 실행되기 때문에 이벤트가 실행되는 시점은 내가 원하는 시점과 약간 차이가 발생한다. 따라서 해당 기능은 사용하지 않고 Event Listener를 사용하였다. 예제 코드 @Component class StartTest { private val logger = LoggerFactory..
이번에는 Spring boot, JPA와 코틀린(Kotlin)을 사용하여 간단한 API를 만들어 보려고 한다. 현재 사내에서 API 서버를 스프링 부트와 코틀린을 사용하여 개발하고 있다. 구글 검색 시 자바에 비해 코틀린에 관한 내용은 많이 부족하다. ....그래서 시간 날떄 틈틈히 정리를 해보려고 한다. 사용한 기술은 아래와 같다. - Spring Boot - Kotlin - gradle - postgresql - JPA IDE는 IntelliJ를 사용하였으며, 이클립스 환경이랑은 약간 차이가 날 수 있다. 이제 아래 코드를 보면서 살펴보자. 프로젝트 구조 먼저 프로젝트 구조는 아래와 같이 구성하였다. 파일 구성은 Controller, Service, DTO, Model, Repository 로 구성하..