재고 차감, 검증은 몇 번 해야 할까?

2025. 11. 14. 17:41·Loopers 2기

재고 차감, 검증은 몇 번 해야 할까?

TL;DR: 주문 생성 시 재고 검증과 차감이 중복·분산돼 혼란스러웠다. 검증을 한 곳에 명확히 두고, 메서드 호출 방식을 통일하는 게 핵심임을 배웠다.


문제 발견

주문 생성 로직을 구현하다 보니 재고 처리 방식이 어색했다.

// Order.create()
product.validateStock(quantity)   // 검증
OrderItem.of(product, quantity)

// OrderService.createOrder()
order.items.forEach {
    it.product.decreaseStock(it.quantity)  // 차감만
}
  • Order 생성 시 검증
  • OrderService에서 차감 → 검증을 두 번? 한 번? 헷갈렸다.

Product에 메서드가 3개나…

fun validateStock(quantity: Quantity) { ... }           // 검증만
fun decreaseStock(quantity: Quantity) { ... }           // 차감만 (VO 내부 검증)
fun decreaseStockWithValidation(quantity: Quantity) { ... } // 검증+차감

"어느 걸 써야 정답이지?" → 일관성 없는 설계의 신호


원인

  • decreaseStock()은 재사용성을 위해 검증 없이 설계
  • Stock VO 내부에도 검증 존재 → 검증이 두 곳에 중복
  • 에러 메시지에 상품명을 넣고 싶어 Product에도 검증 추가

선택지

방식 설명 장점 단점

1. 검증+차감 통합 decreaseStock()이 항상 검증 호출 측 부담 ↓ VO 검증 중복
2. VO 검증만 믿기 엔티티 검증 제거 중복 없음 에러 메시지 제한

내가 선택한 방식: 2번 + 타협

// Product.kt
fun decreaseStock(quantity: Quantity) {
    stock = stock.decrease(quantity.value)  // VO가 검증
}

fun validateStock(quantity: Quantity) {     // 상품명 포함 에러용
    if (!hasEnoughStock(quantity)) {
        throw CoreException(ErrorType.INSUFFICIENT_STOCK,
            "재고 부족. 상품: $name (요청: ${quantity.value})")
    }
}
  • Order.create() → validateStock() (구체적 에러)
  • OrderService → decreaseStock() (VO 검증 위임)

여전히 불편한 점

  1. validateStock()이 public이라 오용 가능성
  2. 검증 후 차감 사이 동시성 문제 (트랜잭션/락 필요)
  3. 메서드 2개 → 여전히 많음

배운 점

  1. 검증은 한 곳에 명확히 (VO or 엔티티)
  2. 메서드 많으면 설계 의심
  3. 일관성 > 완벽함

다음엔 이렇게

fun decreaseStock(quantity: Quantity) {
    if (!hasEnoughStock(quantity)) {
        throw CoreException(ErrorType.INSUFFICIENT_STOCK,
            "재고 부족. 상품: $name (요청: ${quantity.value}, 재고: ${stock.quantity})")
    }
    stock = stock.decrease(quantity.value)
}

메서드 하나, 검증+차감+에러 메시지 통일


재고 차감은 단순해 보이지만, "누가 검증할까? 몇 번 할까? 어떻게 일관되게 할까?" 이 고민이 좋은 설계를 만든다.

다음엔 더 간결하게!

'Loopers 2기' 카테고리의 다른 글

쿠폰 중복 사용 버그, 비관적 락 한 줄로 해결하기  (0) 2025.11.21
Round 2 회고  (0) 2025.11.07
Round 1 회고  (0) 2025.10.31
'Loopers 2기' 카테고리의 다른 글
  • 쿠폰 중복 사용 버그, 비관적 락 한 줄로 해결하기
  • Round 2 회고
  • Round 1 회고
고구마와 감자
고구마와 감자
Amor DevFati는 김연자-Amor Fati에 Development(개발)의 Dev 를 첨가하여 만든 이름
  • 고구마와 감자
    Amor DevFati(아모르 개발파티)
    고구마와 감자
  • 전체
    오늘
    어제
    • 분류 전체보기 (156)
      • Loopers 2기 (4)
      • 스프링 (5)
      • 알고리즘 (113)
        • 백준 (70)
        • 프로그래머스 (7)
        • 인프런_자바코테강의 (20)
        • 리트코드 (5)
        • 해커랭크 (0)
        • 코드업 (3)
        • 이것저것 (7)
      • 자바 (7)
      • GIT (0)
      • 파이썬 (1)
      • 개발이론 (4)
      • JPA (0)
      • 김영한 강의 (13)
        • 모든 개발자를 위한 HTTP 웹 기본 지식 (2)
        • 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 (6)
        • 스프링 핵심 원리 - 기본편 (5)
      • 일기 및 아무말 적기 (6)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    4458
    1247
    Mini Fantasy War
    더하기 3
    카이사르 암호
    그대로출력하기2
    11966
    홀수일까 짝수일까
    첫 글자를 대문자로
    5988
    3059
    10409
    14656
    2의 제곱인가
    할로윈의 사탕
    2857
    조교는 새디스트야!!
    1598
    10178
    16673
    스프링 핵심 원리
    꼬리를 무는 숫자 나열
    고려대학교에는 공식 와인이 있다
    등장하지 않는 문자의 합
    2921
    남욱이의 닭장
    11023
    백준
    전투 드로이드 가격
    5361
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
고구마와 감자
재고 차감, 검증은 몇 번 해야 할까?
상단으로

티스토리툴바