SaaS 데이터베이스 아키텍처 설계하기

첫 주에 내린 잘못된 데이터베이스 결정은 수년 동안 당신을 괴롭힐 것입니다.

SaaS 창업자에게는 멀티테넌시(multi-tenancy), 결제, 성장을 모두 처리할 수 있는 스키마가 필요합니다. 설계를 잘못하면 6개월 안에 시스템 전체를 다시 작성해야 할 수도 있습니다.

프로덕션 환경에 바로 적용 가능한 스키마를 구축하는 방법은 다음과 같습니다.

1. 테넌트 전략 선택하기

고객 간의 데이터를 반드시 격리해야 합니다.

• Row-level (공유 DB): 복잡도가 낮습니다. 대부분의 스타트업에 가장 적합합니다. 모든 쿼리에 WHERE organization_id = ? 필터를 사용하세요. • Schema-level (별도 스키마): 복잡도가 중간 정도입니다. 규제 준수가 필요한 경우에 좋습니다. • Database-level (별도 DB): 복잡도가 높습니다. 엔터프라이즈 고객에게 가장 적합합니다.

신규 제품의 90%에는 row-level 멀티테넌시가 올바른 선택입니다.

2. 올바른 엔티티 계층 구조

사용자를 직접 결제 대상으로 삼지 마세요. 사용자는 들어오고 나가지만, 조직(Organization)은 유지됩니다.

계층 구조는 다음과 같아야 합니다: User ── MemberOf ── Organization ── Subscription ── Invoice

• Users: 이 테이블은 식별 용도로만 유지하세요. 공격을 방지하기 위해 UUID를 사용하세요. • Organizations: 이것이 테넌트의 경계입니다. 구독(subscription)은 항상 조직에 연결하세요. • Memberships: 사용자와 조직을 연결하기 위해 조인 테이블(join table)을 사용하세요. 역할(role)은 사용자 테이블이 아닌 여기에 저장하세요.

3. 결제 및 구독

is_active와 같은 단순한 불리언(boolean) 값을 절대 사용하지 마세요. 이는 데이터를 지저분하게 만듭니다.

구독에는 상태 머신(state machine)을 사용하세요. 일반적인 상태는 다음과 같습니다: • trialing • active • past_due • canceled • expired • incomplete

이를 통해 수동으로 데이터를 수정하지 않고도 결제 실패 및 유예 기간(grace period)을 처리할 수 있습니다.

4. 금액 및 인보이스(Invoicing)

재무적 오류를 방지하려면 다음의 엄격한 규칙을 따르세요:

• 금액을 위해 FLOATREAL을 절대 사용하지 마세요. 센트(cent) 단위로 저장하기 위해 정수(integer)를 사용하세요. 예를 들어, $29.99는 2999가 됩니다. • invoice_line_items 테이블을 사용하세요. 세무 보고 및 환불을 위해 이 테이블이 필요합니다. • 고객의 제품 사용량에 따라 요금을 부과하는 경우 usage_events 테이블을 사용하세요.

5. 성능 팁

• 외래 키(foreign keys)에 인덱스를 생성하세요. • 상태(status) 컬럼에 인덱스를 생성하세요. • 타임스탬프(timestamp) 컬럼에 인덱스를 생성하세요. • N+1 쿼리를 피하세요. JOIN을 사용하여 한 번의 요청으로 조직과 구독 데이터를 가져오세요.

좋은 스키마는 잘 작동할 때는 눈에 띄지 않지만, 실패할 때는 재앙이 됩니다.

조직을 위해 설계하세요. 상태 머신을 사용하세요. 금액은 정수로 저장하세요.

Source: https://dev.to/feidou/designing-saas-database-architecture-users-organizations-subscriptions-and-billing-df

Optional learning community: https://t.me/GyaanSetuAi