AI 에이전트에게 CRM 접근 권한을 줄 때 가장 무서운 점은 '한 고객의 데이터를 다른 고객에게 유출하지 않으려면 어떻게 해야 하는가'라는 당연한 질문입니다.
The scariest thing about giving an AI agent access to your CRM is the obvious question: what stops it from leaking one customer's data to another?
핵심 요약
AI 에이전트의 데이터 유출을 막으려면 별도의 권한 체계를 만들지 말고 기존의 데이터 계층 보안을 그대로 활용해야 합니다.
- 사용자 권한 상속 — 에이전트는 슈퍼유저가 아닌 로그인한 사용자의 권한을 그대로 따름
- 데이터 계층 보안 — 쿼리 단계에서 강제되는 필터를 통해 에이전트의 데이터 접근 범위를 제한함
- 구조적 격리 — 프롬프트 주입 공격을 방지하기 위해 코드 수준에서 테넌트 간 격리를 수행함
- 인간 개입 — 민감한 쓰기 작업은 에이전트가 제안하고 인간이 최종 승인하는 구조를 채택함
우리한테 답은 "새로울 거 없다"였고, 사실 그게 핵심이야.
관리자 플랫폼에 대화형 AI 에이전트를 붙일 때, 보안 버그를 원천 차단하는 결정을 하나 내렸어. 에이전트를 별도의 접근 권한을 가진 시스템으로 만들지 않은 거야. REST API가 이미 쓰고 있는 보안 서비스에 대화형 인터페이스만 씌운 거지.
실제로 이게 무슨 뜻인지 알려줄게.
1. 에이전트는 슈퍼유저가 아니라 사용자 본인의 권한을 그대로 가져가. 모든 에이전트 세션은 로그인한 사용자의 컨텍스트(조직, 역할, 부서 등)를 JWT에서부터 에이전트가 호출하는 모든 도구까지 그대로 물려받아. 에이전트는 절대 사용자 권한을 넘어서지 않고, 딱 '너'처럼 행동해.
2. 모든 도구 호출은 동일한 AccessScopeService를 거쳐. 에이전트가 "내 오픈 리드 보여줘" 같은 도구를 실행할 때, 데이터베이스를 직접 찌르지 않아. 일반 API 요청이 사용하는 도메인 서비스를 똑같이 호출하고, 거기서 똑같은 역할 기반 필터가 적용돼. 그러니까 일반 에이전트의 AI는 자기 기록만 보고, 관리자의 AI는 자기 팀 기록만 보는 거야. 사용자가 직접 조회할 수 없는 데이터는 AI도 절대 못 가져와. WHERE organizationId = … 조건문이 에이전트가 아니라 그 밑단에서 박혀버리거든.
3. 테넌트 간 격리는 프롬프트가 아니라 구조적으로 해결했어. 시스템 프롬프트에 "다른 조직 데이터는 보지 마"라고 빌고 앉아있지 않아. 조직 범위 제한은 코드의 쿼리 계층에서 강제로 적용되거든. 프롬프트 인젝션 따위로 Prisma의 where 절을 뚫는 건 불가능해.
4. 민감한 작업은 사람이 직접 확인해야 해. 읽기 작업은 자동으로 범위가 제한되지만, 리드 삭제, 거래 재할당, 페이지 게시, 브랜드 설정 변경 같은 중요한 '쓰기' 작업은 사용자가 직접 승인해야 실행돼. 에이전트가 제안하고, 사람이 확인하는 방식이지.
5. 이 아키텍처 하나로 성격이 완전히 다른 에이전트 3개를 깔끔하게 돌려. 접근 제어가 공유 가능한 서비스 계층에 있으니까, 핵심 에이전트 하나로 내부 직원용 어시스턴트(전체 RBAC), 로그인한 고객용 컨시어지(CUSTOMER 역할로 제한), 익명 공개용 프리세일즈 봇(가상 플랫폼 ID, 읽기 전용, 데이터 저장 안 함)을 다 돌리는 거야. 엔진은 하나인데 신뢰 수준은 세 개지. 권한 로직을 따로 짤 필요가 없어.
기존 제품에 AI를 붙이려는 사람들을 위한 교훈은 이거야. 에이전트한테 새로운 열쇠를 쥐여주지 마. 이미 만들어둔 자물쇠를 쓰게 만들어. 권한 관리를 UI 계층이 아니라 데이터 계층에서 강제하고 있다면, AI 에이전트는 보안 구멍이 아니라 바로 출시 가능한 훌륭한 기능이 될 거야.
#AI #LLM #Security #RBAC #SoftwareArchitecture #AgenticAI

