공개 자산 스토리지를 설정해도 레이아웃 배경 이미지가 매번 오리진 PHP 를 거쳐 서빙되던 결함을 고친다 (https://github.com/gnuboard/g7/issues/134). 판정 기준은 운영자가 명시 선언한 core.storage.public_asset_disk 와 행 disk 의 일치다 — 디스크의 url 설정 유무로 판정하면 비공개 버킷에 공개 URL 이 설정된 구성에서 발급된 주소가 403 이 되어 그 이미지가 전부 깨진다. 전수조사에서 함께 처리한 것: 게시판 첨부 응답 url 칸(항상 null → 게이트가 살아 있는 서빙 URL), 페이지의 미배선 메서드 삭제, 확장 카테고리별 저장소 URL·경로 조회 교정, 그리고 이번 변경이 새로 만드는 고아 disk 위험 방어 (무인증 공개 서빙 라우트가 500 이 되는 것을 404 로 degrade). 문서화 하네스도 함께 보강한다. 실측을 수행하고도 이력 문서에는 판정만 남기면 대화 로그가 사라진 뒤 아무에게도 도달하지 않는데, 그 강제가 보고 형식에만 있었다.
41 KiB
이커머스 — 데이터 모델
모델·소유 테이블·마이그레이션·Enum · 진입점: AGENTS.md
모델
| 모델 | 테이블 | fillable | 관계 | 특성 |
|---|---|---|---|---|
Brand |
ecommerce_brands |
7 | creator→User, updater→User, products→Product | SoftDeletes, 검색 색인 |
Cart |
ecommerce_carts |
6 | user→User, product→Product, productOption→ProductOption | - |
Category |
ecommerce_categories |
10 | parent→self, children→self, descendants→self, images→CategoryImage, products→Product | 검색 색인 |
CategoryImage |
ecommerce_category_images |
15 | category→Category, creator→User | SoftDeletes |
ClaimReason |
ecommerce_claim_reasons |
10 | creator→User, updater→User | HasUserOverrides |
Coupon |
ecommerce_promotion_coupons |
22 | issues→CouponIssue, products→Product, includedProducts→Product, excludedProducts→Product, categories→Category, includedCategories→Category, 외 2개 | SoftDeletes, 검색 색인 |
CouponIssue |
ecommerce_promotion_coupon_issues |
9 | coupon→Coupon, user→User, order→Order | - |
EcommerceStat |
ecommerce_stats |
4 | - | - |
EcommerceUserProfile |
ecommerce_user_profiles |
3 | user→User | - |
ExtraFeeTemplate |
ecommerce_shipping_policy_extra_fee_templates |
7 | creator→User, updater→User | - |
HasDirectAssetUrl |
(규약) | - | - | - |
MileageBalance |
ecommerce_mileage_balances |
9 | user→User | - |
MileageTransaction |
ecommerce_mileage_transactions |
16 | user→User, order→Order, orderOption→OrderOption, grantedByUser→User, sourceTransaction→self | - |
Order |
ecommerce_orders |
65 | user→User, options→OrderOption, firstOption→OrderOption, addresses→OrderAddress, shippingAddress→OrderAddress, billingAddress→OrderAddress, 외 8개 | SoftDeletes |
OrderAddress |
ecommerce_order_addresses |
23 | order→Order | - |
OrderCancel |
ecommerce_order_cancels |
10 | order→Order, cancelOptions→OrderCancelOption, refund→OrderRefund, cancelledByUser→User | - |
OrderCancelOption |
ecommerce_order_cancel_options |
10 | orderCancel→OrderCancel, order→Order, orderOption→OrderOption, processedByUser→User | - |
OrderCashReceipt |
ecommerce_order_cash_receipts |
16 | order→Order, payment→OrderPayment | - |
OrderOption |
ecommerce_order_options |
57 | order→Order, parentOption→self, childOptions→self, splitOptions→self, product→Product, productOption→ProductOption, 외 4개 | - |
OrderPayment |
ecommerce_order_payments |
58 | order→Order, taxInvoices→OrderTaxInvoice, cashReceipts→OrderCashReceipt | - |
OrderRefund |
ecommerce_order_refunds |
25 | order→Order, orderCancel→OrderCancel, refundOptions→OrderRefundOption, processedByUser→User | - |
OrderRefundOption |
ecommerce_order_refund_options |
12 | orderRefund→OrderRefund, order→Order, orderOption→OrderOption, processedByUser→User | - |
OrderShipping |
ecommerce_order_shippings |
32 | order→Order, orderOption→OrderOption, shippingPolicy→ShippingPolicy, carrier→ShippingCarrier | - |
OrderTaxInvoice |
ecommerce_order_tax_invoices |
21 | order→Order, payment→OrderPayment | - |
Product |
ecommerce_products |
34 | options→ProductOption, images→ProductImage, categories→Category, brand→Brand, commonInfo→ProductCommonInfo, shippingPolicy→ShippingPolicy, 외 6개 | SoftDeletes, 검색 색인 |
ProductAdditionalOption |
ecommerce_product_additional_options |
4 | product→Product, values→ProductAdditionalOptionValue | - |
ProductAdditionalOptionValue |
ecommerce_product_additional_option_values |
8 | additionalOption→ProductAdditionalOption | - |
ProductCommonInfo |
ecommerce_product_common_infos |
6 | products→Product | 검색 색인 |
ProductImage |
ecommerce_product_images |
16 | product→Product, creator→User | SoftDeletes |
ProductInquiry |
ecommerce_product_inquiries |
7 | product→Product, user→User, inquirable→? | SoftDeletes |
ProductLabel |
ecommerce_product_labels |
4 | assignments→ProductLabelAssignment | - |
ProductLabelAssignment |
ecommerce_product_label_assignments |
4 | product→Product, label→ProductLabel | - |
ProductNotice |
ecommerce_product_notices |
2 | product→Product | - |
ProductNoticeTemplate |
ecommerce_product_notice_templates |
5 | - | - |
ProductOption |
ecommerce_product_options |
18 | product→Product | - |
ProductReview |
ecommerce_product_reviews |
13 | product→Product, orderOption→OrderOption, user→User, replyAdmin→User, images→ProductReviewImage | SoftDeletes |
ProductReviewImage |
ecommerce_product_review_images |
15 | review→ProductReview, creator→User | SoftDeletes |
ProductWishlist |
ecommerce_product_wishlists |
2 | user→User, product→Product | - |
SearchPreset |
ecommerce_search_presets |
6 | user→User | - |
Sequence |
ecommerce_sequences |
12 | - | - |
SequenceCode |
ecommerce_sequence_codes |
2 | - | - |
ShippingCarrier |
ecommerce_shipping_carriers |
9 | creator→User, updater→User | HasUserOverrides |
ShippingPolicy |
ecommerce_shipping_policies |
6 | countrySettings→ShippingPolicyCountrySetting, listCountrySettings→ShippingPolicyCountrySetting | - |
ShippingPolicyCountrySetting |
ecommerce_shipping_policy_country_settings |
17 | shippingPolicy→ShippingPolicy | - |
ShippingType |
ecommerce_shipping_types |
8 | creator→User, updater→User | HasUserOverrides |
TempOrder |
ecommerce_temp_orders |
6 | user→User | - |
UserAddress |
ecommerce_user_addresses |
16 | user→User | - |
47개 모델은 다섯 계열로 읽습니다.
| 계열 | 모델 | 읽는 요령 |
|---|---|---|
| 카탈로그 | Product · ProductOption · ProductAdditionalOption(Value) · ProductImage · Category · CategoryImage · Brand · ProductLabel(Assignment) · ProductCommonInfo · ProductNotice(Template) |
판매 단위는 Product 가 아니라 ProductOption 입니다. 재고·가격·주문 연결이 전부 옵션에 걸립니다 |
| 주문 | Order · OrderOption · OrderAddress · OrderPayment · OrderShipping · OrderCashReceipt · OrderTaxInvoice |
Order fillable 65 · OrderOption 57 · OrderPayment 58 — 이 셋이 큰 이유는 주문 시점의 값을 전부 스냅샷으로 복사하기 때문입니다. 상품명·가격·배송정책·통화 정보가 원본을 참조하지 않고 복제됩니다 |
| 취소·환불 | OrderCancel(Option) · OrderRefund(Option) · ClaimReason |
단위가 주문이 아니라 옵션입니다. *Option 쪽이 실제 처리 단위이고 상위는 묶음입니다 |
| 프로모션·적립 | Coupon · CouponIssue · MileageTransaction · MileageBalance |
MileageTransaction 이 원장(SSoT), MileageBalance 는 단방향 파생 캐시입니다 |
| 배송·회원·기타 | ShippingPolicy(CountrySetting) · ShippingCarrier · ShippingType · ExtraFeeTemplate · UserAddress · Cart · TempOrder · ProductWishlist · ProductReview(Image) · ProductInquiry · SearchPreset · Sequence(Code) · EcommerceStat · EcommerceUserProfile |
TempOrder 는 결제창 왕복 동안만 사는 임시 저장소이며 스케줄이 정리합니다 |
HasDirectAssetUrl 은 모델이 아니라 규약(trait) 입니다 — 이미지 계열 모델이 저장소 종류에
관계없이 같은 방식으로 자산 URL 을 내도록 묶습니다. 표에 모델처럼 잡힌 것은 수집기가 클래스
파일 단위로 세기 때문이며, 테이블이 (규약) 인 것이 그 표식입니다.
이 규약은 권한 검사가 걸린 자산에는 배선하지 않는 것이 원칙입니다 — 직접 URL 은 서버
스트리밍 경로의 검사를 우회합니다. 예외가 하나 있습니다: ProductReviewImage 는 이 규약을
씁니다. 리뷰 노출 상태는 리소스 층에서 걸러지므로 숨김 리뷰의 이미지는 응답에 실리지
않지만, 공개 자산 디스크를 켠 상태에서 이미 발급된 직접 URL 을 아는 쪽은 노출→숨김 전환
이후에도 그 파일에 접근할 수 있습니다. 노출 상태를 접근 차단 수단으로 써야 하는 운용이라면
그 카테고리에 공개 자산 디스크를 적용하지 않아야 합니다.
HasUserOverrides 를 쓰는 셋(ClaimReason · ShippingCarrier · ShippingType)은 시더가
기본값을 넣지만 운영자가 고칠 수 있는 테이블입니다. 시더를 다시 돌려도 운영자 수정분은
보존되므로, 이 셋의 기본 데이터를 바꿀 때는 시더만 고쳐서는 기설치본에 반영되지 않습니다.
검색 색인 대상은 Product · Category · Brand · Coupon · ProductCommonInfo 다섯이며,
색인 갱신은 서비스가 아니라 SearchProductsListener 가 훅으로 받아 처리합니다.
소유 테이블
| 테이블 | 모델 |
|---|---|
ecommerce_brands |
Brand |
ecommerce_carts |
Cart |
ecommerce_categories |
Category |
ecommerce_category_images |
CategoryImage |
ecommerce_claim_reasons |
ClaimReason |
ecommerce_mail_templates |
- |
ecommerce_mileage_balances |
MileageBalance |
ecommerce_mileage_transactions |
MileageTransaction |
ecommerce_order_addresses |
OrderAddress |
ecommerce_order_cancel_options |
OrderCancelOption |
ecommerce_order_cancels |
OrderCancel |
ecommerce_order_cash_receipts |
OrderCashReceipt |
ecommerce_order_options |
OrderOption |
ecommerce_order_payments |
OrderPayment |
ecommerce_order_refund_options |
OrderRefundOption |
ecommerce_order_refunds |
OrderRefund |
ecommerce_order_shippings |
OrderShipping |
ecommerce_order_tax_invoices |
OrderTaxInvoice |
ecommerce_orders |
Order |
ecommerce_product_additional_option_values |
ProductAdditionalOptionValue |
ecommerce_product_additional_options |
ProductAdditionalOption |
ecommerce_product_categories |
- |
ecommerce_product_common_infos |
ProductCommonInfo |
ecommerce_product_images |
ProductImage |
ecommerce_product_inquiries |
ProductInquiry |
ecommerce_product_label_assignments |
ProductLabelAssignment |
ecommerce_product_labels |
ProductLabel |
ecommerce_product_logs |
- |
ecommerce_product_notice_templates |
ProductNoticeTemplate |
ecommerce_product_notices |
ProductNotice |
ecommerce_product_options |
ProductOption |
ecommerce_product_review_images |
ProductReviewImage |
ecommerce_product_reviews |
ProductReview |
ecommerce_product_wishlists |
ProductWishlist |
ecommerce_products |
Product |
ecommerce_promotion_coupon_categories |
- |
ecommerce_promotion_coupon_issues |
CouponIssue |
ecommerce_promotion_coupon_products |
- |
ecommerce_promotion_coupons |
Coupon |
ecommerce_search_presets |
SearchPreset |
ecommerce_sequence_codes |
SequenceCode |
ecommerce_sequences |
Sequence |
ecommerce_shipping_carriers |
ShippingCarrier |
ecommerce_shipping_policies |
ShippingPolicy |
ecommerce_shipping_policy_country_settings |
ShippingPolicyCountrySetting |
ecommerce_shipping_policy_extra_fee_templates |
ExtraFeeTemplate |
ecommerce_shipping_types |
ShippingType |
ecommerce_stats |
EcommerceStat |
ecommerce_temp_orders |
TempOrder |
ecommerce_user_addresses |
UserAddress |
ecommerce_user_profiles |
EcommerceUserProfile |
51개 테이블은 전부 ecommerce_ 접두사를 갖습니다. 모델 열이 - 인 다섯은 각각 이유가 있습니다:
| 테이블 | 왜 모델이 없는가 |
|---|---|
ecommerce_product_categories |
상품↔카테고리 다대다 피벗 (관계로만 접근) |
ecommerce_promotion_coupon_products · ecommerce_promotion_coupon_categories |
쿠폰의 적용/제외 대상 피벗 — 한 쿠폰이 포함·제외 두 방향을 함께 갖습니다 |
ecommerce_product_logs |
상품 변경 이력 적재 전용 (읽기는 집계 쿼리로) |
ecommerce_mail_templates |
알림 본문 템플릿. 알림 정의 10종이 여기서 본문을 찾습니다 |
테이블을 추가·변경할 때 DB CASCADE 에 삭제를 맡기지 않습니다. 주문·상품 삭제는 훅 발행· 파일 정리·활동 로그가 함께 일어나야 하므로 Service 가 명시적으로 지웁니다 — CASCADE 로 지우면 그 부가 처리가 통째로 건너뛰어지고 아무 오류도 남지 않습니다.
주문 계열(ecommerce_orders · ecommerce_order_*)과 상품·리뷰·문의 계열은 SoftDeletes 를
씁니다. 목록 쿼리를 새로 만들 때 withTrashed() 를 습관적으로 붙이면 취소·삭제된 행이 매출
집계에 섞이므로 주의합니다.
마이그레이션
마이그레이션 102개.
| 파일 | 생성 테이블 | 변경 테이블 | down() |
|---|---|---|---|
2026_04_01_000001_create_ecommerce_categories_table.php |
ecommerce_categories |
- | ✅ |
2026_04_01_000002_create_ecommerce_category_images_table.php |
ecommerce_category_images |
- | ✅ |
2026_04_01_000003_create_ecommerce_brands_table.php |
ecommerce_brands |
- | ✅ |
2026_04_01_000004_create_ecommerce_search_presets_table.php |
ecommerce_search_presets |
- | ✅ |
2026_04_01_000005_create_ecommerce_products_table.php |
ecommerce_products |
ecommerce_products |
✅ |
2026_04_01_000006_create_ecommerce_product_images_table.php |
ecommerce_product_images |
- | ✅ |
2026_04_01_000007_create_ecommerce_product_options_table.php |
ecommerce_product_options |
- | ✅ |
2026_04_01_000008_create_ecommerce_product_additional_options_table.php |
ecommerce_product_additional_options |
- | ✅ |
2026_04_01_000009_create_ecommerce_product_labels_table.php |
ecommerce_product_labels |
- | ✅ |
2026_04_01_000010_create_ecommerce_product_label_assignments_table.php |
ecommerce_product_label_assignments |
- | ✅ |
2026_04_01_000011_create_ecommerce_product_logs_table.php |
ecommerce_product_logs |
- | ✅ |
2026_04_01_000012_create_ecommerce_product_notice_templates_table.php |
ecommerce_product_notice_templates |
- | ✅ |
2026_04_01_000013_create_ecommerce_product_notices_table.php |
ecommerce_product_notices |
- | ✅ |
2026_04_01_000014_create_ecommerce_product_common_infos_table.php |
ecommerce_product_common_infos |
- | ✅ |
2026_04_01_000015_create_ecommerce_product_categories_table.php |
ecommerce_product_categories |
- | ✅ |
2026_04_01_000016_create_ecommerce_product_wishlists_table.php |
ecommerce_product_wishlists |
- | ✅ |
2026_04_01_000017_create_ecommerce_orders_table.php |
ecommerce_orders |
- | ✅ |
2026_04_01_000018_create_ecommerce_order_options_table.php |
ecommerce_order_options |
- | ✅ |
2026_04_01_000019_create_ecommerce_order_addresses_table.php |
ecommerce_order_addresses |
- | ✅ |
2026_04_01_000020_create_ecommerce_order_payments_table.php |
ecommerce_order_payments |
- | ✅ |
2026_04_01_000021_create_ecommerce_order_shippings_table.php |
ecommerce_order_shippings |
- | ✅ |
2026_04_01_000022_create_ecommerce_order_tax_invoices_table.php |
ecommerce_order_tax_invoices |
- | ✅ |
2026_04_01_000023_create_ecommerce_carts_table.php |
ecommerce_carts |
- | ✅ |
2026_04_01_000024_create_ecommerce_temp_orders_table.php |
ecommerce_temp_orders |
- | ✅ |
2026_04_01_000025_create_ecommerce_shipping_policies_table.php |
ecommerce_shipping_policies |
- | ✅ |
2026_04_01_000026_create_ecommerce_shipping_policy_extra_fee_templates_table.php |
ecommerce_shipping_policy_extra_fee_templates |
- | ✅ |
2026_04_01_000027_create_ecommerce_shipping_policy_country_settings_table.php |
ecommerce_shipping_policy_country_settings |
- | ✅ |
2026_04_01_000028_create_ecommerce_shipping_carriers_table.php |
ecommerce_shipping_carriers |
- | ✅ |
2026_04_01_000029_create_ecommerce_promotion_coupons_table.php |
ecommerce_promotion_coupons |
- | ✅ |
2026_04_01_000030_add_vat_amount_to_ecommerce_orders_table.php |
- | ecommerce_orders |
✅ |
2026_04_01_000031_create_ecommerce_promotion_coupon_issues_table.php |
ecommerce_promotion_coupon_issues |
- | ✅ |
2026_04_01_000032_create_ecommerce_promotion_coupon_products_table.php |
ecommerce_promotion_coupon_products |
- | ✅ |
2026_04_01_000033_create_ecommerce_promotion_coupon_categories_table.php |
ecommerce_promotion_coupon_categories |
- | ✅ |
2026_04_01_000034_create_ecommerce_sequences_table.php |
ecommerce_sequences |
- | ✅ |
2026_04_01_000035_create_ecommerce_sequence_codes_table.php |
ecommerce_sequence_codes |
- | ✅ |
2026_04_01_000036_create_ecommerce_user_addresses_table.php |
ecommerce_user_addresses |
- | ✅ |
2026_04_01_000037_create_ecommerce_mail_templates_table.php |
ecommerce_mail_templates |
- | ✅ |
2026_04_01_000038_change_ecommerce_user_addresses_name_to_string.php |
- | ecommerce_user_addresses |
✅ |
2026_04_01_000039_create_ecommerce_product_reviews_table.php |
ecommerce_product_reviews |
ecommerce_product_reviews |
✅ |
2026_04_01_000040_create_ecommerce_product_review_images_table.php |
ecommerce_product_review_images |
ecommerce_product_review_images |
✅ |
2026_04_01_000041_create_ecommerce_order_cancels_table.php |
ecommerce_order_cancels |
- | ✅ |
2026_04_01_000042_create_ecommerce_order_cancel_options_table.php |
ecommerce_order_cancel_options |
- | ✅ |
2026_04_01_000043_create_ecommerce_order_refunds_table.php |
ecommerce_order_refunds |
- | ✅ |
2026_04_01_000044_create_ecommerce_order_refund_options_table.php |
ecommerce_order_refund_options |
- | ✅ |
2026_04_01_000045_add_cancellation_columns_to_ecommerce_orders_and_options.php |
- | ecommerce_orders, ecommerce_order_options |
✅ |
2026_04_01_000046_add_mc_refund_columns_to_ecommerce_order_refunds_table.php |
- | ecommerce_order_refunds |
✅ |
2026_04_01_000047_modify_i18n_columns_in_ecommerce_order_options_table.php |
- | ecommerce_order_options |
✅ |
2026_04_01_000048_create_ecommerce_claim_reasons_table.php |
ecommerce_claim_reasons |
- | ✅ |
2026_04_01_000049_add_confirmed_at_to_ecommerce_order_options_table.php |
- | ecommerce_order_options |
✅ |
2026_04_01_000050_drop_ecommerce_product_logs_table.php |
ecommerce_product_logs |
- | ✅ |
2026_04_01_000051_remove_url_from_ecommerce_product_images_and_review_images_table.php |
- | ecommerce_product_images, ecommerce_product_review_images |
✅ |
2026_04_01_000052_create_ecommerce_product_inquiries_table.php |
ecommerce_product_inquiries |
ecommerce_product_inquiries |
✅ |
2026_04_01_000053_add_indexes_to_ecommerce_products_table.php |
- | ecommerce_products |
✅ |
2026_04_01_000054_add_indexes_to_ecommerce_orders_table.php |
- | ecommerce_orders |
✅ |
2026_04_01_000055_add_indexes_to_ecommerce_order_addresses_table.php |
- | ecommerce_order_addresses |
✅ |
2026_04_01_000056_drop_carrier_name_from_ecommerce_order_shippings_table.php |
- | ecommerce_order_shippings |
✅ |
2026_04_01_000057_add_fulltext_indexes_to_ecommerce_products_table.php |
- | ecommerce_products |
✅ |
2026_04_01_000058_add_fulltext_indexes_to_ecommerce_categories_table.php |
- | ecommerce_categories |
✅ |
2026_04_01_000059_add_fulltext_indexes_to_ecommerce_brands_table.php |
- | ecommerce_brands |
✅ |
2026_04_01_000060_add_fulltext_indexes_to_ecommerce_promotion_coupons_table.php |
- | ecommerce_promotion_coupons |
✅ |
2026_04_01_000061_add_fulltext_indexes_to_ecommerce_product_common_infos_table.php |
- | ecommerce_product_common_infos |
✅ |
2026_04_01_000062_create_ecommerce_shipping_types_table.php |
ecommerce_shipping_types |
- | ✅ |
2026_04_01_000063_add_custom_shipping_name_to_country_settings.php |
- | ecommerce_shipping_policy_country_settings |
✅ |
2026_04_13_000001_drop_ecommerce_mail_templates_table.php |
ecommerce_mail_templates |
- | ✅ |
2026_04_13_000002_add_user_overrides_to_ecommerce_claim_reasons_table.php |
- | ecommerce_claim_reasons |
✅ |
2026_04_19_000000_add_user_overrides_to_ecommerce_shipping_types_table.php |
- | ecommerce_shipping_types |
✅ |
2026_04_20_000001_add_user_overrides_to_ecommerce_shipping_carriers_table.php |
- | ecommerce_shipping_carriers |
✅ |
2026_05_16_000001_add_unique_index_to_transaction_id_on_ecommerce_order_payments_table.php |
- | - | ✅ |
2026_06_02_000001_add_guest_lookup_password_hash_to_ecommerce_orders_table.php |
- | ecommerce_orders |
✅ |
2026_06_11_000001_create_ecommerce_mileage_transactions_table.php |
ecommerce_mileage_transactions |
- | ✅ |
2026_06_11_000002_add_delivered_at_to_ecommerce_order_options_table.php |
- | ecommerce_order_options |
✅ |
2026_06_11_000003_add_mc_subtotal_earned_points_amount_to_ecommerce_order_options_table.php |
- | ecommerce_order_options |
✅ |
2026_06_11_000004_create_ecommerce_mileage_balances_table.php |
ecommerce_mileage_balances |
- | ✅ |
2026_06_16_000001_add_is_mileage_deducted_to_ecommerce_orders_table.php |
- | ecommerce_orders |
✅ |
2026_06_16_000001_create_ecommerce_stats_table.php |
ecommerce_stats |
- | ✅ |
2026_06_22_000001_add_api_config_to_ecommerce_shipping_policy_country_settings_table.php |
- | ecommerce_shipping_policy_country_settings |
✅ |
2026_06_22_000001_add_cancelled_at_to_ecommerce_orders_table.php |
- | ecommerce_orders |
✅ |
2026_06_23_000001_add_seo_sync_flags_to_ecommerce_products_table.php |
- | ecommerce_products |
✅ |
2026_06_24_000001_convert_seo_meta_to_multilingual_json.php |
- | - | ✅ |
2026_06_24_000001_create_ecommerce_user_profiles_table.php |
ecommerce_user_profiles |
- | ✅ |
2026_06_24_000010_create_ecommerce_product_additional_option_values_table.php |
ecommerce_product_additional_option_values |
- | ✅ |
2026_06_24_000011_add_additional_option_selections_to_ecommerce_carts_table.php |
- | ecommerce_carts |
✅ |
2026_06_24_000012_add_additional_options_columns_to_ecommerce_order_options_table.php |
- | ecommerce_order_options |
✅ |
2026_06_25_000001_add_preferred_shipping_country_to_ecommerce_user_profiles_table.php |
- | ecommerce_user_profiles |
✅ |
2026_06_25_000001_change_ecommerce_product_prices_to_decimal.php |
- | ecommerce_products, ecommerce_product_options |
✅ |
2026_06_25_000002_add_shipping_snapshot_to_ecommerce_order_cancels_table.php |
- | ecommerce_order_cancels |
✅ |
2026_06_25_000013_add_allow_custom_text_to_ecommerce_product_additional_option_values_table.php |
- | ecommerce_product_additional_option_values |
✅ |
2026_06_26_000001_add_delivery_memo_label_to_ecommerce_order_addresses_table.php |
- | ecommerce_order_addresses |
✅ |
2026_06_26_000002_add_orderer_locale_to_ecommerce_order_addresses_table.php |
- | ecommerce_order_addresses |
✅ |
2026_07_09_000001_create_ecommerce_order_cash_receipts_table.php |
ecommerce_order_cash_receipts |
- | ✅ |
2026_07_09_000002_add_cash_equivalent_amount_to_ecommerce_orders_table.php |
- | ecommerce_orders, ecommerce_order_options |
✅ |
2026_07_09_000003_add_cash_receipt_identifier_encrypted_to_ecommerce_order_payments_table.php |
- | ecommerce_order_payments |
✅ |
2026_07_09_000004_add_cash_receipt_identifier_type_to_ecommerce_order_payments_table.php |
- | ecommerce_order_payments |
✅ |
2026_07_27_000001_add_mileage_policy_snapshot_to_ecommerce_orders_table.php |
- | ecommerce_orders |
✅ |
2026_07_30_000001_add_created_at_indexes_to_ecommerce_product_reviews_table.php |
- | ecommerce_product_reviews |
✅ |
2026_07_31_000001_add_shipped_at_index_to_ecommerce_order_shippings_table.php |
- | ecommerce_order_shippings |
✅ |
2026_08_01_000001_add_list_sort_indexes_to_ecommerce_tables.php |
- | - | ✅ |
2026_08_02_000001_add_storefront_indexes_to_ecommerce_tables.php |
- | - | ✅ |
2026_08_11_000001_fix_weight_volume_unit_comments_in_ecommerce_order_tables.php |
- | ecommerce_orders, ecommerce_order_options |
✅ |
2026_08_17_000001_add_soft_deletes_to_ecommerce_product_inquiries_table.php |
- | ecommerce_product_inquiries |
✅ |
2026_08_21_000001_add_unique_purchase_earn_lot_to_ecommerce_mileage_transactions_table.php |
- | - | ✅ |
2026_08_22_000001_add_content_thumbnail_url_to_ecommerce_products_table.php |
- | ecommerce_products |
✅ |
102개는 초기 스키마 한 벌이 아니라 누적된 변경 이력입니다. 새 컬럼을 추가할 때 초기
create_* 파일을 고치는 것이 아니라 새 add_*/change_* 파일을 더합니다 — 이미 설치된
사이트는 초기 마이그레이션을 다시 실행하지 않기 때문입니다.
같은 이유로 소스만 고쳐서는 기설치본이 낫지 않습니다. 컬럼 기본값·comment·데이터 형태를
바로잡는 변경은 마이그레이션과 함께 upgrades/ 의 업그레이드 스텝에 백필을 써야 이미 운영
중인 사이트에 반영됩니다.
작성 규칙 셋(코어 공통이지만 이 모듈에서 특히 자주 걸립니다):
- 모든 컬럼에 한국어
comment와down()구현 - FK 컬럼의
->comment()는->constrained()앞에 둡니다 (뒤에 두면 comment 가 컬럼이 아니라 FK 정의에 붙어 조용히 사라집니다) - 데이터를 순회하며 그 행을 갱신·삭제하는 백필은
chunkById()—chunk()계열은 OFFSET 기반이라 처리된 행이 필터에서 이탈한 만큼 커서가 밀려 미처리 행을 조용히 건너뜁니다
Enum
| Enum | backing | case 수 | case |
|---|---|---|---|
AdjustmentType |
string |
1 | cancel |
CancelOptionStatusEnum |
string |
2 | requested, completed |
CancelStatusEnum |
string |
2 | requested, completed |
CancelTypeEnum |
string |
2 | full, partial |
CashReceiptIdentifierType |
string |
3 | phone, card, business |
CashReceiptIssueStatus |
string |
3 | IN_PROGRESS, COMPLETED, FAILED |
CashReceiptTransactionType |
string |
2 | issue, cancel |
CashReceiptType |
string |
2 | income, expense |
ChargePolicyEnum |
string |
14 | free, fixed, conditional_free, range_amount, range_quantity, range_weight, range_volume, range_volume_weight, 외 6개 |
ClaimReasonFaultTypeEnum |
string |
3 | customer, seller, carrier |
ClaimReasonTypeEnum |
string |
1 | refund |
CouponDiscountType |
string |
2 | fixed, rate |
CouponIssueCondition |
string |
4 | manual, signup, first_purchase, birthday |
CouponIssueMethod |
string |
3 | direct, download, auto |
CouponIssueRecordStatus |
string |
4 | available, used, expired, cancelled |
CouponIssueStatus |
string |
2 | issuing, stopped |
CouponTargetScope |
string |
3 | all, products, categories |
CouponTargetType |
string |
3 | product_amount, order_amount, shipping_fee |
DeliveryMemoPresetEnum |
string |
4 | door, security, parcel_box, call |
DeviceTypeEnum |
string |
6 | pc, mobile, app_ios, app_android, admin, api |
MileageEarnTriggerEnum |
string |
2 | delivered, confirmed |
MileageTransactionTypeEnum |
string |
8 | purchase_earn, admin_earn, order_use, admin_deduct, expired, refund_restore, order_cancel_restore, earn_cancel |
OrderDateTypeEnum |
string |
5 | ordered_at, paid_at, confirmed_at, delivered_at, cancelled_at |
OrderOptionSourceTypeEnum |
string |
3 | order, exchange, split |
OrderStatusEnum |
string |
10 | pending_order, pending_payment, payment_complete, shipping_hold, preparing, shipping_ready, shipping, delivered, 외 2개 |
PaymentMethodEnum |
string |
8 | card, vbank, dbank, bank, phone, point, deposit, free |
PaymentStatusEnum |
string |
8 | ready, in_progress, waiting_deposit, paid, partial_cancelled, cancelled, failed, expired |
ProductDateType |
string |
2 | created_at, updated_at |
ProductDisplayStatus |
string |
2 | visible, hidden |
ProductImageCollection |
string |
3 | main, detail, additional |
ProductPriceType |
string |
3 | selling_price, supply_price, list_price |
ProductSalesStatus |
string |
4 | on_sale, suspended, sold_out, coming_soon |
ProductTaxStatus |
string |
2 | taxable, tax_free |
RefundMethodEnum |
string |
3 | pg, bank, points |
RefundOptionStatusEnum |
string |
6 | requested, approved, processing, on_hold, completed, rejected |
RefundPriorityEnum |
string |
2 | pg_first, points_first |
RefundStatusEnum |
string |
6 | requested, approved, processing, on_hold, completed, rejected |
ReviewStatus |
string |
2 | visible, hidden |
SearchPresetTargetScreen |
string |
3 | products, orders, customers |
SequenceAlgorithm |
string |
5 | hybrid, sequential, daily, timestamp, nanoid |
SequenceType |
string |
5 | product, order, shipping, cancel, refund |
ShippingApiAuthType |
string |
3 | none, bearer, custom_header |
ShippingApiHttpMethod |
string |
2 | GET, POST |
ShippingApiRequestField |
string |
5 | policy_id, country_code, items, group_total, total_quantity |
ShippingApiResponseType |
string |
2 | json, text |
ShippingCountryEnum |
string |
4 | KR, US, CN, JP |
ShippingFeeTaxPolicy |
string |
3 | proportional, taxable, follow_main_item |
ShippingStatusEnum |
string |
11 | pending, preparing, ready, shipped, in_transit, out_for_delivery, delivered, failed, 외 3개 |
TaxInvoiceStatusEnum |
string |
5 | pending, processing, issued, failed, cancelled |
Enum 49종이 이 도메인의 어휘 전체입니다. 상태·분류를 문자열 리터럴로 비교하는 코드가 있으면 그 자리는 Enum 으로 바꿔야 하는 신호입니다 — 화면 필터 옵션·검증 게이트·실제 기록 값 셋이 같은 Enum 에서 파생되지 않으면, 빠진 값으로 기록된 행이 어떤 필터로도 도달할 수 없게 됩니다.
먼저 읽어야 하는 것들:
| Enum | 왜 중요한가 |
|---|---|
OrderStatusEnum (10) |
주문 상태 전이의 SSoT. 어느 상태까지 취소를 허용할지는 설정(cancellable_statuses)이 이 케이스 이름으로 정합니다 |
PaymentStatusEnum (8) · PaymentMethodEnum (8) |
결제 상태와 코어 기본 결제수단. 플러그인이 추가하는 결제수단(kginicis_naverpay 등)은 여기에 없고 카탈로그 선언으로만 존재합니다 — 이 Enum 을 결제수단의 전체 목록으로 오해하지 않습니다 |
ChargePolicyEnum (14) |
배송비 산정 방식. 무료·정액·조건부무료·금액/수량/무게/부피 구간 등 국가별 요금 규칙이 전부 이 하나로 표현됩니다 |
MileageTransactionTypeEnum (8) |
원장 기록의 종류. 적립·사용·소멸·환불복원·취소복원이 모두 별개 케이스라 원장만 보고 잔액을 재구성할 수 있습니다 |
RefundMethodEnum (3) · RefundPriorityEnum (2) |
환불을 어디로 돌려줄지와 그 우선순위 |
SequenceType (5) · SequenceAlgorithm (5) |
채번 대상과 방식. 주문번호·상품코드 형식을 바꾸는 자리입니다 |
ShippingStatusEnum (11) · ShippingCountryEnum (4) |
배송 진행 상태와 기본 제공 국가 |
ShippingCountryEnum 이 4개뿐인 것은 기본 제공 목록이기 때문입니다. 취급 국가는 환경설정과
배송정책 국가별 설정이 정하므로, 나라를 늘리는 것은 이 Enum 을 고치는 일이 아닙니다.
Repository
| 클래스 | 종류 | 설명 |
|---|---|---|
BrandRepository |
구현 | 브랜드 Repository 구현체 |
BrandRepositoryInterface |
인터페이스 | 브랜드 Repository 인터페이스 |
CartRepository |
구현 | 장바구니 Repository 구현체 |
CartRepositoryInterface |
인터페이스 | 장바구니 Repository 인터페이스 |
CategoryImageRepository |
구현 | 카테고리 이미지 Repository 구현체 |
CategoryImageRepositoryInterface |
인터페이스 | 카테고리 이미지 Repository 인터페이스 |
CategoryRepository |
구현 | 카테고리 Repository 구현체 |
CategoryRepositoryInterface |
인터페이스 | 카테고리 Repository 인터페이스 |
ClaimReasonRepository |
구현 | 클레임 사유 Repository 구현체 |
ClaimReasonRepositoryInterface |
인터페이스 | 클레임 사유 Repository 인터페이스 |
CouponIssueRepository |
구현 | 쿠폰 발급 Repository 구현체 |
CouponIssueRepositoryInterface |
인터페이스 | 쿠폰 발급 Repository 인터페이스 |
CouponRepository |
구현 | 쿠폰 Repository 구현체 |
CouponRepositoryInterface |
인터페이스 | 쿠폰 Repository 인터페이스 |
EcommerceStatRepository |
구현 | 이커머스 일별 판매 집계 Repository |
EcommerceStatRepositoryInterface |
인터페이스 | 이커머스 일별 판매 집계 Repository 계약 |
EcommerceUserProfileRepository |
구현 | 이커머스 사용자 프로필 Repository 구현체 (A3) |
EcommerceUserProfileRepositoryInterface |
인터페이스 | 이커머스 사용자 프로필 Repository 인터페이스 (A3) |
ExtraFeeTemplateRepository |
구현 | 추가배송비 템플릿 Repository 구현체 |
ExtraFeeTemplateRepositoryInterface |
인터페이스 | 추가배송비 템플릿 Repository 인터페이스 |
MileageBalanceRepository |
구현 | 마일리지 잔액 캐시 Repository 구현체 (단방향 파생 — 원장/옵션 → 캐시) |
MileageBalanceRepositoryInterface |
인터페이스 | 마일리지 잔액 캐시 Repository 인터페이스 (파생 캐시) |
MileageTransactionRepository |
구현 | 마일리지 거래(원장) Repository 구현체 |
MileageTransactionRepositoryInterface |
인터페이스 | 마일리지 거래(원장) Repository 인터페이스 |
OrderCancelOptionRepository |
구현 | 주문 취소 옵션 리포지토리 구현체 |
OrderCancelOptionRepositoryInterface |
인터페이스 | 주문 취소 옵션 리포지토리 인터페이스 |
OrderCancelRepository |
구현 | 주문 취소 리포지토리 구현체 |
OrderCancelRepositoryInterface |
인터페이스 | 주문 취소 리포지토리 인터페이스 |
OrderCashReceiptRepository |
구현 | 주문 현금영수증 이력 Repository 구현체 |
OrderCashReceiptRepositoryInterface |
인터페이스 | 주문 현금영수증 이력 Repository 인터페이스 |
OrderOptionRepository |
구현 | 주문 옵션 리포지토리 |
OrderOptionRepositoryInterface |
인터페이스 | 주문 옵션 리포지토리 인터페이스 |
OrderPaymentRepository |
구현 | 주문 결제 Repository 구현체 |
OrderPaymentRepositoryInterface |
인터페이스 | 주문 결제 Repository 인터페이스 |
OrderRefundOptionRepository |
구현 | 주문 환불 옵션 리포지토리 구현체 |
OrderRefundOptionRepositoryInterface |
인터페이스 | 주문 환불 옵션 리포지토리 인터페이스 |
OrderRefundRepository |
구현 | 주문 환불 리포지토리 구현체 |
OrderRefundRepositoryInterface |
인터페이스 | 주문 환불 리포지토리 인터페이스 |
OrderRepository |
구현 | 주문 Repository 구현체 |
OrderRepositoryInterface |
인터페이스 | 주문 Repository 인터페이스 |
OrderShippingRepository |
구현 | 주문 배송 리포지토리 구현체 |
OrderShippingRepositoryInterface |
인터페이스 | 주문 배송 리포지토리 인터페이스 |
ProductAdditionalOptionValueRepository |
구현 | 상품 추가옵션 선택지 Repository 구현체 |
ProductAdditionalOptionValueRepositoryInterface |
인터페이스 | 상품 추가옵션 선택지 Repository 인터페이스 |
ProductCommonInfoRepository |
구현 | 공통정보 Repository 구현체 |
ProductCommonInfoRepositoryInterface |
인터페이스 | 공통정보 Repository 인터페이스 |
ProductImageRepository |
구현 | 상품 이미지 Repository 구현체 |
ProductImageRepositoryInterface |
인터페이스 | 상품 이미지 Repository 인터페이스 |
ProductInquiryRepository |
구현 | 상품 1:1 문의 Repository 구현체 |
ProductInquiryRepositoryInterface |
인터페이스 | 상품 1:1 문의 Repository 인터페이스 |
ProductLabelRepository |
구현 | 상품 라벨 Repository 구현체 |
ProductLabelRepositoryInterface |
인터페이스 | 상품 라벨 Repository 인터페이스 |
ProductNoticeTemplateRepository |
구현 | 상품정보제공고시 템플릿 Repository 구현체 |
ProductNoticeTemplateRepositoryInterface |
인터페이스 | 상품정보제공고시 템플릿 Repository 인터페이스 |
ProductOptionRepository |
구현 | 상품 옵션 Repository 구현체 |
ProductOptionRepositoryInterface |
인터페이스 | 상품 옵션 Repository 인터페이스 |
ProductRepository |
구현 | 상품 Repository 구현체 |
ProductRepositoryInterface |
인터페이스 | 상품 Repository 인터페이스 |
ProductReviewImageRepository |
구현 | 상품 리뷰 이미지 Repository 구현체 |
ProductReviewImageRepositoryInterface |
인터페이스 | 상품 리뷰 이미지 Repository 인터페이스 |
ProductReviewRepository |
구현 | 상품 리뷰 Repository 구현체 |
ProductReviewRepositoryInterface |
인터페이스 | 상품 리뷰 Repository 인터페이스 |
ProductWishlistRepository |
구현 | 상품 찜 Repository 구현체 |
ProductWishlistRepositoryInterface |
인터페이스 | 상품 찜 Repository 인터페이스 |
SearchPresetRepository |
구현 | 검색 프리셋 Repository 구현체 |
SearchPresetRepositoryInterface |
인터페이스 | 검색 프리셋 Repository 인터페이스 |
SequenceRepository |
구현 | 시퀀스 Repository 구현체 |
SequenceRepositoryInterface |
인터페이스 | 시퀀스 Repository 인터페이스 |
ShippingCarrierRepository |
구현 | 배송사 Repository 구현체 |
ShippingCarrierRepositoryInterface |
인터페이스 | 배송사 Repository 인터페이스 |
ShippingPolicyRepository |
구현 | 배송정책 Repository 구현체 |
ShippingPolicyRepositoryInterface |
인터페이스 | 배송정책 Repository 인터페이스 |
ShippingTypeRepository |
구현 | 배송유형 Repository 구현체 |
ShippingTypeRepositoryInterface |
인터페이스 | 배송유형 Repository 인터페이스 |
TempOrderRepository |
구현 | 임시 주문 Repository 구현체 |
TempOrderRepositoryInterface |
인터페이스 | 임시 주문 Repository 인터페이스 |
UserAddressRepository |
구현 | 사용자 배송지 Repository 구현체 |
UserAddressRepositoryInterface |
인터페이스 | 사용자 배송지 Repository 인터페이스 |
Repository 는 인터페이스와 구현이 1:1 로 짝을 이루며, 서비스는 인터페이스만 주입받습니다 (구체 클래스 타입힌트 금지). 바인딩은 모듈 서비스 프로바이더가 담당합니다.
이 모듈에서 Repository 를 손댈 때 특히 걸리는 것 셋:
- 목록 쿼리의 컬럼 프루닝 —
paginate()에 컬럼 목록을 주고, 목록이 실제로 그리는 것만 싣습니다. 상품 목록에 옵션 전체를 실으면 상품 100건 × 옵션 20건이 한 응답에 나갑니다. - 정렬 컬럼 화이트리스트 — 요청에서 온 정렬 컬럼을 그대로
orderBy에 넘기지 않습니다. 화면의 정렬 옵션 ⊆ FormRequest 게이트 ⊆ Repository 화이트리스트 순서로 포함 관계가 유지되어야 하며, 어긋나면 422 뒤에 직전 목록이 남아 정렬된 것처럼 보입니다. - 마일리지 두 Repository 의 역할 차이 —
MileageTransactionRepository는 원장이고MileageBalanceRepository는 파생 캐시입니다. 차감 가능 여부 판정은 반드시 원장FOR UPDATE로 하고, 캐시는 같은 트랜잭션 마지막에 재계산합니다. 캐시를 근거로 차감하면 동시 요청에서 잔액이 음수가 됩니다.
EcommerceStatRepository 만 성격이 다릅니다 — 대시보드용 일별 집계 테이블을 읽고 쓰며, 원본
주문에서 매번 집계하지 않기 위한 자리입니다. 집계를 채우는 것은 aggregate-stats 스케줄입니다.