BorrowMe / Engineering case

팀 시연이 끝난 코드를 다시 검증 가능한 상태로 만들기

과거 개선 수치를 되풀이하지 않고 현재 코드가 지켜야 할 조회 SQL 상한과 재고 불변식을 테스트로 남겼습니다.

GitHub에서 코드 보기 ↗
User impact

상품이 늘수록 목록이 느려지거나 동시에 예약한 수보다 재고가 더 많이 줄면 대여 서비스의 기본 신뢰가 깨집니다.

01

어떻게 깨지는가

  • DTO 조립 중 연관 객체를 순회하면 상품 수만큼 SQL이 다시 늘 수 있습니다.
  • 재고를 읽고 감소시키는 사이에 다른 요청이 같은 수량을 읽을 수 있습니다.
  • 같은 취소가 겹치면 이미 반납한 수량이 다시 복원될 수 있습니다.

02

지켜야 할 경계

  • 현재 저장소에서 반복 가능한 검증만 공개합니다.
  • 과거 팀 개발과 2026 개인 보강을 같은 기여 기간으로 합치지 않습니다.
현재 코드에 남긴 두 회귀 방지선과거 개선 배수 대신 조회 SQL 상한과 재고 합계를 검증합니다.loadbulk lookupcountcountseparate invariantProduct listDTO assemblyFetch pathproduct + owner + tagsBulk followcandidate user IDsSQL guardfixed upper boundStock guardsuccess + remaining
  1. 상품·작성자·태그 fetch와 follow lookup을 나눕니다.
  2. Hibernate Statistics로 응답 조립까지의 SQL 상한을 확인합니다.
  3. 동시 예약에서는 성공 수와 남은 재고의 합을 검증합니다.
과거 개선 배수 대신 조회 SQL 상한과 재고 합계를 검증합니다.
현재 코드에 남긴 두 회귀 방지선
현재 코드에 남긴 두 회귀 방지선과거 개선 배수 대신 조회 SQL 상한과 재고 합계를 검증합니다.loadbulk lookupcountcountseparate invariantProduct listDTO assemblyFetch pathproduct + owner + tagsBulk followcandidate user IDsSQL guardfixed upper boundStock guardsuccess + remaining

03

선택한 설계

  • 상품·작성자·해시태그 fetch와 follow bulk lookup의 query 상한을 분리합니다.
  • 실제 MySQL 경계에서 동시 예약 성공 수와 남은 재고의 합을 확인합니다.
  • 예약과 상품 row를 잠그고 이미 취소된 요청은 재고를 다시 바꾸지 않게 합니다.

04

감수한 trade-off

  • 화려한 개선 배수 대신 현재 지켜지는 상한만 말합니다.
  • 테스트 fixture가 운영 트래픽을 대신하지 않는다는 한계를 함께 공개합니다.

05

어떻게 확인했는가

  • 상품 목록과 인증 응답의 SQL 상한을 Hibernate Statistics로 확인합니다.
  • 100명 동시 예약에서도 성공 수와 남은 재고의 합이 초기 재고와 같습니다.
  • 같은 취소를 20개 요청이 동시에 실행해도 재고는 한 번만 복원됩니다.

Sources

코드와 테스트로 돌아가기

  • 상품 목록 query-count 회귀 테스트

    공개 저장소에서 확인
    근거 ↗
  • 동시 예약·중복 취소 재고 불변식

    공개 저장소에서 확인
    근거 ↗
한계와 다음 확인
  • 현재 로컬 환경의 회귀 검증이며 production 성능을 뜻하지 않습니다.
  • 당시 서비스의 지속 운영을 주장하지 않습니다.