Skip to content
isdnetworks
Go back

복제가 데려가야 하는 것들

(수정됨)

상품 복제 기능을 만들었더니 복제한 상품에 옵션이 없다는 문의가 왔다. 코드는 $product->replicate() 로 products 행 하나만 복제하고 있었다.

Table of contents

Open Table of contents

원인 — 행 하나만 복제한 결과

product_options 와 media 와 product_categories 와 stocks 가 전부 딸려 있는데 아무것도 따라가지 않았다. 복제라는 말이 무엇을 뜻하는지가 정해지지 않은 채로 구현된 상태였다.

행을 복사하는 것은 기술적으로 쉽지만 무엇까지 복제할지는 설계 결정이다. 그 결정을 안 하면 가장 좁은 범위로만 동작한다.

검증 — 딸린 것을 찾는 방법

이 테이블을 참조하는 관계를 information_schema.KEY_COLUMN_USAGE 로 뽑으려 했는데 외래키가 걸려 있지 않아 아무것도 안 나왔다. 그래서 information_schema.COLUMNS 에서 COLUMN_NAME = 'product_id' 로 전체 스키마를 훑어 아홉 개를 찾았다.

외래키가 있으면 관계로 찾고 없으면 컬럼 이름으로 찾는다. 관계 정의가 없다는 것이 딸린 것이 없다는 뜻은 아니었다.

조치 — 복제할 것과 아닌 것

아홉 중 넷만 복제 대상이었고 나머지는 복제하면 안 되는 것이었다. order_items 와 reviews 와 view_logs 와 price_histories 와 product_stats 가 그쪽이었다.

새 상품에 옛 주문이 붙거나 남이 쓴 후기가 붙으면 데이터가 거짓이 되므로 이력과 남이 만든 것은 복제 대상이 아니다. 복제한다는 말의 범위를 이렇게 명시하고 나서야 구현이 정해졌다.

주의 — 그대로 두면 안 되는 값

행을 그대로 복사하면 문제가 되는 컬럼도 있었다. product_code 는 겹치면 안 되고 name 에는 (복사) 표시가 필요하며 created_at 과 view_count 와 sold_count 는 새로 시작해야 한다.

가장 중요한 것이 status 였는데 ON_SALE 인 채로 복제되면 복제하자마자 팔린다. 이미지도 파일까지 복사해야 하는데 파일을 공유하면 한쪽을 지울 때 다른 쪽 이미지가 함께 사라진다.

배경 — 트랜잭션 범위와 분류 강제

데이터베이스 작업은 DB::transaction 으로 묶어서 중간에 실패했을 때 반쯤 복제된 상품이 안 남게 했다. 파일 복사는 두 가지 방법이 있었는데 트랜잭션 안에 넣는 것과 밖에서 따로 처리하는 것이다. 뒤쪽을 골랐다. 이유는 S3 복사가 오래 걸려 그동안 잠금을 쥐고 있게 돼서다. 대신 실패하면 이미지 없는 상품이 남는 것을 감수했고 그것은 다시 시도하면 된다.

어느 상품에서 복제했는지를 cloned_from_id 컬럼으로 남기니 복제로 만들어진 것이 얼마나 되는지 셀 수 있었고 원본을 고칠 때 복제본을 함께 봐야 하는지 물어볼 근거가 됐다. 새 연관이 생겼을 때 복제 대상인지 분류하지 않으면 시험이 실패하게 만들어서 판단이 빠지지 않게 했다.

정리


Share this post on:

Previous Post
이름이 같은데 다른 것
Next Post
한 겹 대신 여러 겹