목록기술블로그 (4)
Mini

문제상황jpashop 서비스에는 상품목록을 조회할수있는 api를 제공하고 있습니다.데이터가 백만건이 넘는상황에서도 원하는 성능으로 잘 작동하는지 보겠습니다.10만번째 페이지를 요청시, 실행시간이 약 600ms가 소요되며, 매우 느린상황입니다.원인분석쿼리 dsl 코드, 실행되는 sql 쿼리는 다음과 같습니다.public List findAllByQueryDsl(int pageNum) { return query .select(item) .from(item) .orderBy(item.id.desc()) .offset(pageNum * 10) .limit(10) .fetch();}SELEC..

문제상황어느부분에서 병목이 발생하는지, 그리고 어떤 부분에서 예외가 발생하는지를 로그를 통해 확인하기 위해 아래 요구사항에 맞춰 로그 추적기를 만들던 도중 문제가 발생했습니다.요구사항 모든 PUBLIC 메서드의 호출과 응답 정보를 로그로 출력 애플리케이션의 흐름을 변경하면 안됨 로그를 남긴다고 해서 비즈니스 로직의 동작에 영향을 주면 안됨 메서드 호출에 걸린 시간 정상 흐름과 예외 흐름 구분 예외 발생시 예외 정보가 남아야 함 메서드 호출의 깊이 표현 HTTP 요청을 구분 HTTP 요청 단위로 특정 ID를 남겨서 어떤 HTTP 요청에서 시작된 것인지 명확하게 구분이 가능해야 함 트랜잭션 ID (DB 트랜잭션X), 여기서는 하나의 HTTP 요청이 시작해서 끝날 때 까지를 하나의 트랜잭션이 라 함작동예시정상..

웹 에러인경우 문제상황없는경로로 접근시 웹사이트가 망한것 같은 에러페이지가 등장합니다.이를 개선해고자 합니다.해결방법간단히 아래경로에 html 파일을 추가해 주시만 하면 됩니다.에러발생시 전체 흐름은 아래와 같습니다.1. WAS(/error-ex, dispatchType=REQUEST) -> 필터 -> 서블릿 -> 인터셉터 -> 컨트롤러 2. WAS(여기까지 전파) 3. WAS 오류 페이지 확인 4. WAS(/error, dispatchType=ERROR) -> 필터(x) -> 서블릿 -> 인터셉터(x) -> 컨트롤러(/error/500) ->View이때, WAS까지 오류가 전달되면 WAS는 다시 /error 경로로 서버에 요청을 한다는 점이 키포인트 입니다.관련 스프링 코드를 보겠습니다.BasicErr..

들어가며안녕하세요. 백엔드 개발자 유동훈입니다. 쇼핑몰 프로젝트를 고도화 하면서 여러 클라이언트에서 접근시 재고감소 로직이 의도대로 작동하지 않는 문제를 발견하고 해결한 과정을 공유하고자 합니다.문제상황문제 상황을 재현하기 위한 테스트코드는 다음과 같습니다. @Test @DisplayName("20명이 5개씩 주문하면 재고가 100이 줄어야 한다.") public void stock_decrease_concurrency() throws Exception { // given int stockQuantity = 100; TestDataDto testData = testDataService.createTestData(stockQuantity); ..