Skip to content
isdnetworks
Go back

옵션 조합이 폭발했다

상품에 옵션이 여럿이었다.

크기   6종
색상   4종
수량   3종

Table of contents

Open Table of contents

배경 — 조합을 미리 만들었다

처음에는 조합을 전부 미리 만들었다.

6 × 4 × 3 = 72

상품 하나에 72행이다. 이유가 있었는데 조합마다 재고가 다르기 때문이다.

크기 A · 색 B  →  재고 5
크기 A · 색 C  →  재고 0

행이 있어야 재고를 붙일 수 있어서 등록할 때 데카르트 곱을 전부 만들어 뒀다.

행이 곱해서 늘어났다

상품이 늘면서 이 테이블이 커졌다.

상품 1,000개 × 평균 조합 50 = 5만 행

옵션 종류가 하나 늘면 행이 그 배수로 늘어난다. 그런데 세어 보니 대부분 재고가 0이었다.

실제로 파는 조합은 일부였고 나머지는 자리만 차지하고 있었다. 안 파는 조합까지 만들어 둔 것이다.

필요할 때 만들기로 했다

방향을 바꿨다. 미리 전부 만들고 재고를 0으로 두는 대신 파는 것만 만든다.

$stock = $model->get_stock($productId, $options);
$available = $stock ? $stock->qty : 0;

조회할 때 행이 없으면 품절로 처리했다. 없음이 곧 0이다. (product_id, opt1, opt2, opt3)UNIQUE KEY 를 걸어 중복도 막았다.

5만 행이 수천 행이 됐다. 대신 화면이 달라져야 했다. 전에는 행이 있으니 선택지를 목록으로 뽑았는데 이제는 행이 없는 조합이 있어 그럴 수 없다.

따로 둔 옵션 정의와 남길 것

어떤 옵션이 있는지를 따로 뒀다.

product_option
  product_id
  option_type   크기 / 색상
  option_value  A / B / C

정의와 재고를 나눈 것이다. 화면은 product_option 으로 선택지를 그리고 재고는 사용자가 고른 뒤에 조회한다.

그런데 살 수 없는 조합도 선택지에 나왔다. 크기 A 를 고르면 색상이 전부 표시되고 어떤 색을 고르면 그제야 품절이라는 것을 안다.

미리 표시하려면 조합마다 재고를 봐야 하는데 그러면 조회가 그만큼 는다.

$stocks = $model->get_all_stocks($productId);

조합마다 부르지 않고 그 상품의 재고 전부를 한 번에 가져왔는데 수천 행 전체가 아니라 그 상품 것만이라 양이 적었다.

가져온 것을 화면 쪽에서 선택지에 반영해 재고 있는 조합은 선택 가능하게 하고 없는 조합은 회색으로 뒀다. 고르기 전에 알 수 있게 된 것이다.

이 방식은 상품 하나의 조합 수가 많지 않아서 가능했다. 옵션 5종에 각 10개면 10만 조합인데 그런 상품은 없었다. 다만 언제 다시 봐야 하는지를 적어 뒀다.

한 상품의 조합이 수백을 넘으면 다시 본다

재고가 0이 된 행을 지울지도 정해야 했다. 지우면 행이 주는 대신 판 적 있는 조합인지 모르게 되고 남기면 이력이 남는다.

남기기로 했는데 팔린 적 있는 조합 자체가 정보였기 때문이다. 그리고 판 적이 있는 조합은 주문 이력이 참조하고 있어서 애초에 지울 수도 없었다. InnoDB 는 ON DELETE 를 안 적으면 NO ACTION 이 되고 그것이 RESTRICT 와 같아서 지우려 하면 ER_ROW_IS_REFERENCED_2 로 막힌다.

다만 오래 0인 것은 정리했다. NOT EXISTS 로 주문 이력이 없는 것만 골라 1년 넘게 0이면 지웠다. 조건을 붙여서 지운 것이다.

정리


Share this post on:

Previous Post
온 김에 더 고칠지 정했다
Next Post
조건 하나가 전부를 걸렀다