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

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)
  • 블로그 메뉴

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

  • 공지사항

  • 인기 글

  • 태그

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

  • 최근 글

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

티스토리툴바