80%를 재구축하는 것을 멈추세요: 모든 AI 에이전트 SaaS가 첫 고객을 만나기 전에 갖춰야 할 기반
요약
AI 에이전트 SaaS를 구축할 때 재구축을 멈추지 않는 개발자에게 필수적인 기반 구조 체크리스트를 제시합니다. 인증, 워크스페이스 관리, 테넌트 격리(RLS), 실행 큐, 스트리밍, 비용 제어 등 핵심 요소를 다룹니다.
핵심 포인트
- Supabase JWT 검증 시 레거시 및 JWKS 비대칭 키 모두 처리 필요
- 테넌트 격리는 API만으로는 부족하며 모든 테이블에 RLS 적용 필수
- 실행 큐는 웹 요청 내부가 아닌 별도의 워커로 관리해야 함
- 비용 제어(Cost control)를 위해 월간 예산 및 토큰 한도 설정이 중요
제가 구축한 모든 AI 에이전트 SaaS는 고객이 비용을 지불하기 전에 동일한 기반 구조를 필요로 했습니다. 저는 멈출 때까지 여러 번 재구축했습니다. 처음 가졌으면 좋았을 체크리스트와, 사람들이 가장 자주 실수하는 두 항목에 대한 중요한 코드를 소개합니다.
체크리스트
- 두 언어에서의 인증(Auth). Supabase가 Next.js 측에서 사용자 로그인을 처리합니다. 여러분의 FastAPI 백엔드는 모든 요청마다 해당 JWT를 검증해야 합니다: 서명(signature), 수신자(audience), 만료 시간(expiry). Supabase는 이제 두 가지 종류의 서명 키(레거시 HS256 시크릿과 JWKS로 게시된 비대칭 키)를 가지고 있으므로, 둘 다 처리할 수 있어야 합니다.
- 워크스페이스와 역할. 소유자(Owner), 관리자(admin), 멤버, 그리고 초대 링크가 필요합니다. 사용자가 여러 워크스페이스에 속할 수 있는지 여부를 초기에 결정해야 합니다 (물론 그럴 것입니다).
- 데이터베이스에서 테넌트 격리(Tenant isolation)를 구현하고, API만으로는 부족합니다. 벡터 테이블을 포함한 모든 테이블에 행 수준 보안(Row-level security)을 적용해야 합니다.
- 실제 실행 큐(run queue). 에이전트 한 번의 실행은 1분을 걸릴 수 있습니다. 이를 웹 요청 내부가 아닌 큐에 넣고, 취소(cancel), 시간 초과(timeouts), 그리고 중간에 충돌하는 워커를 처리할 수 있어야 합니다.
- 실제 네트워크 환경에서 살아남는 스트리밍. 모든 이벤트를 저장하여, 재연하거나 출력을 잃어버리는 대신
Last-Event-ID부터 다시 연결할 수 있도록 해야 합니다. - 비용 제어(Cost control). 실행당 최대 단계 수, 실행당 토큰 한도, 그리고 할당량에 도달하면 새로운 실행을 거부하는 워크스페이스별 월간 예산이 필요합니다.
- 타입화된 출력(Typed outputs). 에이전트의 출력이 UI를 구동한다면, Pydantic으로 검증하고 한 번의 복구 시도(repair attempt)를 허용해야 합니다.
FastAPI에서 Supabase 토큰 검증하기 (두 키 유형 모두)
def decode_supabase_jwt(token: str, settings: Settings) -> dict[str, Any]:
alg = jwt.get_unverified_header(token).get(
패턴: API는 사용자를 대신하여 슈퍼유저(superuser)로 쿼리하지 않습니다. 트랜잭션을 열고, 사용자의 JWT 클레임(claims)을 설정한 다음, Supabase 자체의 REST 레이어와 정확히 같이 `authenticated` 역할로 전환합니다. 그러면 `WHERE` 절이 없는 쿼리에 대해서도 모든 RLS 정책이 적용됩니다.
async with pool.acquire() as conn, conn.transaction():
await conn.execute(
"select set_config('request.jwt.claims', $1, true), "
...
그리고 하나의 정책(policy):
alter table public.runs enable row level security;
create policy runs_select on public.runs for select to authenticated
...
## 두 사용자로 테스트하기
제가 가장 중요하게 생각하는 테스트는 두 개의 워크스페이스에 두 명의 사용자를 생성하고, 사용자 A가 에이전트와 실행(run)을 생성하도록 한 다음, 사용자 B가 모든 API 경로를 통해 403 또는 404 응답을 받는지 확인한 후, 마지막으로 사용자 B로서 Postgres에 A의 행(rows)을 직접 요청하는 것입니다:
assert await admin_conn.fetchval(
"select count(*) from runs where org_id = $1", a.org_id
)
== 0
만약 이 카운트가 0이 아니게 된다면, 데이터 유출(data leak)이 발생한 것이고, 고객으로부터 발견하는 대신 CI 환경에서 발견하게 됩니다.
## 제가 재구축을 멈춘 이유
모든 재구축 과정에는 예전 곳에 새로운 버그가 있었습니다. 패키징을 완료한 후에도 실제 로컬 Supabase를 대상으로 하는 최종 엔드투엔드(end-to-end) 실행에서 네 가지 문제를 발견했습니다: `make dev` 하에서 모델 클라이언트까지 도달하지 못한 `.env` 키, 설정을 거부하는 Supabase CLI, API 이미지를 망가뜨린 누락된 `.dockerignore`, 그리고 브라우저가 CORS로 보고한 임베딩 오류였습니다. 이들 중 어느 것도 '흥미로운' 코드 안에 있는 것이 아니었습니다.
공개 고지: 저는 이 전체 체크리스트가 구축되고 테스트된 AI Agent Boilerplate Pro의 제작자입니다. 이는 Next.js 16, FastAPI 및 Supabase를 기반으로 합니다 (위 스니펫들은 여기서 가져온 것입니다). 스타터는 $99이고, CrewAI 크루와 화이트 라벨 클라이언트 포털이 포함된 에이전시 버전은 $299이며, code LAUNCH에서는 10월 24일까지 20% 할인을 제공하고 14일 보장 기간을 제공합니다: [https://theapplab.gumroad.com/l/ai-agent-boilerplate?utm_source=devto&utm_medium=article&utm_campaign=stopped-from-scratch](https://theapplab.gumroad.com/l/ai-agent-boilerplate?utm_source=devto&utm_medium=article&utm_campaign=stopped-from-scratch). 만약 더 작게 시작하고 싶다면, 무료 MIT FastAPI + LangChain 스타터는 여기에서 확인할 수 있습니다: [https://github.com/The-AppLab/ultimate-fastapi-langchain-boilerplate](https://github.com/The-AppLab/ultimate-fastapi-langchain-boilerplate)
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기