+ 모호성을 폭넓게 짚고 이력·스냅샷까지 구체화했다.
- 중복 이력 모델과 회차·주문의 FK 방향이 일관되지 않다.
기능 설명을 받아 엔티티와 관계를 세웁니다. 애매한 부분을 묻고 넘어가지 않습니다.
| 분류 | 개발 › 데이터·DB |
|---|---|
| 태그 | 초안작성분석개발자 |
Derive a data model from these requirements. Step 1 — **Ambiguities first. Do not model yet.** List every place the requirements do not settle a cardinality, an optionality, or a lifetime. Phrase each as a question with a recommended default. Typical ones: can this have more than one, can it be empty, what happens when the parent is deleted, is this value historical or current, can it change after creation. Step 2 — Entities. One line each on what a row represents. *If you cannot say what one row is, it is not an entity yet.* Step 3 — Relationships with cardinality, and which side holds the key. Step 4 — Attributes, with the ones that are derived rather than stored marked as such. Step 5 — What the model makes hard. Every model makes some question expensive; name the queries that will be awkward here. Step 6 — Two or three decisions you made that a reasonable person would make differently, and what the alternative costs. Rules: - *Do not invent requirements to resolve an ambiguity.* Put it in step 1. - Model what the requirements say, not what similar products usually do. - No DDL yet. Structure first; syntax is a separate step.
요구사항에는 항상 "한 명이 여러 개를 가질 수 있나"가 안 적혀 있다. 이 프롬프트는 그 모호함을 먼저 목록으로 뽑아 묻고, 그다음에 구조를 세운다.
ChatGPT가 모호성 식별과 구체성에서 가장 우수하지만 다소 과도하고 일부 관계가 모순된다. Gemini는 더 응집력 있으나 미확정 사항을 단정했고, [C]는 답이 제시되지 않았다.
+ 모호성을 폭넓게 짚고 이력·스냅샷까지 구체화했다.
- 중복 이력 모델과 회차·주문의 FK 방향이 일관되지 않다.
+ 주문·결제와 실제 출고를 명확히 분리했다.
- 매출 기준을 paid_at으로 정하고 번들 구조도 단정했다.
| 기준 | ChatGPT | Gemini | 앞선 모델 |
|---|---|---|---|
| 지시 준수 | 9 | 7 | ChatGPT +29% |
| 정확성 | 7 | 6 | ChatGPT +17% |
| 구체성 | 9 | 8 | ChatGPT +13% |
| 구성·가독성 | 8 | 9 | Gemini +13% |
| 분량 적정성 | 6 | 7 | Gemini +17% |
gpt-5.6-sol가 모델 이름을 가린 채 1~10점으로 채점했습니다 (2026-09-25). 측정값이 아니라 AI 심사 결과입니다.
같은 입력을 세 모델에 넣어 받은 답을 그대로 옮겼습니다. 각 CLI(에이전트 하네스)에서 실행했습니다. ChatGPT·Claude 앱이나 웹에서는 답이 다를 수 있습니다.
요구사항: - 고객은 여러 개의 정기구독을 가질 수 있다 (예: 스킨케어 3종 세트, 클렌징 세트). - 각 구독은 배송 주기(2주/4주)를 가지며, 고객이 언제든 일시정지·해지할 수 있다. - 구독 1건당 매 배송 회차마다 실제 발송된 상품 목록과 운송장 번호가 남아야 한다. - 고객은 구독과 별도로 단건 주문도 할 수 있다. - 프로모션 쿠폰은 특정 구독 상품에만 적용되는 경우와 전체 주문에 적용되는 경우가 있다. - 관리자는 회차별로 발송 상품 구성을 바꿀 수 있어야 한다 (예: 이번 달은 A상품 대신 B상품 발송). 제약 조건: PostgreSQL 사용. 기존 users, products 테이블 구조는 그대로 유지. 정산팀이 구독 매출을 월별로 집계하는 리포트를 쓰고 있어 매출 인식 시점은 바꿀 수 없음.
추천 기본값은 이후 모델에서 사용할 가정이다.
한 고객은 구독을 최대 몇 건까지 가질 수 있는가?
→ 여러 건 허용. 같은 상품을 포함한 구독도 허용할지 별도 결정.
하나의 구독에는 상품이 몇 개까지 포함될 수 있는가?
→ 1개 이상 여러 개 허용.
구독 생성 시 상품 구성은 반드시 있어야 하는가?
→ 최소 1개 필요.
구독 상품의 수량은 상품별로 가질 수 있는가?
→ 상품별 수량을 허용.
구독 주기는 생성 후 변경할 수 있는가?
→ 변경 가능하되 변경 이력을 보존할지 결정 필요. 추천: 변경 이력 보존.
일시정지 기간은 정해져 있는가, 무기한인가?
→ 무기한 일시정지 허용. 재개 시점은 별도 기록.
일시정지·해지는 즉시 적용되는가, 다음 배송 회차부터 적용되는가?
→ 다음 미발송 회차부터 적용.
해지한 구독을 다시 재개할 수 있는가?
→ 재개 불가, 새 구독을 생성. 재개 허용이 필요하면 상태 이력이 필요하다.
구독 해지 후 기존 배송 회차와 매출 기록은 유지되는가?
→ 유지.
구독의 한 배송 회차는 실제로 반드시 발송되는가?
→ 취소·스킵·실패 상태도 허용하고, 발송된 회차만 실제 상품 목록을 필수로 둔다.
하나의 배송 회차가 여러 택배로 나뉠 수 있는가?
→ 추천: 회차당 운송장 1개. 여러 운송장이 필요하면 별도 배송 패키지 엔티티가 필요하다.
배송 회차의 상품 구성은 발송 전 언제까지 변경할 수 있는가?
→ 발송 확정 전까지 변경 가능, 발송 확정 후 불변.
관리자가 상품 구성을 변경하면 원래 예정된 구성도 보존해야 하는가?
→ 예정 구성과 실제 발송 구성을 모두 보존. 추천: 변경 이력도 보존.
상품명·가격이 변경되거나 상품이 삭제되어도 과거 회차의 정보는 그대로 보여야 하는가?
→ 그렇다. 과거 발송 상품에는 상품 참조와 함께 당시 이름·가격을 저장.
상품 가격은 구독 생성 시 고정되는가, 발송 회차 당시 가격을 사용하는가?
→ 요구사항만으로 결정할 수 없다. 추천: 회차 확정 시 가격을 고정.
단건 주문도 배송 이력과 운송장 번호를 가져야 하는가?
→ 요구사항에는 구독 배송만 명시되어 있다. 추천: 단건 주문도 같은 배송 구조를 재사용하되, 필수 여부는 별도 결정.
쿠폰은 한 주문에 여러 개 적용할 수 있는가?
→ 추천: 한 주문당 최대 1개.
특정 구독 상품용 쿠폰은 구독 전체 기간 동안 재사용 가능한가, 한 회차만 가능한가?
→ 추천: 쿠폰 정책으로 명시하고, 적용된 각 회차에 적용 이력을 남긴다.
쿠폰이 적용되는 대상은 구독의 예정 상품인가, 실제 발송 상품인가?
→ 추천: 실제 발송·청구된 상품 기준.
쿠폰 할인 금액이나 적용 규칙이 나중에 변경되면 과거 주문에도 영향을 주는가?
→ 영향을 주지 않음. 적용 당시 할인 규칙과 금액을 주문에 복사.
쿠폰이 전체 주문에 적용될 때 배송비·세금도 할인 대상인가?
→ 요구사항에 없다. 상품 금액에만 적용하는 것을 기본값으로 제안.
쿠폰은 만료·사용 횟수·고객별 사용 제한을 갖는가?
→ 미정. 필요한 경우 쿠폰 정책 속성으로 추가.
매출 인식 시점은 정확히 어떤 이벤트인가?
→ 기존 정산 시스템의 현재 기준을 확인해야 한다. 추천: 회차별 매출 인식 이벤트와 인식 시각을 별도 불변 기록.
결제 실패·환불·부분 환불이 발생할 수 있는가?
→ 요구사항에 없다. 정산 리포트가 이를 다루면 주문·매출 조정 모델을 추가해야 한다.
Subscription: 고객과 구독 계약 한 건을 나타낸다.SubscriptionItem: 구독에 포함된 상품과 수량 한 건을 나타낸다.SubscriptionCycle: 구독의 특정 배송 회차 한 건을 나타낸다.SubscriptionCycleItem: 특정 회차에 실제로 발송된 상품과 수량 한 건을 나타낸다.Order: 단건 주문 또는 구독 회차에 대응하는 금전 거래 한 건을 나타낸다.OrderItem: 주문에서 청구된 상품과 수량 한 건을 나타낸다.Coupon: 프로모션 쿠폰 정의 한 건을 나타낸다.CouponApplication: 특정 주문에 쿠폰이 적용된 사실 한 건을 나타낸다.CouponApplicationItem: 쿠폰이 특정 상품에 적용된 경우의 대상 상품 한 건을 나타낸다.SubscriptionStatusHistory: 구독의 상태 변경 한 건을 나타낸다.SubscriptionItemHistory: 구독 상품 구성 변경 한 건을 나타낸다.RevenueRecognition: 기존 정산 기준에 따라 매출이 인식된 사실 한 건을 나타낸다.기존 users, products 테이블은 그대로 참조한다.
users 1 : N Subscription
외래 키는 Subscription이 가진다.
Subscription 1 : N SubscriptionItem
외래 키는 SubscriptionItem이 가진다.
products 1 : N SubscriptionItem
외래 키는 SubscriptionItem이 가진다.
Subscription 1 : N SubscriptionCycle
외래 키는 SubscriptionCycle이 가진다.
SubscriptionCycle 1 : N SubscriptionCycleItem
외래 키는 SubscriptionCycleItem이 가진다.
products 1 : N SubscriptionCycleItem
외래 키는 SubscriptionCycleItem이 가진다.
SubscriptionCycle 1 : 1 Order
구독 회차 주문이 존재한다면 Order가 회차를 참조한다. 추천 구조는 구독 회차마다 주문을 하나 만든다.
단건 주문은 Order만 가지며 SubscriptionCycle은 없다.
따라서 Order의 주문 유형으로 단건 주문과 구독 회차 주문을 구분한다.
Order 1 : N OrderItem
외래 키는 OrderItem이 가진다.
products 1 : N OrderItem
외래 키는 OrderItem이 가진다.
Coupon 1 : N CouponApplication
외래 키는 CouponApplication이 가진다.
Order 1 : 0..1 CouponApplication
추천 기본값은 주문당 쿠폰 하나다.
CouponApplication 1 : 0..N CouponApplicationItem
전체 주문 쿠폰이면 대상 상품이 없고, 특정 상품 쿠폰이면 대상 상품 목록이 존재한다.
OrderItem 1 : 0..N CouponApplicationItem
특정 주문 상품에 대한 쿠폰 적용 대상을 나타낸다.
Subscription 1 : N SubscriptionStatusHistory
외래 키는 이력 테이블이 가진다.
Subscription 1 : N SubscriptionItemHistory
외래 키는 이력 테이블이 가진다.
Order 또는 SubscriptionCycle 1 : N RevenueRecognition
실제 정산 기준이 주문 단위인지 회차 단위인지 확인한 뒤 하나를 기준으로 고정한다.
Subscription현재 상태는 이력에서 계산할 수도 있지만, 조회 성능을 위해 저장할 수 있다.
SubscriptionItemSubscriptionCycle운송장 번호는 발송 전에는 비어 있을 수 있다.
SubscriptionCycleItem이 테이블이 관리자 변경 후의 실제 발송 구성을 보존한다.
OrderOrderItemCouponCouponApplicationCouponApplicationItemSubscriptionStatusHistorySubscriptionItemHistoryRevenueRecognition매출 인식 시각은 기존 정산팀의 기준을 그대로 사용하며, 새 모델이 그 시점을 변경하지 않도록 한다.
특정 시점의 모든 구독 상품 구성을 재현하는 질문
→ 현재 구성과 변경 이력을 함께 조회해야 한다.
“관리자가 왜 이 회차의 상품을 바꿨는가?”를 정확히 추적하는 질문
→ 변경 이력과 회차 스냅샷을 함께 봐야 한다.
구독 예정 구성과 실제 발송 구성이 다른 회차만 찾는 질문
→ SubscriptionItem과 SubscriptionCycleItem을 시점별로 비교해야 한다.
쿠폰 하나가 구독 전체 기간에 걸쳐 얼마를 할인했는지 계산하는 질문
→ 각 회차 주문의 쿠폰 적용 이력을 합산해야 한다.
상품의 현재 가격과 과거 청구 가격을 비교하는 질문
→ 상품 테이블과 여러 스냅샷 컬럼을 조합해야 한다.
하나의 구독에서 발생한 매출과 단건 주문 매출을 같은 기준으로 비교하는 질문
→ 주문 유형과 회차, 매출 인식 기록을 조인해야 한다.
구독 회차마다 Order를 만들지 여부
SubscriptionCycle 자체를 금전 거래로 취급한다.배송 회차의 상품 목록을 주문 항목과 별도로 저장할지 여부
OrderItem과 SubscriptionCycleItem을 분리한다.구독 상품 변경 이력을 별도 테이블로 저장할지 여부
SubscriptionItem만 수정한다.| 대용량 텍스트 변환기 프롬프트 | |
| AI 데이터 추출 도구 기획 프롬프트 | |
| AI2sql 자연어 SQL 생성 프롬프트 | |
| 백엔드 아키텍트 역할을 맡기는 프롬프트 | |
| Base R 프로그래밍 프롬프트 |