
테넌트별로 격리된 AI 에이전트 기반 구축하기
요약
SaaS 환경에서 AI 에이전트를 구축할 때 발생하는 멀티 테넌트 격리 문제를 해결하기 위한 아키텍처를 소개합니다. 애플리케이션 코드가 아닌 클라우드 IAM 경계를 통해 테넌트별로 독립된 실행 환경을 할당하여 보안과 데이터 문맥을 보호하는 방식을 제안합니다.
핵심 포인트
- 에이전트는 단순 API와 달리 자율적인 실행 주체이므로 강력한 격리가 필요함
- 제어 플레인과 데이터 플레인을 분리하여 에이전트의 환경 변경 권한을 제한함
- 1테넌트 1환경 원칙을 통해 전용 서비스 계정과 독립된 리소스를 할당함
- 애플리케이션 코드가 아닌 클라우드 IAM 수준에서 테넌트 간 권한 분리 수행
안녕하세요, SALESCORE의 무라모토입니다.
SALESCORE에서는 영업 조직의 회의·상담 데이터를 AI로 분석하여, 가시화와 제안으로 연결하는 프로덕트를 제공하고 있습니다. 그 개발 과정에서 저희는 "고객별 AI 에이전트 환경을 어떻게 제공할 것인가"라는 과제에 직면해 왔습니다. 본 기사에서는 이 과제에 대해 저희가 도달한 구성을 소개합니다.
과제 — 에이전트는 기존 API와 성질이 다르다
AI 에이전트를 SaaS에 통합할 때, 가장 먼저 인식해야 할 점이 있습니다. 에이전트는 "요청을 받아 답을 돌려주는 API"가 아니라, 파일을 읽고 쓰고, 툴을 호출하며, 장시간 자율적으로 움직이는 실행 주체라는 점입니다.
이러한 성질은 기존의 멀티 테넌트 (Multi-tenant) 방식과 궁합이 좋지 않습니다.
첫째, 권한 분리의 문제입니다. 여러 테넌트를 하나의 공유 프로세스에 공존시키면, 테넌트 간의 분리는 애플리케이션 코드(Application code)로 지켜야 합니다. 정형적인 CRUD 처리라면 이것으로 충분했습니다. 하지만 자율적으로 판단하여 움직이는 에이전트가 상대라면, 코드의 사소한 고려 누락이 그대로 고객 데이터의 침범으로 이어질 수 있습니다.
둘째, 테넌트별 차이입니다. 계약 중인 CRM 연동 여부, 이용 가능한 툴, 접속에 필요한 인증 정보는 테넌트마다 다릅니다. 모두에게 동일한 능력을 가진 에이전트를 배포한다는 단순화는 불가능합니다.
셋째, 문맥(Context)의 축적입니다. 에이전트 추론의 질은 모델의 성능만으로 결정되지 않습니다. 대상에 대한 이해——지금까지 무엇을 관측했고, 무엇을 알고 있는가——를 계속해서 축적함으로써 판단과 제안의 정밀도가 올라갑니다. 그리고 이 축적된 문맥은 고객의 데이터 그 자체입니다. 축적될수록 가치가 올라가는 동시에, 절대로 유출되어서는 안 되는 것이 됩니다.
이 세 가지를 동시에 만족하기 위해 저희는 다음과 같은 방침을 세웠습니다.
격리는 애플리케이션 코드가 아니라 클라우드의 IAM 경계에서 수행한다
환경을 구성하는 측과 환경 안에서 움직이는 측의 권한을 완전히 분리한다
문맥은 격리 경계 내부에 축적한다
구체적으로는, 테넌트마다 완전히 독립된 에이전트 실행 환경을 할당하는 구성입니다. 실행 환경의 구현으로서 현재는 Google Cloud Run을 사용하고 있지만, 이는 방침을 만족하는 수단 중 하나이며, 후반부에서 선정 이유와 함께 설명하겠습니다.
전체 아키텍처
기반은 크게 두 가지 플레인(Plane)으로 나뉩니다.
┌──────────────────────────────────────────────────┐
│ 본체 애플리케이션 (SaaS) │
│ 관리 UI ──────────────┐ 채팅 UI ─────┐ │
...
| 컴포넌트 | 역할 |
|---|---|
| 본체 애플리케이션 | 테넌트 관리, 인증, 회의 데이터 처리, 가시화 UI, 채팅 UI를 가진 SaaS 본체 |
| ... |
설계상 가장 중요한 판단은, 제어 플레인(Control plane)과 데이터 플레인(Data plane)의 분리입니다. 환경을 변경할 권한을 가진 것은 프로비저너(Provisioner)뿐이며, 에이전트의 실행체는 배포나 구성 변경 권한을 일절 가지지 않습니다. 에이전트는 외부의 지시에 따라 움직이는 존재이기에, 실행체 스스로가 자신의 환경을 다시 쓸 수 없다는 점이 기반 안전성의 전제가 됩니다.
테넌트별 격리 — 1테넌트 1환경
멀티 테넌트 격리 단위는 "1테넌트당 1개의 독립된 실행 환경"입니다. 관리 UI에서 테넌트의 에이전트 환경을 활성화하면, 프로비저너가 다음 리소스 세트를 테넌트 전용으로 할당합니다.
| 리소스 | 역할 |
|---|---|
| 전용 서비스 계정 (Service Account) | 이 테넌트의 워커(Worker)만이 가지는 ID. 타 테넌트의 리소스에는 도달할 수 없음 |
| ... |
포인트는, 격리를 애플리케이션 코드가 아니라 클라우드의 IAM 경계에서 실현하고 있다는 점입니다. 테넌트 A의 워커는 테넌트 A 전용 서비스 계정으로 동작하며, 테넌트 A의 버킷(Bucket)과 시크릿(Secret)에만 액세스 권한을 가집니다. 설령 에이전트가 예상치 못한 동작을 하더라도, 넘을 수 있는 경계는 IAM이 허가한 범위로 한정됩니다. "코드가 올바르기 때문에 안전하다"가 아니라, "실수하더라도 넘을 수 없다"를 목표로 한 구성입니다.
또한, 워커의 호출은 본체 애플리케이션이 가진 전용 호출 ID에 의해서만 허용됩니다. 에이전트 환경이 인터넷을 향해 열리는 일은 없습니다.
능력 프로파일과 툴 사이드카 (Tool Sidecar)
테넌트에 따라 사용할 수 있는 도구는 다릅니다. CRM 연동을 계약한 테넌트에게는 CRM 도구가 필요하며, 그렇지 않은 테넌트에게는 존재해서는 안 됩니다.
이를 표현하는 것이 **능력 프로파일 (Capability Profile)**입니다. 프로비저너(Provisioner)는 테넌트별 계약 및 설정에 따라 유효한 도구군을 결정하고, 실행 환경을 멀티 컨테이너 (Multi-container, 사이드카) 구성으로 조립합니다.
테넌트 전용 실행 환경 (1개의 서비스)
├── 에이전트 워커 (Agent Worker)
├── 제안 조작 도구
...
사이드카에는 기동 프로브 (Startup Probe)가 설정되어, 도구군이 준비될 때까지 실행 환경은 요청을 받지 않습니다. 각 도구가 필요로 하는 인증 정보는 시크릿 관리 (Secret Management)로부터 실행 시점에 주입되며, 컨테이너 이미지에 포함(bake-in)되지 않습니다. 사용하지 않는 도구는 비활성화된 것이 아니라 해당 테넌트의 환경에 존재하지 않는 것——이것이 능력의 차등 제공에 대한 우리의 해답입니다.
워크스페이스 — 스토리지 마운트
또 다른 중요한 설계 결정은, 테넌트 전용 스토리지 버킷 (구현에는 Cloud Storage를 사용함)을 실행 환경에 볼륨(Volume)으로 마운트하는 것입니다. 에이전트에게는 그저 파일 시스템처럼 보입니다.
파일 조작을 MCP 도구로 제공하는 선택지도 있었으나, 채택하지 않았습니다. 에이전트가 가장 잘하는 것은 CLI 기반의 파일 조작이기 때문입니다. 디렉토리를 나열하여 구조를 파악하고, 검색으로 목적 파일을 찾고, 읽고, 쓰는——에이전트가 일상적으로 수행하는 이 작업 양식을 도구 호출 스키마로 번역하는 것은 우회하는 길입니다. 파일 시스템으로 보여주면 에이전트는 익숙한 도구로 그대로 작업할 수 있습니다. 도구의 스키마 설계도, 호출 시의 오버헤드도 필요하지 않습니다.
이 마운트 구성은 기반의 다른 요소들과도 맞물려 있습니다.
- 마운트는 테넌트 전용 서비스 계정의 권한으로 수행되므로, IAM 경계가 그대로 유지됩니다.
- 쓰여진 내용은 버킷에 영속화되므로, 인스턴스가 사라져도 상태는 남습니다 (후술할 Scale-to-zero와 양립 가능).
- 후술할 스킬 정의와 ContextGraph도 이 워크스페이스 위에 놓입니다.
에이전트에게 전달하는 도구는 MCP와 같은 도구 호출 방식일 필요가 없습니다. 에이전트가 본래 잘하는 양식——쉘(Shell)과 파일——에 맞춰 환경 측을 설계하는 것이 더 잘 작동하는 경우가 많습니다.
에이전트 워커 (Agent Worker)
워커는 에이전트 실행 엔진을 래핑(Wrap)한 HTTP 서버입니다. 역할은 세 가지가 있습니다.
| 역할 | 내용 |
|---|---|
| 채팅 | 본체 애플리케이션의 채팅 UI와 SSE로 연결되어, 추론의 중간 과정이나 도구 호출 상황을 순차적으로 스트리밍함 |
| ... |
요청 스코프 (Request Scope)
에이전트에 대한 요청은 "무엇을 대상으로 작업할 것인가"를 명시적인 스코프로 가집니다.
| 스코프 | 대상 지정 | 이용 가능한 문맥 |
|---|---|---|
| 테넌트 | 없음 | 테넌트 전체 |
| ... |
요청이 주장하는 스코프와 검증된 컨텍스트 정보가 나타내는 스코프는 일치해야 하며, 워커는 이를 요청마다 검증합니다. 동일한 테넌트 내부라 하더라도, 에이전트는 선언된 문맥 밖을 건드리지 않는 구조입니다.
스킬을 통한 능력 확장
에이전트의 행동은 테넌트의 워크스페이스에 배치된 스킬 정의에 의해 확장됩니다. 스킬은 컨테이너 이미지에 포함되지 않으므로, 테넌트별 능력의 추가 및 변경 시 재배포가 필요하지 않습니다. 영업 분석 절차나 문서 평가 관점과 같은 도메인 지식을 테넌트 단위로 운영 과정에서 키워나갈 수 있습니다.
ContextGraph — 축적되는 문맥
서두에서 언급한 세 번째 과제인 문맥의 축적을 담당하는 것이 ContextGraph입니다.
ContextGraph는 에이전트가 대상(고객이나 안건)별로 구축해 나가는 인식의 이력입니다. 단순히 과거 정보를 기록해 두는 메커니즘이 아닙니다. 에이전트는 자신이 그것을 "어떤 자격으로 알고 있는가"——직접 관측한 사실인지, 거기서 도출한 추론인지, 두고 있는 전제인지——를 구분하여 유지하며, 아직 확인되지 않은 것이나 서로 일치하지 않는 관측도 있는 그대로 다룹니다.
따라서 관측이 늘어날 때 발생하는 것은 단순한 정보량의 증가가 아니라 **이해의 갱신 (Update of Understanding)**입니다. 가설이 뒷받침되거나 혹은 뒤집히고, 미확정이었던 것이 확정되어 갑니다. 사람이 고객과의 대화를 거듭할수록 기억이 늘어날 뿐만 아니라 이해 그 자체가 깊어지는 것과 유사한 동작을 보이며, 이것이 관측과 함께 판단 및 제안의 정밀도를 끌어올립니다.
외부 지식을 그 자리에서 검색하여 도입하는 RAG (Retrieval-Augmented Generation)와는 애초에 담당하는 역할이 다릅니다. RAG가 다루는 것이 '참조해야 할 지식'이라면, ContextGraph가 다루는 것은 '대상을 어떻게 이해하고 있는가에 대한 인식 상태'입니다. 에이전트는 실행할 때마다 먼저 대상의 ContextGraph를 읽어 이전까지의 인식을 계승한 뒤 작업을 시작하며, 새로운 관측이 있으면 작업의 완료 조건으로서 이를 갱신합니다.
내부 구조의 상세한 내용에 대해서는 본 기사에서 다루지 않지만, 중요한 점은 이렇게 축적된 문맥이 테넌트 전용 워크스페이스에 저장되며, 전절까지의 격리 경계 안쪽에서 관리된다는 점입니다. 문맥의 축적과 격리는 어느 한쪽만으로는 성립할 수 없는 설계입니다.
실행 환경으로서의 Cloud Run
지금까지의 구성은 특정 클라우드 서비스를 전제로 한 것이 아닙니다. '테넌트마다 독립된 실행 환경을 IAM 경계와 함께, 필요할 때만 구동한다'라는 요구사항을 충족하는 기반이라면 성립합니다. 저희는 현재 이 실행 환경으로 Google Cloud Run을 선택하고 있습니다.
1테넌트 1환경이라는 구성은 언뜻 보기에는 리소스 낭비처럼 보일 수 있습니다. 이를 현실적으로 만드는 것이 Cloud Run의 특성입니다.
| 특성 | 기반에서의 의미 |
|---|---|
| 스케일 투 제로 (Scale-to-zero) | 사용되지 않는 테넌트의 환경은 인스턴스 0으로 대기하며, 과금되지 않음 |
| ... |
특히 스케일 투 제로의 존재감이 매우 커서, 테넌트 수가 늘어나도 유휴 비용 (Idle Cost)이 선형적으로 증가하지 않습니다. '테넌트마다 전용 환경을 갖는다'라는 언뜻 사치스러워 보이는 구성은, 서버리스의 종량제 과금이 있기에 비로소 경제적으로 성립합니다.
Cloud Run Sandboxes — 격리의 더 깊은 안쪽으로
지금까지의 격리는 테넌트와 테넌트 '사이'를 나누는 이야기였습니다. 한 단계 더 안쪽——테넌트의 환경 안에서 에이전트가 생성·실행하는 코드의 격리——에 대해서도 플랫폼 측에서 선택지가 나오고 있습니다.
2026년 7월, Cloud Run Sandboxes가 퍼블릭 프리뷰 (Public Preview)로 발표되었습니다. Cloud Run 인스턴스 내부에 밀리초 단위로 기동하는 경량 샌드박스 (Sandbox)를 만들어, 신뢰할 수 없는 코드를 실행할 수 있는 기능입니다. 샌드박스 내부에서는 환경 변수나 메타데이터 서버에 접근할 수 없고, 네트워크는 기본적으로 차단되며, 파일 시스템에 대한 쓰기는 실행 종료와 함께 파기됩니다. 추가 요금은 없으며, 인스턴스에 할당된 리소스 범위 내에서 동작합니다.
에이전트는 코드를 생성하여 실행하는 존재입니다. 현재 구성에서는 에이전트가 실행하는 처리가 워커 (Worker)의 권한——즉, 테넌트 전용 서비스 계정(Service Account)——으로 동작하지만, 생성된 코드의 실행만 인증 정보가 없는 샌드박스로 격리한다면 방어 계층을 한 층 더 늘릴 수 있습니다. 테넌트 간은 IAM 경계로, 테넌트 내의 생성 코드는 샌드박스로. 플랫폼 자체가 에이전트 워크로드 (Workload)를 향해 진화하고 있다는 점은, 실행 환경으로서 Cloud Run을 선택하는 이유를 하나 더 더해줍니다.
※ Cloud Run Sandboxes는 2026년 7월 시점의 퍼블릭 프리뷰 상태입니다.
요약
테넌트별로 격리된 AI 에이전트 기반 구축 설계를 정리합니다.
- 격리는 IAM으로 수행 — 테넌트마다 ID, 스토리지, 시크릿, 실행 환경을 분리하여 애플리케이션 코드에 격리의 책임을 지우지 않음
- 제어와 실행을 분리 — 환경을 구성하는 권한은 제어 평면 (Control Plane)만이 가지며, 에이전트 실행체는 자신의 환경을 변경할 수 없음
- 능력은 선언적으로 구성 — 능력 프로필로부터 도구 구성을 조립하며, 사용하지 않는 도구는 환경에 존재시키지 않음. 스킬은 재배포 없이 업데이트함
- 도구는 에이전트의 양식에 맞춤 — 파일 조작은 MCP 도구가 아니라 스토리지 마운트를 통해 제공함. 에이전트는 CLI를 통해 자연스럽게 작업할 수 있음
- 문맥은 격리 안쪽에 축적 — ContextGraph를 통해 대상별 이해가 깊어지며, 추론의 정밀도가 관측과 함께 향상됨
에이전트를 제품에 통합할 때의 과제는 모델의 성능 그 자체보다 권한, 격리, 문맥 관리와 같은 운영 측면에 집중됩니다. 실행 환경의 격리를 클라우드의 IAM 경계에 맡기고, 서버리스 (Serverless) 종량제 과금을 통해 경제성을 확보하는 본 구성은 그 현실적인 해답 중 하나가 될 것이라고 생각합니다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기