분리된 데이터 파티션을 여러 클라이언트 조직(테넌트)에 제공하는 방법으로 애플리케이션에서 다중 테넌트 지원을 지원할 수 있습니다. 이렇게 하면 모든 테넌트에 동일한 데이터 스키마를 유지하면서 각 테넌트의 데이터 값을 맞춤설정할 수 있습니다. 테넌트를 추가할 때 데이터 구조를 변경할 필요가 없기 때문에 새로운 테넌트의 프로비저닝이 보다 효율적으로 이루어집니다.
멀티테넌시의 이점
Datastore 모드의 Firestore에서는 멀티테넌시 애플리케이션이 테넌트마다 분리된 데이터 사일로를 사용할 수 있고, 다음 항목도 계속 사용 가능합니다.
단일 프로젝트
종류의 단일 논리 구조
단일 색인 정의 집합(종류가 각 테넌트에 대해 논리적으로 동일하기 때문)
Datastore는 네임스페이스를 제공하여 멀티테넌시를 사용 설정합니다.
멀티테넌시 및 파티션을 나눈 데이터
Datastore 모드는 각 테넌트의 데이터를 사일로로 격리하기 위해 파티션을 사용합니다. 프로젝트 ID와 네임스페이스 ID의 조합은 각 파티션을 식별하는 파티션 ID를 형성합니다. 항목은 단일 파티션에 속하며 쿼리의 범위도 단일 파티션으로 지정됩니다.
항목의 네임스페이스 지정
네임스페이스는 항목을 생성할 때 지정하게 되며 항목을 생성한 후에는 네임스페이스를 변경할 수 없습니다. 항목의 네임스페이스를 명시적으로 지정하지 않으면 문자열 식별자가 없는 기본 네임스페이스로 자동 할당됩니다.
상위 항목이 있는 경우 네임스페이스 사용법
항목과 그 상위에 있는 모든 항목은 단 하나의 네임스페이스에 소속됩니다. 즉, 다른 상위 항목이 지정된 항목을 생성하면 하위 항목과 상위 항목이 모두 동일한 네임스페이스에 있게 되며 다른 네임스페이스를 지정할 수 없습니다.
샘플 사용 사례
멀티테넌시의 주요 이점은 동일한 애플리케이션을 다양한 클라이언트 조직에 사용할 수 있다는 데 있습니다. 특정 종류에 대해 이 이점을 활용하려면 네임스페이스에 상관없이 애플리케이션이 동일하게 작동해야 합니다. 예를 들어 애플리케이션의 관점에서 한 네임스페이스에 있는 Task 종류의 항목은 기타 모든 네임스페이스의 Task 종류 항목과 논리적으로 동일해야 합니다. 그래야 애플리케이션에서 Task 항목이 포함된 네임스페이스에 상관없이 단일 집합의 색인 정의를 사용해 Task 쿼리를 지원할 수 있습니다.
사용자 기반으로 데이터를 격리하는 Task List 애플리케이션을 예시로 들어보겠습니다. 애플리케이션은 사용자 이름을 기반으로 네임스페이스를 정의하므로 다음과 같은 파티션으로 나누어집니다.
애플리케이션은 모든 네임스페이스에 사용할 Task 종류의 논리적 구조를 다음과 같이 정의할 수 있습니다.
kind: Task
properties:
- "done", Boolean
- "created", DateTime
- "description", String, excluded from index
사용자가 Task 종류의 항목을 생성할 때 항목은 사용자의 자체 파티션에 저장되므로 데이터가 격리됩니다. Task 종류에는 단 하나의 스키마가 사용되므로 애플리케이션은 여러 네임스페이스에서 Task 항목을 일관되게 처리합니다. 데이터가 격리되어 있고 일관된 작동을 하는 애플리케이션은 멀티테넌트를 지원한다고 할 수 있습니다.
Task 종류의 논리적 구조가 네임스페이스별로 차이가 있는 경우에는 네임스페이스마다 Task 항목을 다르게 처리하기 때문에 애플리케이션이 멀티테넌시가 아닙니다. 네임스페이스에 따라 스키마가 다른 Task 종류를 예시로 들어보겠습니다.
Joe 네임스페이스의 Task 항목이 색인에서 description 속성을 제외하는 경우
Alice 네임스페이스의 Task 항목이 색인의 description 속성을 포함하는 경우
애플리케이션은 description 속성에서 Alice의 Task 항목을 쿼리할 수 있지만 description 속성에서는 Joe의 Task 항목을 쿼리할 수 없기 때문에 애플리케이션은 멀티테넌시가 되지 않습니다.
콘솔에서 네임스페이스 보기
프로젝트에 사용된 네임스페이스 통계를 보려면 Google Cloud Console의 Datastore 대시보드 페이지를 방문하세요. 프로젝트에서 어떤 네임스페이스가 사용되는지 프로그래매틱 방식으로 확인하려면 네임스페이스 쿼리를 참조하세요.
테넌트 내에 데이터를 그룹화해야 한다면 데이터를 종류별로 분류하고 항목 그룹과 관련이 높은 데이터를 구성할 수도 있습니다.
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["이해하기 어려움","hardToUnderstand","thumb-down"],["잘못된 정보 또는 샘플 코드","incorrectInformationOrSampleCode","thumb-down"],["필요한 정보/샘플이 없음","missingTheInformationSamplesINeed","thumb-down"],["번역 문제","translationIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-04-22(UTC)"],[[["\u003cp\u003eMultitenancy in applications is supported by creating separate data partitions for each client organization (tenant), allowing for custom data values while maintaining a uniform data schema across all tenants.\u003c/p\u003e\n"],["\u003cp\u003eDatastore mode facilitates multitenancy through the use of namespaces, where each namespace, combined with a project ID, forms a partition ID, isolating each tenant's data.\u003c/p\u003e\n"],["\u003cp\u003eEntities in Datastore mode are confined to a single partition, and queries are restricted to that same partition, with all entities and their ancestors within a hierarchical structure sharing the same namespace.\u003c/p\u003e\n"],["\u003cp\u003eApplications must process entities of the same kind consistently across different namespaces to be considered multitenant, which means using a single schema and behavior for a given entity type.\u003c/p\u003e\n"],["\u003cp\u003eThe namespace assigned to an entity cannot be changed once the entity has been created, and entities without a specified namespace are automatically assigned to the default namespace.\u003c/p\u003e\n"]]],[],null,["# Multitenancy\n\nYou can support *multitenancy* in your application by providing separate data\npartitions for multiple client organizations, known as tenants. This allows you\nto customize *data values* for each tenant, while keeping the same *data schema*\nfor all tenants. This makes provisioning new tenants more efficient because\nyou don't have to change data structure when you add a tenant.\n\nBenefits of multitenancy\n------------------------\n\nFirestore in Datastore mode allows a multitenant application to use separated silos of data\nfor each tenant while still using:\n\n- a single project\n- a single logical structure for the kinds\n- a single set of index definitions, because the kinds are the same logically for each tenant\n\nDatastore mode enables multitenancy by providing *namespaces*.\n\nMultitenancy and partitioned data\n---------------------------------\n\nDatastore mode uses *partitions* to silo data for each tenant. The\ncombination of a project ID and a namespace ID forms a *partition ID*, which\nidentifies each partition. An entity belongs to a single partition, and queries\nare scoped to a single partition.\n| **Note:** Namespaces are not a security mechanism in Datastore mode. A user with access to one partition in a project has access to all partitions in the project. Namespaces provide a way to organize your entities within a project.\n\nSpecifying a namespace for an entity\n------------------------------------\n\nYou specify the namespace when you create the entity: after you create the entity,\nyou cannot change the namespace. If you don't explicitly specify a namespace for\nan entity, it is automatically assigned to the *default namespace*, which has\nno string identifier.\n\nUsing namespaces with parent entities\n-------------------------------------\n\nAn entity and all of its ancestors belong to one and only one namespace. This\nmeans that when you create an entity with another entity designated as parent,\nthe child entity is in the same namespace as its parent: you cannot specify\nsome other namespace.\n\nSample use case\n---------------\n\nA key benefit of multitenancy is having the same application serve multiple\nclient organizations. To achieve this benefit, for a given kind, your\napplication should behave the same regardless of the namespace. For example,\nfrom the application's perspective, an entity of kind `Task` in one namespace\nshould logically be the same as an entity of kind `Task` in all other\nnamespaces. Your application could then use a single set of index definitions\nto support `Task` queries, regardless of which namespaces contain `Task`\nentities.\n\nFor example, consider a Task List application that silos data on a per user\nbasis. The application could define namespaces based on user name, resulting in\nthe following partitions: \n\n```\nPartition ID: project:\"my_project_id\"/namespace:\"Joe\"\nPartition ID: project:\"my_project_id\"/namespace:\"Alice\"\nPartition ID: project:\"my_project_id\"/namespace:\"Charlie\"\n```\n\nThe application could define a logical structure of a `Task` kind as follows, to\nuse for all namespaces: \n\n```\nkind: Task\nproperties:\n - \"done\", Boolean\n - \"created\", DateTime\n - \"description\", String, excluded from index\n```\n\nWhen a user creates an entity of kind `Task`, the entity is stored in the user's\nown partition, resulting in siloed data. The application processes `Task`\nentities consistently across namespaces because only one schema is used for the\n`Task` kind. An application with siloed data and consistent behaviour would be\nmultitenant.\n\nIf the logical structure of a `Task` kind differs by namespace, the application\nwould not be multitenant because it processes `Task` entities differently\nacross namespaces. For example, consider `Task` kinds that have different schema\nbased on namespace:\n\n- `Task` entities in the Joe namespace *exclude* the `description` property from the index\n- `Task` entities in the Alice namespace *include* the `description` property from the index\n\nThe application could query on the `description` property for Alice's `Task`\nentities, but it could not query on the `description` property for Joe's `Task`\nentities, so the application would not be multitenant.\n\nViewing namespaces in the console\n---------------------------------\n\nTo see statistics for the namespaces used in your project, visit the\n[Datastore Dashboard](https://console.cloud.google.com/datastore/stats) page in\nthe Google Cloud console. To programmatically determine which namespaces are used\nin your project, see [Namespace queries](/datastore/docs/concepts/metadataqueries#namespace_queries).\n\nIf you need to group data *within* a tenant, you can categorize your data by\n[kinds](/datastore/docs/concepts/entities#kinds_and_identifiers), and you can also organize highly related data with\n[entity groups](/datastore/docs/concepts/entities#entity_groups).\n\nWhat's next\n-----------\n\n- Learn about [entities](/datastore/docs/concepts/entities).\n- Learn about [queries](/datastore/docs/concepts/queries)."]]