SaaS(Software as a Service)를 만들겠다는 클라이언트를 만날 때마다 가장 먼저 확인하는 것이 있습니다. "멀티테넌시를 고려하셨나요?" 멀티테넌시(Multi-tenancy)란 하나의 애플리케이션이 여러 조직(테넌트)에 서비스를 제공하되, 각 조직은 자신의 데이터만 볼 수 있는 구조를 말합니다.
Slack, Notion, Shopify 같은 서비스가 대표적인 멀티테넌트 애플리케이션입니다. SaaS를 구축한다면 반드시 이해해야 할 아키텍처입니다.
아파트와 단독주택의 비유
멀티테넌시를 가장 쉽게 이해하는 방법은 아파트와 단독주택의 비유입니다. 단독주택은 각 가정이 독립된 건물, 독립된 배관, 독립된 전기 시설을 갖습니다. 보안과 프라이버시는 완벽하지만 비용이 높습니다. 아파트는 건물 구조, 엘리베이터, 주차장을 공유하되, 각 세대는 잠금장치로 보호된 독립 공간을 갖습니다.
효율적이지만 설계가 중요합니다. 멀티테넌시는 아파트 모델입니다. 서버, 데이터베이스, 코드베이스라는 인프라를 공유하면서 각 테넌트의 데이터는 철저히 분리합니다. 인프라 비용을 절감하면서 수백, 수천 개의 조직에 서비스를 제공할 수 있는 것이 최대 장점입니다.
세 가지 구현 방식
멀티테넌시를 구현하는 방식은 크게 세 가지입니다. 각각의 장단점을 정확히 이해해야 프로젝트에 맞는 선택을 할 수 있습니다.
첫 번째, 공유 데이터베이스에 tenant_id 컬럼을 추가하는 방식입니다. 모든 테넌트의 데이터가 같은 테이블에 저장되고 tenant_id로 구분합니다. 가장 단순하고 비용이 적게 듭니다. 새 테넌트 추가도 레코드 하나만 생성하면 됩니다. 단점은 데이터 격리 수준이 상대적으로 낮다는 것입니다. 쿼리에서 tenant_id 필터를 빠뜨리면 다른 테넌트의 데이터가 노출될 위험이 있습니다. 스타트업이나 초기 SaaS에 적합합니다.
두 번째, 테넌트별 별도 스키마(Schema)를 사용하는 방식입니다. PostgreSQL에서는 하나의 데이터베이스 안에 여러 스키마를 생성할 수 있습니다. 테넌트 A는 tenant_a 스키마, 테넌트 B는 tenant_b 스키마를 사용합니다. 데이터 격리가 더 강하면서도 인프라 비용은 하나의 DB만 운영하면 됩니다. 중간 단계의 SaaS에 적합하지만, 테넌트가 수천 개로 늘어나면 스키마 마이그레이션이 복잡해지는 단점이 있습니다.
두 번째, 테넌트별 별도 데이터베이스를 운영하는 방식입니다. 가장 강력한 데이터 격리를 제공하며, 특정 테넌트의 데이터를 독립적으로 백업하거나 이관하기 쉽습니다. 하지만 데이터베이스 인스턴스마다 비용이 발생하고 운영 복잡도가 크게 증가합니다. 금융, 의료, 정부 관련 서비스처럼 강력한 컴플라이언스가 요구되는 엔터프라이즈 환경에 적합합니다.
보안은 타협 불가
멀티테넌시에서 보안은 절대 타협할 수 없는 영역입니다. 하나의 테넌트가 다른 테넌트의 데이터를 보는 사고가 단 한 번이라도 발생하면, 서비스의 신뢰는 회복 불가능하게 무너집니다. Django로 구현할 때는 커스텀 미들웨어에서 테넌트 컨텍스트를 자동으로 설정하고, 모든 QuerySet에 테넌트 필터가 자동 적용되도록 설계해야 합니다.
Manager 클래스를 오버라이드하여 기본 QuerySet에 tenant 필터를 포함시키는 것이 가장 안전한 방법입니다. 새로운 API 엔드포인트를 추가할 때 개발자가 tenant 필터를 깜빡 잊는 것이 가장 흔한 사고 원인이므로, 시스템 레벨에서 강제하는 것이 핵심입니다.
실무에서 놓치기 쉬운 고려사항
멀티테넌시를 구현할 때 데이터 분리 외에도 고려할 사항이 많습니다. 테넌트 인식 캐싱(Tenant-aware Caching)이 대표적입니다. Redis 캐시 키에 tenant_id를 포함시키지 않으면 테넌트 A의 캐시된 데이터가 테넌트 B에게 노출됩니다. 테넌트별 커스터마이징도 중요합니다. 로고, 브랜드 색상, 커스텀 도메인 등 테넌트가 자신의 브랜드로 서비스를 사용할 수 있어야 합니다. 과금과 사용량 추적도 테넌트 단위로 이루어져야 합니다.
프로덕트 메이커의 권장 전략
프로덕트 메이커는 SaaS 프로젝트에서 공유 DB와 tenant_id 방식으로 시작할 것을 권장합니다. 초기에는 테넌트 수가 적고 빠른 개발이 중요하기 때문입니다. 이후 엔터프라이즈 고객이 보안 인증이나 데이터 격리를 요구할 때 스키마 분리로 마이그레이션하는 단계적 접근이 가장 현실적입니다.
처음부터 완벽한 격리를 추구하면 개발 기간과 비용이 2~3배로 늘어나는데, 초기 SaaS에서 이 비용을 감당하기는 어렵습니다. 중요한 것은 어떤 방식을 선택하든 향후 마이그레이션이 가능하도록 테넌트 관련 로직을 추상화 계층으로 분리해두는 것입니다.