User 중심
role, plan, setting이 user에 붙어 있어 개인 제품에는 단순하다.
문제: 한 사용자가 여러 팀에 속하면 권한과 결제가 꼬인다.분류: Layer 13 - Product Engineering & Growth Systems
Product Engineer는 화면을 만드는 동시에 그 화면 뒤의 제품 상태를 모델링한다. workspace, member, role, invite, subscription, entitlement, project 같은 객체가 흐릿하면 UX Flow, feature flag, analytics, billing, support tooling이 모두 흔들린다.
Product Domain Modeling은 사용자 경험 뒤에 있는 제품 객체, 관계, 상태 전이, 불변식을 정의하고 이를 API·DB·권한·analytics 계약으로 연결하는 역량이다.
Product Engineer가 자주 만나는 기능은 단순 CRUD처럼 보인다.
하지만 실제로는 권한, 결제, lifecycle, audit log, analytics가 붙어 있다. 예를 들어 멤버 초대는 Invite 하나를 만들고 끝나는 기능이 아니다. 초대 가능한 role, seat limit, email delivery, expired token, accepted membership, audit log, activation event가 모두 연결된다.
제품 도메인 모델이 약하면 화면마다 다른 상태 해석이 생긴다. 한 화면은 user.role을 보고, 다른 API는 membership.role을 보고, billing은 seat count를 따로 계산한다. 이런 시스템은 실험과 출시가 아니라 예외 처리의 늪이 된다.
일반 DB 모델링은 테이블과 관계를 잘 잡는 데 초점이 있다. DDD는 도메인 언어와 aggregate, invariant를 강조한다. 하지만 Product Engineer에게는 여기에 제품 성장과 운영의 관점이 더 붙는다. 같은 User라도 개인 계정인지, workspace member인지, billing customer인지, experiment subject인지에 따라 의미가 달라진다.
CRUD 중심 모델링은 “저장할 수 있는가”에는 답하지만 “이 상태에서 어떤 사용자가 어떤 기능을 볼 수 있는가”, “이 상태 전이가 제품 지표에 어떤 이벤트로 남는가”, “결제 실패 후 entitlement를 언제 회수할 것인가”에는 약하다.
Product Domain Modeling은 이 한계를 메운다. DB 테이블은 결과물이고, 먼저 정의해야 하는 것은 제품 객체의 언어, 상태 전이, 불변식, 권한 경계, 분석 이벤트다.
많은 B2B/SaaS 제품은 다음 객체를 중심으로 돌아간다.
| 객체 | 의미 | 흔한 관계 |
|---|---|---|
| User | 로그인 가능한 개인 | 여러 workspace의 member가 될 수 있음 |
| Account/Workspace | 협업과 결제의 기본 단위 | member, project, subscription을 가짐 |
| Membership | user와 workspace의 관계 | role, status, joined_at을 가짐 |
| Role/Permission | 행동 가능 범위 | owner/admin/member/viewer |
| Invite | 아직 수락되지 않은 초대 | token, role, expiry, inviter |
| Project/Resource | 제품의 핵심 작업 단위 | owner workspace, visibility, lifecycle |
| Plan/Subscription | 결제 상태 | trialing, active, past_due, canceled |
| Entitlement | 기능 접근 권한 | feature key, limit, enabled state |
Product Engineer는 이 객체를 UI 상태로 흩뿌리지 않고 서버 도메인 모델로 둔다. 그래야 feature flag, analytics, billing, support console이 같은 언어를 쓴다.
가장 흔한 실수는 user 하나에 모든 상태를 붙이는 것이다.
role, plan, setting이 user에 붙어 있어 개인 제품에는 단순하다.
문제: 한 사용자가 여러 팀에 속하면 권한과 결제가 꼬인다.협업, 결제, 권한의 기본 단위를 workspace로 둔다.
장점: B2B SaaS, 팀 초대, seat billing, audit log에 적합하다.user와 workspace 사이의 관계 객체가 role과 상태를 가진다.
장점: 같은 user가 workspace마다 다른 role을 가질 수 있다.plan 이름이 아니라 기능 접근 권한을 별도 객체로 둔다.
장점: billing 변경과 feature exposure를 느슨하게 연결한다.협업 제품에서는 user.role = admin보다 membership.role = admin이 안전하다. 사용자는 여러 workspace에 속할 수 있고, 권한은 관계마다 달라진다.
제품 객체에는 lifecycle이 있다.
Invite: pending -> accepted pending -> expired pending -> revoked
Workspace: active -> suspended active -> deleted_pending deleted_pending -> deleted
Subscription: trialing -> active active -> past_due past_due -> canceled상태 전이는 API endpoint보다 먼저 정의해야 한다. 그리고 각 전이에 불변식을 붙인다.
퀴즈
힌트: 권한은 사용자 자체가 아니라 사용자와 workspace의 관계일 수 있다.
한 사용자가 여러 workspace에서 서로 다른 role을 가져야 할 때 표현할 수 없다. 권한 변경, 초대, audit log, billing seat 계산도 관계 단위로 다뤄야 하므로 Membership 같은 관계 객체가 필요하다.
제품 도메인 모델은 DB에만 머물지 않는다.
| 영역 | 도메인 모델이 주는 효과 |
|---|---|
| API | workspace_id, membership_id, entitlement_key가 명확해진다 |
| UI | empty/error/success 상태가 도메인 상태와 맞아진다 |
| Analytics | event property가 같은 집계 단위를 쓴다 |
| Feature flag | targeting rule이 role, plan, workspace 상태를 참조한다 |
| Billing | subscription과 entitlement 변경이 기능 접근으로 이어진다 |
| Support | 고객 문의를 같은 객체 언어로 추적한다 |
이 언어가 흔들리면 분석 이벤트도 흔들린다. 예를 들어 account_id, workspace_id, team_id가 같은 뜻인지 다른 뜻인지 불명확하면 cohort 분석도 신뢰하기 어렵다.
Product Engineer가 만든 제품 상태는 사용자와 support team이 나중에 설명할 수 있어야 한다.
초대 기능이라면 audit log에는 다음 정보가 필요할 수 있다.
Audit log는 보안 기능이기도 하지만 제품 운영 기능이기도 하다. 상태 전이를 설명할 수 없는 제품은 고객 지원과 incident 대응이 어렵다.
시나리오
무료 plan은 member 3명까지 가능하고, 유료 plan은 seat 수만큼 초대할 수 있다. 초대받은 사용자는 링크로 가입하거나 기존 계정으로 수락할 수 있다.
User, Workspace, Membership, Invite, Subscription, Entitlement 중 어떤 객체와 상태 전이를 먼저 정의해야 하는가?권장 루틴은 다음과 같다.
Product Domain Modeling은 이어지는 billing/entitlement 문서의 기반이다. subscription 상태와 entitlement 변경은 제품 객체와 상태 전이 없이는 안전하게 구현하기 어렵다.
Billing, Subscription & Entitlement: 결제 lifecycle과 기능 접근 권한을 모델링한다.Privacy, Consent & Product Data Governance: 도메인 객체에 붙은 개인정보와 보존 정책을 다룬다.Experimentation & Feature Flags: role, plan, workspace 상태를 flag targeting에 활용한다.