왜 쓸까?Spring Retry에선 특정 메서드를 지정한 만큼 재시도 처리할 수 있도록 하는 기능을 제공한다. 일반적인 유스케이스는 외부 인프라(DB, API, 메시지 큐 등등..)와의 소통 및 처리과정에서 재시도 처리가 필요한 로직들일 것이다. 대개는 간헐적이고 일시적으로 발생하는 장애 상황에 대응하기 위한 전략으로 사용된다. 따라서 외부 API 호출 시 함께 사용되는 경우가 많으며, 관련 예제들도 보통은 Feign, RestTemplate 등의 클라이언트 관련 기술들과 함께 작성된 경우가 많다.사용해보기Spring Retry를 사용하기 위해선 아래 두 개의 의존성이 필요하다.dependencies { ... implementation 'org.springframework.retry:spring..
프레임워크
문제상황프로젝트에서 시간 관련 객체는 모두 타임존 정보가 없는 LocalDateTime 객체로 처리되고 있다. 사실 별 이유가 있었던 것은 아니고 잘 몰라서였다.(흑흑) 서버의 타임존은 KST로 설정되어있었기 때문에 요청값과 응답값이 모두 별도의 타임존 값 없이 암묵적으로 KST 시간대로 통일되어 돌아가고 있었다. 그런데 프로젝트에 여러 클라이언트들이 붙으며 작업을 할수록 문제가 생겼다. 서비스에서 사용자 개인이 직접 표시 시간대를 설정할 수 있고, 이 설정값에 따라서 KST로 설정되어있는 시간 데이터를 다시 적절히 계산하여 내려줘야하는데 이걸 서버 측에서 모두 하자니 누락되는 부분이 발생할 확률이 매우 높았고, 표시 시간대 데이터를 매번 조회해야하므로 성능상 좋지도 않았다. 결국 성능과 유지보수 측면에..
Job Job은 Spring Batch의 계층 구조에서 가장 상위에 위치한 개념으로, 하나의 배치 작업 그 자체를 의미한다. Job은 최소 하나 이상의 Step으로 구성되며, Spring Batch가 정의한 Job 인터페이스를 구현해 빈으로 등록 후 배치 작업을 실행시킬 수 있다. JobParamter Job 자체는 동일한 논리적인 작업 그 자체이지만, 해당 Job 자체는 모두 독립적인 실행을 보장해야할 것이다. 예컨대 특정 사용자가 한 해 사용한 카드값을 정산하는 Job이 있다고 가정했을 때, 카드값을 계산하는 로직 자체는 누구에게나 동일할 것이지만 정산을 하는 시점 및 대상 등은 Job을 실행하는 시점에 따라 달라질 수 있다. 이러한 기능을 제공하기 위해서 Spring Batch에선 실제 Job을 실..
WireMock? WireMock is a library for stubbing and mocking web services. It constructs an HTTP server that we can connect to as we would to an actual web service. When a WireMock server is in action, we can set up expectations, call the service and then verify its behaviors. https://www.baeldung.com/introduction-to-wiremock WireMock은 Mock API를 구축해주는 라이브러리로써, 외부 API와 통신을 하는 애플리케이션 코드를 테스트하기 위해 주로 ..
서론사내 프로젝트에서 새로운 API를 추가한 후, MockMvc를 통해 통합 테스트를 하는 과정에서 계속해서 오류가 발생했다. 테스트 코드 로그를 통해 자세한 오류를 확인한 결과, 요청이 엉뚱한 RequestHandler에게 가고 있었다. 예컨대, 아래와 같이 API가 정의되어있다고 가정해보자.@RestControllerpublic class OrderController { @RequestMapping(method = RequestMethod.GET, value = "/orders/{no}", produces = "application/json") public long getOrder(@PathVariable long no) { ... } // 새로 추가 @..
우리는 스프링에서 테스트 코드 수행시간을 측정하기 위해 일반적으로 IDE의 도움을 받는다. 이미 많은 사람들이 사용하고 있는 JetBrains의 IntelliJ에서는 테스트의 수행시간을 화면 상에 표시해준다. 하지만, 이와 같은 방법은 몇 가지 한계점이 있다. 바로 @SpringBootTest 혹은 @DataJpaTest 등에서 테스트 컨텍스트를 로딩하는 시간이 수행 시간에서 제외된다는 것이다. 사실, 테스트 자체를 수행하는 시간은 1초 이상을 넘기는 일이 잘 없으며 테스트 컨텍스트 로딩 시간이 우리가 체감하는 테스트 수행 시간의 대부분을 차지한다. 이 시간을 줄이기 위해선 우선 해당 시간을 정확히 측정해볼 필요가 있다. 컨텍스트 로딩 시간을 포함한 테스트 코드 전체 수행시간을 구하기 위해선 스프링 프레..
서론 Spring + JPA를 사용해 진행 중인 프로젝트에서 bulk insert가 필요한 상황이 생겼다. bulk라기엔 민망한 최대 300개 데이터이긴 하지만, JpaRepository의 saveAll 메서드를 호출해 저장 시 300개의 insert 쿼리가 따로 나간다는 점이 조금 마음에 걸렸다. 사실상 saveAll은 사용하지 말자는 것은 정해진 듯 보였고, 다음 고민거리는 대체자로 무엇을 사용할 것인가였다. 가장 일반적으로 사용되는 대안은 JdbcTemplate이었으나, 아예 문자열로 쿼리를 박아버리는 방식 자체가 찝찝해 다른 방법이 있는지 찾아보고 있던 상황이었다. 그러던 중 친구랑 나눈 대화가 실험욕구를 자극했다. 본론 그래서 JPARepository.saveAll과 JdbcTemplate.ba..
Mock에 대한 이해 Spring에서는 DI 컨테이너에서 객체들 간의 의존성을 자동으로 관리해주기 때문에, 개발자는 소스 코드 상에서 의존성 주입에 대해 크게 신경쓰지 않고 개발할 수 있다. 하지만, 이렇게 작성한 소스 코드를 단위 테스트하는 과정에서 객체들 간 맺어진 의존성은 객체들이 서로 영향을 끼치도록 하여 테스트에서 각 객체들 간의 독립성을 해치고 테스트 코드의 신뢰성을 떨어트릴 수 있다. @RequiredArgsConstructor public class BookService { private final BookRepository bookRepository; public List getBooksUnderPrice(int price) { List allBooks = bookRepository.fi..