멀티테넌트 클라우드 호스팅은 하나의 서버군과 소프트웨어로 여러 고객에게 서비스를 제공하면서 테넌트 사이를 논리적으로 격리하는 모델입니다. 아파트 건물을 떠올리면 됩니다. 입주자들은 건물 구조, 배관, 전기를 공유하지만 모든 현관문은 잠깁니다. 대안인 싱글테넌트 호스팅은 단독 주택입니다. 통제력은 완전하고 임대료는 더 높으며, 유지 보수도 더 많이 직접 맡아야 합니다.
핵심 요약
| 질문 | 답변 |
|---|---|
| 정의 | 공유 서버와 소프트웨어, 여러 고객, 논리적으로 분리된 데이터 |
| 존재 이유 | 인프라 공유가 클라우드 요금을 가능하게 함 |
| 어려운 부분 | 격리. 테넌트는 서로의 데이터를 보거나 서로의 부하를 느껴서는 안 됨 |
| vs. 싱글테넌트 | 더 저렴하고 온보딩이 빠르며 업데이트 주기가 하나. 대가는 물리적 분리의 포기 |
| 격리가 있어야 할 곳 | 데이터 계층. 모든 쿼리의 WHERE 절이 아님 |
테넌트 데이터가 분리되는 방식
모든 멀티테넌트 시스템은 먼저 한 가지 질문에 답합니다. 격리는 어디에 있는가? 데이터베이스 계층에는 세 가지 정석 패턴이 있습니다. 공유 스키마, 테넌트별 스키마, 테넌트별 데이터베이스입니다. 공유 스키마가 주력이며, 데이터베이스 자체가 경계를 강제할 때 가장 안전합니다:
-- 패턴 1: 공유 스키마 — 모든 행이 자신의 테넌트를 지님
CREATE TABLE invoices (
id bigserial PRIMARY KEY,
tenant_id uuid NOT NULL,
amount numeric(10,2) NOT NULL
);
-- 격리는 모든 쿼리가 아니라 데이터베이스에서 강제
ALTER TABLE invoices ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON invoices
USING (tenant_id = current_setting('app.tenant_id')::uuid);
행 수준 정책이 있으면 테넌트 필터를 잊은 쿼리는 전부가 아니라 아무것도 반환하지 않습니다. 실패 모드가 데이터 침해에서 빈 페이지로 뒤집힙니다.
Backend as a Service에서는 같은 원칙이 SQL 정책 대신 객체별 접근 제어로 표현됩니다. 각 레코드는 자신을 볼 수 있는 테넌트 역할을 지정한 ACL을 지니고, 플랫폼이 모든 요청에서 이를 강제합니다:
// JavaScript / Node.js — Back4app JS SDK
const doc = new Parse.Object('Invoice');
doc.set('amount', 480);
const acl = new Parse.ACL();
acl.setPublicReadAccess(false); // invisible to every other tenant
acl.setRoleReadAccess('tenant-acme', true);
acl.setRoleWriteAccess('tenant-acme', true);
doc.setACL(acl);
await doc.save(); // Flutter / Dart — Back4app Flutter SDK
final doc = ParseObject('Invoice')..set('amount', 480);
final acl = ParseACL();
acl.setPublicReadAccess(allowed: false);
acl.setRoleReadAccess('tenant-acme', true);
acl.setRoleWriteAccess('tenant-acme', true);
doc.setACL(acl);
await doc.save(); // iOS / Swift — Back4app Swift SDK
var doc = Invoice()
doc.amount = 480
var acl = ParseACL()
acl.publicRead = false
acl.setReadAccess(roleName: "tenant-acme", value: true)
acl.setWriteAccess(roleName: "tenant-acme", value: true)
doc.ACL = acl
doc.save { _ in } // Android / Kotlin — Back4app Android SDK
val doc = ParseObject("Invoice").apply { put("amount", 480) }
val acl = ParseACL().apply {
publicReadAccess = false
setRoleReadAccess("tenant-acme", true)
setRoleWriteAccess("tenant-acme", true)
}
doc.acl = acl
doc.saveInBackground() 격리는 스위치가 아니라 스펙트럼
“모두 공유”와 “모두 전용” 사이에는 실제 시스템 대부분이 고르는 세 가지 배포 형태가 있습니다:
성숙한 플랫폼은 이들을 섞어 씁니다. 다수의 소규모 테넌트는 pool로, 중간 규모는 bridge로, 규제 대상이거나 거대하거나 시끄러운 소수는 silo로 둡니다. 흔한 실수는 이 선택을 전역적인 것으로 다루는 것입니다. 선택은 요금제 단위로, 심지어 구성 요소 단위로도 내릴 수 있습니다.
멀티테넌트 vs. 싱글테넌트 호스팅
| 기준 | 멀티테넌트 | 싱글테넌트 |
|---|---|---|
| 테넌트당 비용 | 낮음. 인프라 비용이 분산됨 | 높음. 고객마다 전용 스택 |
| 데이터 격리 | 논리적(정책, ACL, 스키마) | 물리적(별도 인스턴스와 데이터베이스) |
| 영향 범위 | 장애 한 번이 여러 테넌트에 닿을 수 있음 | 고객 한 곳에 국한 |
| 노이지 네이버 | 발생 가능. 할당량과 스로틀링 필요 | 없음. 리소스가 전용 |
| 업그레이드 | 한 번의 롤아웃으로 모두 업데이트 | 인스턴스마다 따로 패치 적용 |
| 온보딩 | 설정 변경, 몇 분 | 프로비저닝, 몇 시간에서 몇 주 |
| 커스터마이징 | 설정과 피처 플래그 | 인스턴스 단위의 깊은 변경 가능 |
| 컴플라이언스 적합성 | 대부분 충분. 엄격한 체계에서는 마찰 | 엄격한 격리 의무에 선호됨 |
| 대표적 용도 | SaaS, BaaS, 공유 클라우드 플랫폼 | 규제 산업, 프리미엄 엔터프라이즈 요금제 |
구분해야 할 두 가지 의미
“멀티테넌트 클라우드 호스팅”은 서로 다른 두 층위에서 쓰이며, 대부분의 설명은 이를 뭉뚱그립니다:
- 호스팅 계층으로서: 공유 호스팅입니다. 사용자의 워크로드가 다른 고객의 워크로드와 같은 물리 머신에서 실행됩니다. 모든 퍼블릭 클라우드의 기본 방식이며, NIST 정의는 테넌트 간 리소스 풀링을 클라우드 컴퓨팅 자체의 필수 특성으로 꼽습니다.
- 애플리케이션 아키텍처로서: 사용자 자신의 제품이 하나의 공유 백엔드로 고객들을 서비스합니다. 구독형 소프트웨어가 만들어지는 방식입니다. 여기서는 사용자가 건물주이고 테넌트 격리는 사용자의 책임이 되며, 앞서 본 패턴들이 바로 여기에 쓰입니다.
둘은 겹쳐 쌓입니다. SaaS 제품(애플리케이션 수준 멀티테넌시)은 보통 pool 방식의 클라우드 인프라(호스팅 수준 멀티테넌시) 위에서 실행되며, 각 계층이 자신의 테넌트를 격리합니다.
노이지 네이버 문제
공유는 경합을 뜻합니다. 한 테넌트의 대량 가져오기가 다른 테넌트의 결제를 느리게 만들 수 있습니다. 표준 완화책을 강도 순으로 정리하면 다음과 같습니다:
- 테넌트별 할당량과 속도 제한 – 어떤 테넌트든 시간 구간당 소비할 수 있는 양에 상한을 둡니다.
- 리소스 스케줄링과 오토스케일링 – 급증이 다른 누군가의 지연 시간이 되기 전에 흡수합니다.
- 워크로드 분리 – 무거운 작업(내보내기, 분석)을 요청 경로 밖의 백그라운드 큐로 옮깁니다.
- 부분 silo화 – 한 테넌트가 지속적으로 과부하를 일으키면 경합이 일어나는 구성 요소(보통 데이터베이스)에 전용 파티션을 주고 나머지는 pool로 둡니다.
일반적인 사용 사례
- SaaS 제품. 하나의 코드베이스로 모든 고객을 서비스하는 모든 구독형 앱입니다. 정석적인 사례이자 이 패턴이 존재하는 이유입니다.
- BaaS와 플랫폼 호스팅. 플랫폼은 공유되면서도 격리된 인프라에서 수천 개의 앱을 실행하므로, 앱 하나를 프로비저닝하는 비용이 거의 0입니다. 무료 요금제를 떠받치는 모델입니다.
- 테넌트 워크스페이스를 둔 B2B 애플리케이션. 하나의 배포에 여러 고객 조직이 있고, 각 조직은 자신의 사용자, 역할, 데이터 경계를 가집니다.
- 내부 플랫폼. 분석이나 도구 배포 하나를 여러 부서가 공유하고 팀 단위로 격리합니다.
- 여러 클라이언트 앱을 운영하는 에이전시. 아래에는 공유 플랫폼을 두고, 그 위에 클라이언트마다 격리된 백엔드를 하나씩 둡니다.
멀티테넌트, 싱글테넌트, 혼합 중 무엇을 선택해야 할까? 결정 매트릭스
| 멀티테넌트를 선택해야 할 때 | 싱글테넌트를 선택해야 할 때 | 혼합을 선택해야 할 때 |
|---|---|---|
| 하나의 제품으로 여러 고객을 서비스함 | 규제나 계약이 물리적 격리를 요구함 | 대부분의 테넌트는 표준적이고 소수만 규제 대상임 |
| 고객당 비용이 0에 가까워야 함 | 한 고객의 SLA가 전용 용량을 정당화함 | 한 테넌트가 중앙값보다 100× 큼 |
| 모두를 위한 업데이트 주기를 하나로 유지하고 싶음 | 고객별 깊은 커스터마이징 자체가 제품임 | 프리미엄 “전용” 요금제가 필요함 |
| 온보딩이 셀프 서비스이고 즉각적이어야 함 | 고객 수가 한 자릿수임 | 시끄러운 테넌트에 전용 데이터베이스가 필요함 |
기본값은 멀티테넌트로 두고, 테넌트별로 근거가 생길 때 벗어나는 것이 좋습니다. 싱글테넌트 코드베이스에 테넌시를 나중에 끼워 넣는 일은 과부하를 일으키는 고객 하나를 나중에 silo로 분리하는 일보다 훨씬 어렵습니다.
한계와 트레이드오프
- 격리는 강제되는 만큼만 유효합니다. 애플리케이션 코드에서 누락된 테넌트 필터 하나가 고전적인 테넌트 간 데이터 유출입니다. 경계를 데이터 계층(행 수준 정책, 객체별 ACL)으로 밀어 넣어 플랫폼이 실패 시 닫히도록(fail closed) 해야 합니다.
- 공유되는 영향 범위. 장애, 잘못된 배포, 침해 한 번이 모든 테넌트에 동시에 영향을 줄 수 있습니다. 단계적 롤아웃과 테넌트별 백업은 공유 자체가 아니라 피해의 범위를 줄여 줍니다.
- 노이지 네이버는 구조적입니다. 할당량과 스케줄링은 경합을 관리할 뿐이고, 경합을 없애는 것은 부분 silo화뿐이며 그만큼 silo에 가까운 비용이 듭니다.
- 커스터마이징의 상한. 테넌트가 하나의 코드베이스를 공유하므로 테넌트별 동작은 설정과 피처 플래그 안에 있어야 합니다. 싱글테넌트 고객에게는 없는 제약입니다.
- 어디에나 필요한 테넌트 컨텍스트. 모든 쿼리, 캐시 키, 작업, 로그 줄이 테넌트를 인식해야 합니다. 복잡성이 인프라에서 애플리케이션으로 옮겨 가며, 관리형 데이터 계층 격리는 바로 이 부담을 흡수하기 위해 존재합니다.
Back4app에서의 멀티테넌트 호스팅
Back4app은 관리형 데이터베이스, 자동 생성되는 REST 및 GraphQL API, 인증, 파일 스토리지, Cloud Code 서버리스 함수를 결합한 오픈소스 Backend as a Service(BaaS) 플랫폼입니다. Back4app은 두 층위 모두에서 멀티테넌트입니다. 플랫폼으로서는 공유 인프라 위에서 수천 개의 격리된 앱 백엔드를 실행하며, 그래서 새 백엔드가 무료 요금제에서 몇 분 만에 프로비저닝됩니다. 사용자의 애플리케이션 테넌트에 대해서는 격리가 관례가 아니라 데이터 계층의 기능입니다. 모든 객체가 ACL을 지니고, 역할이 테넌트별로 사용자를 묶으며, 클래스 수준 권한이 스키마 전체의 규칙을 정하고, Back4app이 이 모두를 모든 요청에서 강제합니다. 행 수준 보안에 관한 엔지니어링 심층 글은 문서 데이터베이스에서의 전체 패턴을 보여 줍니다. WHERE 절에 대한 규율은 필요하지 않습니다.
자주 묻는 질문
클라우드 컴퓨팅에서 멀티테넌시란 무엇입니까?
소프트웨어의 단일 인스턴스와 그 아래의 인프라가 테넌트라 불리는 여러 고객을 서비스하는 아키텍처입니다. 테넌트는 컴퓨팅, 스토리지, 하나의 코드베이스를 공유하지만 각 테넌트의 데이터는 논리적으로 격리되어 다른 테넌트에게 보이지 않습니다. 클라우드의 경제성을 가능하게 하는 패턴입니다. 고객 하나를 추가하는 일이 새 하드웨어가 아니라 설정 변경이 됩니다.
멀티테넌트 호스팅과 싱글테넌트 호스팅의 차이는 무엇입니까?
싱글테넌트는 고객마다 전용 인스턴스와 데이터베이스를 제공합니다. 통제력과 물리적 격리가 최대이지만 가격이 더 높고, 인스턴스마다 패치와 업그레이드를 따로 해야 합니다. 멀티테넌트는 하나의 인스턴스를 모든 고객이 공유합니다. 테넌트당 비용이 낮고 모두를 위한 업데이트 주기가 하나이며, 격리는 물리적이 아니라 논리적으로 강제됩니다. 대부분의 SaaS는 멀티테넌트로 운영되며, 규제 대상이거나 규모가 매우 큰 고객은 싱글테넌트를 정당화하기도 합니다.
멀티테넌트 클라우드는 안전합니까?
격리가 올바르게 강제된다면 안전합니다. 테넌트는 서로의 데이터를 볼 수 없습니다. 남는 위험은 테넌트 필터를 건너뛰는 애플리케이션 버그와, 공유 시스템의 더 넓은 영향 범위입니다. 침해나 장애 한 번이 모든 테넌트에 닿을 수 있습니다. 그래서 가장 견고한 설계는 모든 쿼리가 WHERE 절을 기억하리라 믿는 대신, 행 수준 정책과 객체별 접근 제어로 격리를 데이터 계층까지 내려 보냅니다.
노이지 네이버 문제란 무엇입니까?
한 테넌트가 공유 CPU, 메모리, I/O를 과도하게 사용해 같은 인프라 위의 다른 모든 테넌트의 성능이 떨어지는 현상입니다. 완화책으로는 테넌트별 할당량과 속도 제한, 리소스 스케줄링, 오토스케일링이 있고, 한 테넌트가 지속적으로 과부하를 일으킨다면 경합이 일어나는 구성 요소(보통 데이터베이스)를 별도의 silo로 분리합니다.
공유 클라우드에서 테넌트 데이터는 어떻게 분리됩니까?
데이터베이스 계층에는 세 가지 정석 패턴이 있습니다. 모든 행이 테넌트 식별자를 지니는 공유 스키마(밀도가 가장 높고 보통 행 수준 보안과 함께 사용), 공유 데이터베이스 안의 테넌트별 스키마, 그리고 테넌트별 데이터베이스(격리가 가장 강하고 비용도 가장 높음)입니다. 그 아래에서는 인프라가 자체 계층을 더합니다. 가상 머신, 컨테이너 네임스페이스, 마이크로 VM이 테넌트의 워크로드를 서로 떼어 놓습니다.
멀티테넌시는 가상화와 같은 것입니까?
아닙니다. 가상화는 한 대의 물리 머신을 격리된 가상 머신들로 나누고, 멀티테넌시는 하나의 애플리케이션 인스턴스를 여러 고객이 공유하는 것입니다. 둘은 상호 보완적입니다. 가상화는 제공업체가 테넌트의 워크로드를 격리하는 데 쓰는 메커니즘 중 하나이고, 멀티테넌시는 애초에 무엇을 공유할지 결정하는 아키텍처 패턴입니다.
언제 싱글테넌트를 선택해야 합니까?
엄격한 규제 체계나 계약이 물리적 격리 또는 데이터 레지던시를 요구할 때, 고객이 인스턴스 단위의 깊은 커스터마이징을 필요로 할 때, 또는 고가치 계정의 성능 보장이 비용보다 중요할 때입니다. 점점 더 흔해지는 답은 혼합 테넌시입니다. 대부분의 테넌트는 공유 인프라에 pool로 두고, 규제 대상이거나 거대하거나 시끄러운 소수만 silo로 분리합니다.
멀티테넌시가 SaaS에 중요한 이유는 무엇입니까?
구독형 소프트웨어가 기반으로 삼는 아키텍처이기 때문입니다. 하나의 코드베이스가 모든 고객을 서비스하므로 수정과 기능이 모든 테넌트에 한 번에 배포되고, 하드웨어 활용도가 고객 기반 전체에 분산되며, 신규 고객 온보딩 비용은 거의 0에 가깝습니다. 멀티테넌시가 없다면 구독 하나하나가 전용 서버와 고객별 유지 보수 비용을 떠안게 됩니다.