Chapter 19. 인증과 데이터베이스 연동
아이디어와 화면까지는 신나게 달려왔는데, 여기서 갑자기 발이 묶이는 순간이 있습니다. 바로 인증과 데이터입니다. 로그인은 붙였는데 세션이 자꾸 풀리고, 사용자 정보는 어디까지 auth.users에 두고 어디부터 우리 테이블에 둘지 애매하고, 스키마를 한 번 바꾸려니 운영 데이터가 무섭습니다.
이 구간을 넘지 못하면 앱은 예쁜 데모로 남습니다. 반대로 이 구간을 잘 넘기면 "장난감 앱"이 아니라 "돈 받고 팔 수 있는 SaaS"의 형태가 잡히기 시작합니다.
이번 장에서는 한국 개발자가 가장 많이 손에 잡을 만한 두 가지 흐름으로 설명하겠습니다. 하나는 Next.js + Supabase 조합으로 빠르게 인증과 데이터 계층을 올리는 방법이고, 다른 하나는 Express + MongoDB 조합으로 유연한 백엔드를 만들되 스키마 드리프트를 통제하는 방법입니다. 그리고 마지막에는 마이그레이션 자동화와 RAG용 벡터 DB 연결까지 한 번에 이어 보겠습니다.

왜 인증과 DB가 첫 번째 진짜 난관인가
UI는 틀려도 눈에 보입니다. 그런데 인증과 데이터는 틀리면 조용히 망가집니다.
로그인 흐름이 꼬이면 사용자는 "왜 자꾸 튕기지?"만 느낍니다. 권한 설계가 엉키면 남의 데이터를 보게 되거나, 반대로 자기 데이터도 못 봅니다. 스키마 변경이 거칠면 어제까지 되던 기능이 오늘 특정 사용자에게만 깨집니다.
이게 무서운 이유는 간단합니다. 인증과 데이터 계층은 한 번 만들고 끝나는 코드가 아니기 때문입니다. 서비스가 커질수록 이 레이어는 계속 수정됩니다. 소셜 로그인 추가, 팀 권한 추가, 구독 상태 추가, 감사 로그 추가, 검색용 인덱스 추가처럼 요구사항이 계속 붙습니다.
그래서 이 장의 핵심은 화려한 해법이 아닙니다. 처음부터 바꿀 수 있게 만드는 것입니다.
먼저 결정해야 할 것: 인증은 외주를 주고, 도메인 데이터는 내가 가진다
초기 SaaS에서 가장 흔한 실수는 인증도 직접 다 만들고 싶어 하는 것입니다. 이메일 인증, 비밀번호 재설정, OAuth, 세션 관리, 보안 정책까지 전부 직접 잡으려 들면 개발자 자존심은 만족할지 몰라도 출시 일정은 울게 됩니다.
그래서 실전에서는 보통 역할을 이렇게 나눕니다.
| 영역 | 추천 책임 주체 | 이유 |
|---|---|---|
| 로그인, 세션, 이메일 인증, OAuth | Supabase Auth 같은 관리형 서비스 | 보안·운영 부담을 크게 줄임 |
| 프로필, 팀, 구독, 프로젝트, 문서, 결제 상태 | 내 앱의 도메인 테이블 | 비즈니스 규칙은 결국 내가 책임져야 함 |
| 접근 제어 | Auth + DB 정책의 조합 | 로그인과 권한은 다른 문제이기 때문 |
Supabase Auth는 JWT 기반 인증과 Postgres의 RLS(Row Level Security, 행 단위 접근 제어)와 자연스럽게 연결됩니다. 쉽게 말해 "누가 로그인했는가"와 "그 사람이 어떤 행에 접근할 수 있는가"를 한 흐름 안에서 다루기 좋습니다.1
이 구조가 좋은 이유는 단순합니다. 로그인 그 자체는 외주를 주고, 서비스의 진짜 경쟁력인 데이터 구조와 권한 모델은 우리 손에 남길 수 있기 때문입니다.
Next.js + Supabase: 가장 빠르게 SaaS의 뼈대를 세우는 조합
한국 개발자 기준으로 보면 Next.js + Supabase는 꽤 현실적인 선택입니다. 프론트와 백엔드 경계가 너무 멀지 않고, App Router 기반의 서버 컴포넌트와 인증 흐름도 잘 맞습니다. Supabase 공식 가이드도 Next.js App Router 기준으로 환경 변수와 서버 측 인증 구성을 안내하고 있습니다.2
기본 출발점은 간단합니다. 프로젝트 URL과 퍼블리셔블 키를 넣고, 브라우저용 클라이언트와 서버용 클라이언트를 나눠 둡니다.2 여기서 중요한 건 "같은 Supabase라도 어디서 부르느냐에 따라 역할이 다르다"는 점입니다.
브라우저에서는 로그인 버튼 클릭, 현재 사용자 표시, 로그아웃 같은 상호작용을 처리합니다. 반면 서버에서는 쿠키 기반 세션을 읽고, 보호된 페이지를 렌더링하고, 민감한 작업을 대신 처리합니다. App Router에서는 이 구분이 특히 중요합니다. 서버에서 세션을 안정적으로 읽어야 첫 렌더부터 보호된 화면을 보여줄 수 있기 때문입니다.3
이 구조를 잡아두면 이후 기능 개발이 훨씬 편해집니다. 대시보드 페이지를 열 때 서버에서 사용자와 팀 정보를 미리 가져오고, 클라이언트는 그 결과를 이어받아 반응형 UI만 담당하면 됩니다. "로그인했나?"를 매번 프론트에서 따로 물어보는 앱보다 훨씬 덜 흔들립니다.
OAuth는 클라이언트보다 서버 경유가 덜 사고 난다
구글 로그인, 카카오 로그인은 대부분의 한국 SaaS에서 거의 기본값입니다. 특히 카카오는 국내 사용자 진입 장벽을 크게 낮춰 줍니다. Supabase는 Google과 Kakao 같은 OAuth 공급자를 지원하고, 실제 한국 사례에서도 Next.js App Router와 함께 많이 쓰입니다.4
여기서 추천하는 방식은 브라우저에서 SDK를 직접 다루는 단순 SPA 흐름보다, Next.js Route Handler를 거치는 서버 중심 OAuth 흐름입니다.35
흐름은 이렇습니다.
사용자가 "구글로 시작하기" 버튼을 누르면, 브라우저는 바로 OAuth 공급자로 가지 않고 우리 서버의 /api/auth/google 같은 라우트로 요청합니다. 이 라우트가 Supabase의 signInWithOAuth를 호출해 인증 URL을 만들고, 사용자는 공급자 로그인 화면으로 이동합니다. 인증이 끝나면 Supabase가 다시 /api/auth/callback으로 코드를 넘기고, 서버는 exchangeCodeForSession으로 세션을 교환한 뒤 원하는 페이지로 리다이렉트합니다.5
이 패턴이 실무에서 좋은 이유는 세 가지입니다.
민감한 세션 교환 과정을 서버에서 처리할 수 있습니다.
리다이렉트 후 이동 경로를 통제하기 쉽습니다.
Server Components와 쿠키 기반 세션 흐름이 자연스럽게 이어집니다.5
한마디로, 로그인은 사용자가 하지만 세션은 서버가 정리해 주는 구조입니다. 실제 서비스에서 이게 훨씬 덜 삐걱거립니다.
한국 서비스라면 카카오 로그인은 처음부터 고려하는 편이 낫다
해외 튜토리얼만 보고 가면 구글과 GitHub만 붙이고 끝내기 쉽습니다. 그런데 한국 사용자 대상 서비스라면 카카오 로그인을 꽤 일찍 넣는 편이 좋습니다. Supabase는 Kakao provider를 지원하고, 실제 설정 과정도 카카오 개발자 포털의 Redirect URI와 Supabase의 Callback URL을 맞추는 방식으로 진행됩니다.4
여기서 자주 헷갈리는 포인트는 "개발 환경 URL, 프리뷰 URL, 운영 URL"이 서로 다를 때입니다. 예를 들어 Vercel 프리뷰 주소가 바뀌는데 Redirect URI는 하나만 넣어 둔 경우, 특정 브랜치에서만 로그인 실패가 납니다. 이럴 때는 인증 설정을 기능 개발 뒤에 미루지 말고, 배포 URL 체계를 먼저 정리하는 편이 낫습니다.
그리고 하나 더. 한국 서비스는 종종 "이메일만으로 가입"보다 "카카오로 빠르게 진입"하는 흐름에서 전환율이 더 좋습니다. 처음부터 모든 인증 방식을 다 넣을 필요는 없지만, 최소한 이메일 기반과 카카오 기반 둘 중 어느 쪽을 메인 진입 경로로 삼을지는 초기에 정해야 합니다. 그 선택이 이후 온보딩 문구, 약관 동의, 프로필 수집 구조까지 바꿉니다.
auth.users와 우리 테이블을 섞지 말고, 연결하라
Supabase를 처음 쓰면 auth.users가 있으니 거기에 모든 걸 넣고 싶어집니다. 하지만 실전에서는 그 테이블을 인증의 원장처럼 보고, 서비스 데이터는 별도 테이블로 분리하는 편이 좋습니다.1
예를 들어 우리 서비스가 팀 협업용 AI 메모 SaaS라면, 최소한 이런 구조가 나옵니다.
profiles: 닉네임, 아바타, 온보딩 상태workspaces: 팀 또는 개인 작업 공간workspace_members: 멤버십과 역할documents: 사용자가 만드는 실제 콘텐츠subscriptions: 플랜, 상태, 갱신일
이때 profiles.id = auth.users.id처럼 1:1 연결을 두면 인증과 도메인 모델이 깔끔하게 분리됩니다. 로그인 공급자가 바뀌어도 우리 비즈니스 데이터는 안정적으로 유지됩니다. 나중에 구글만 쓰다가 카카오를 추가해도, 사용자 도메인 데이터는 같은 사용자 ID 체계 아래에서 확장할 수 있습니다.
Codex에게 이 구조를 맡길 때는 막연하게 "유저 테이블 만들어줘"보다 이렇게 지시하는 편이 훨씬 좋습니다.
Supabase Auth를 사용한다.
auth.users는 직접 수정하지 않는다.profiles,workspaces,workspace_members를 만들고,profiles.id는auth.users.id를 참조한다. 개인 워크스페이스는 회원가입 직후 자동 생성하고, RLS 정책까지 포함해 마이그레이션 SQL을 작성해줘.
이 한 줄 차이로 결과물 품질이 꽤 달라집니다. Codex는 인증 원장과 도메인 테이블을 분리하라는 의도를 이해해야 제대로 된 설계를 내놓습니다.
RLS를 빼먹으면 로그인은 했는데 권한은 없는 앱이 된다
Supabase의 장점은 Postgres 위에서 인증과 권한을 함께 다룰 수 있다는 점입니다. 하지만 이 장점은 동시에 함정이기도 합니다. 테이블을 잘 만들고 로그인까지 붙였는데 RLS 정책을 안 넣으면, 개발 환경에서는 되는 것처럼 보이다가 운영에서 갑자기 다 막히거나, 반대로 너무 열려 버릴 수 있습니다.1
예를 들어 documents 테이블이 있다고 해봅시다. 로그인한 사용자라면 누구나 모든 문서를 읽을 수 있어서는 안 됩니다. 최소한 "내가 속한 워크스페이스의 문서만 읽을 수 있다" 같은 규칙이 있어야 합니다.
이때 좋은 접근은 UI 기준이 아니라 데이터 기준으로 정책을 적는 것입니다. 화면에서 버튼을 숨기는 건 보안이 아닙니다. 진짜 보안은 DB가 직접 "이 행은 이 사용자에게 보여도 되는가?"를 판단하게 하는 것입니다.
실전에서는 보통 이런 순서가 안전합니다.
첫째, 서비스 롤과 사용자 롤을 구분합니다. 둘째, 모든 테이블에서 기본 거부를 전제로 생각합니다. 셋째, 읽기 정책과 쓰기 정책을 따로 적습니다. 넷째, 팀 멤버십 테이블을 중심으로 접근 가능 범위를 계산합니다.
이 과정을 Codex에게 시킬 때도 좋습니다. 다만 반드시 요구사항을 구체적으로 줘야 합니다.
사용자는 자신이 속한 워크스페이스의 문서만 SELECT 가능하다. 문서 생성은 멤버만 가능하다. 수정과 삭제는
owner,admin, 문서 작성자만 가능하다. SQL migration과 테스트용 seed SQL을 같이 만들어줘.
이렇게 주면 Codex는 단순 CRUD가 아니라 실제 운영 권한 모델을 반영한 결과를 만들 가능성이 높아집니다.
Supabase MCP는 "개념 설명"보다 "작업 단위"로 쓰는 편이 낫다
MCP 자체는 이미 앞 장에서 다뤘습니다. 이번 장에서는 길게 설명하지 않겠습니다. 중요한 건 Supabase MCP를 붙였을 때 무엇이 쉬워지느냐입니다.
가장 체감이 큰 건 세 가지입니다. 현재 스키마를 읽어 와서 Codex가 구조를 더 정확하게 이해하게 하는 것, SQL 마이그레이션 초안을 만든 뒤 실제 상태와 비교하게 하는 것, 그리고 운영 전 점검용 질의를 안전하게 준비하는 것입니다.
예를 들어 Next.js + Supabase 프로젝트에서 로그인 이후 개인 워크스페이스를 자동 생성하는 기능을 만들고 싶다면, Codex에게 대충 "회원가입 후 워크스페이스도 만들자"라고 시키는 것보다 이렇게 맡기는 편이 낫습니다.
Supabase 프로젝트의 현재 테이블과 함수 정의를 읽고, 신규 사용자 가입 시
profiles와 개인workspace가 함께 생성되도록 트리거 또는 서버 액션 기반 설계를 제안해줘. 지금 스키마와 충돌하는 부분을 먼저 보고한 뒤 SQL migration을 작성해줘.
이 지시의 장점은 "코드 생성"보다 "현 상태 파악"이 먼저라는 점입니다. 실무에서 사고는 대부분 새 코드가 아니라 기존 스키마를 잘못 이해해서 납니다.
마이그레이션은 기능 개발의 부록이 아니라 본편이다
서비스가 조금만 살아나면 스키마 변경은 피할 수 없습니다. users.plan 하나 추가하는 수준에서 끝나지 않습니다. price를 amount로 바꾸고 싶을 수도 있고, 단일 팀 구조를 멀티 워크스페이스 구조로 바꿔야 할 수도 있습니다.
이때 중요한 건 "DB 변경 파일 하나 만들기"가 아닙니다. 읽기 호환성을 유지한 채 천천히 옮기는 전략입니다. 특히 MongoDB든 Postgres든 운영에서는 한 번에 뒤집는 마이그레이션이 생각보다 위험합니다.67
초기 서비스에서는 다음 원칙만 지켜도 사고가 많이 줄어듭니다.
새 구조를 먼저 추가하고, 구 구조는 일정 기간 같이 읽습니다.
코드가 새 구조를 우선 사용하게 만든 뒤, 데이터를 배치로 보정합니다.
충분히 안정화된 후에야 구 필드를 제거합니다.
이 흐름은 생각보다 지루합니다. 하지만 운영은 원래 약간 지루해야 안전합니다.
Express + MongoDB: 유연하지만, 방치하면 스키마가 자라난다
이제 두 번째 축으로 넘어가 보겠습니다. Express + MongoDB는 빠르게 API를 만들고 구조를 유연하게 바꾸기 좋습니다. Mongoose를 붙이면 스키마와 검증도 비교적 쉽게 관리할 수 있습니다.89
간단한 사용자 모델과 CRUD만 놓고 보면 이 조합은 아주 경쾌합니다. Express로 라우트를 만들고, Mongoose로 모델을 정의하고, Atlas나 로컬 MongoDB에 연결하면 바로 API가 돌아갑니다.89
문제는 성공하고 나서 생깁니다.
처음에는 문서 구조가 자유로운 게 장점처럼 느껴집니다. 그런데 운영이 길어질수록 같은 컬렉션 안에 서로 다른 형태의 문서가 쌓이기 시작합니다. 예전 사용자는 email, 최근 사용자는 emails, 어떤 문서는 name, 어떤 문서는 profile.firstName 같은 식입니다. MongoDB는 이를 허용하지만, 애플리케이션은 그 순간부터 방어 코드를 끝없이 늘리게 됩니다.7
즉, MongoDB에는 스키마가 없는 게 아니라 스키마의 책임이 애플리케이션에 있는 것입니다.6
Express + MongoDB에서 인증은 대개 두 갈래다
이 조합에서 인증은 보통 두 방식 중 하나를 택합니다.
하나는 JWT 기반 자체 인증입니다. 이메일/비밀번호를 받고, 해시해서 저장하고, 로그인 시 토큰을 발급하는 전통적인 방식입니다. 커스터마이징은 자유롭지만 보안과 운영 책임이 모두 우리에게 옵니다.
다른 하나는 "인증은 외부 서비스, 도메인 데이터는 MongoDB" 방식입니다. 예를 들어 로그인은 Supabase Auth나 Auth.js에 맡기고, 애플리케이션 데이터만 Express + MongoDB가 처리합니다. 초기 SaaS에서는 이 방식이 꽤 실용적입니다. 인증 레이어는 이미 검증된 도구에 맡기고, Node API는 팀 로직과 데이터 처리에 집중할 수 있기 때문입니다.
실전에서 저는 두 번째 방식을 더 자주 추천합니다. 로그인은 이미 잘하는 서비스에게 맡기고, Express는 다음 역할에 집중하게 만드는 겁니다.
비즈니스 규칙이 복잡한 API
외부 시스템 연동
배치 작업과 큐 처리
MongoDB에 잘 맞는 문서 중심 데이터 모델
한마디로, 굳이 두 번 고생하지 말자는 뜻입니다.
MongoDB 스키마 변경은 schemaVersion 없이는 금방 흐려진다
MongoDB 운영에서 정말 유용한 습관 하나를 꼽으라면 schemaVersion 필드를 드는 것입니다. 문서마다 현재 구조의 버전을 명시해 두면, 코드가 어떤 형식을 기대해야 하는지 분명해지고 점진적 마이그레이션도 쉬워집니다.7
예를 들어 원래 사용자 문서가 이렇게 생겼다고 해봅시다.
{
"_id": "u1",
"name": "Kim Dev",
"email": "[email protected]"
}서비스가 커지면서 이름을 구조화하고 복수 이메일을 허용하고 싶어졌습니다. 그러면 다음 버전은 이렇게 갈 수 있습니다.
{
"_id": "u1",
"schemaVersion": 2,
"profile": {
"firstName": "Dev",
"lastName": "Kim"
},
"emails": ["[email protected]"]
}이때 중요한 건 모든 문서를 한 번에 갈아엎지 않는 것입니다. 새 코드는 v1과 v2를 모두 읽을 수 있게 만들고, 백그라운드 배치가 천천히 v1을 v2로 올립니다. 그 뒤에야 구 필드를 정리합니다.67
이 방식이 번거로워 보여도, 실제로는 장애 복구 시간을 크게 줄여 줍니다. 문제가 생기면 "어떤 버전 문서에서 터졌는가"를 바로 좁힐 수 있기 때문입니다.
migrate-mongo로 MongoDB 마이그레이션을 코드처럼 다뤄라
MongoDB는 자유롭지만, 운영에서는 자유보다 기록이 더 중요합니다. 그래서 마이그레이션 도구를 붙여 두는 게 좋습니다. migrate-mongo는 Node.js 프로젝트에서 MongoDB 변경을 파일 단위로 관리하기 쉬운 도구입니다. 설정 파일과 migrations 디렉터리를 만들고, up과 down 함수를 통해 적용과 롤백을 나눠 관리할 수 있습니다.10
예를 들어 users 컬렉션에 schemaVersion: 2를 백필하는 마이그레이션을 Codex에게 시킨다고 해봅시다. 이때는 이렇게 요구하는 편이 좋습니다.
Express + Mongoose 프로젝트다.
migrate-mongo기준으로users컬렉션의 기존name,profile,emails,schemaVersion구조로 옮기는 migration 파일을 작성해줘.up은 점진 변환,down은 가능 범위 내 롤백을 지원해야 한다. 배치 처리와 인덱스 영향도 설명해줘.
이 프롬프트가 좋은 이유는 단순 필드 추가가 아니라 운영 고려사항까지 포함하고 있기 때문입니다. up만 있는 스크립트는 쓰기 쉽지만, 새벽에 되돌릴 수 없으면 팀 채팅방이 갑자기 아주 시끄러워집니다.
Codex로 마이그레이션 자동화할 때는 "생성"보다 "검토 루프"를 설계해야 한다
AI에게 마이그레이션을 맡길 때 흔한 오해가 있습니다. "SQL이나 스크립트를 빨리 써주니 끝"이라고 생각하는 겁니다. 아닙니다. 진짜 중요한 건 생성 이후입니다.
좋은 루프는 대체로 이렇습니다.
첫째, 현재 스키마를 읽습니다. 둘째, 변경 목표를 문장으로 적습니다. 셋째, 마이그레이션 파일을 생성합니다. 넷째, 스테이징 데이터에서 dry-run 또는 샘플 검증을 돌립니다. 다섯째, 롤백 경로를 확인합니다. 여섯째, 배포 체크리스트를 문서화합니다.
이 과정을 한 번 Skill로 만들어 두면 계속 재사용할 수 있습니다. 예를 들어 migration-safety-review 같은 Skill은 다음 항목을 강제하게 만들면 좋습니다.
breaking change 여부
백필 필요 여부
읽기 호환성 유지 여부
롤백 가능 여부
인덱스와 락 영향
운영 배포 순서
이런 Skill이 있으면 Codex는 단순 작성기가 아니라 꽤 쓸 만한 심사관으로 바뀝니다.
Next.js + Supabase 실전 예제: 회원가입부터 워크스페이스 생성까지
이제 실제 SaaS 시나리오를 그려 봅시다. 서비스는 "팀용 회의 요약 SaaS"라고 하겠습니다. 사용자는 이메일 또는 카카오로 가입하고, 가입 직후 개인 워크스페이스를 하나 받습니다.
흐름은 다음처럼 잡으면 안정적입니다.
사용자가 회원가입을 마치면 Supabase Auth에 사용자가 생성됩니다. 그다음 우리 서버 액션 또는 DB 함수/트리거가 profiles 레코드를 만들고, 이어서 개인 워크스페이스와 멤버십을 생성합니다. 이후 대시보드 진입 시 서버 컴포넌트는 세션을 읽고, 현재 사용자의 워크스페이스 목록과 최근 문서를 한 번에 가져옵니다.
여기서 중요한 건 "회원가입 성공"과 "도메인 초기화 성공"을 분리해서 다루는 것입니다. 로그인은 되었지만 워크스페이스 생성이 실패할 수 있습니다. 이 경우 사용자를 다시 온보딩 복구 플로우로 보내야 합니다. 실제 서비스에서 이런 보정 루프가 없으면, 특정 사용자는 영원히 빈 계정 상태로 남습니다.
Codex에게는 이렇게 맡길 수 있습니다.
Next.js App Router + Supabase 프로젝트다. 이메일/카카오 로그인 후 최초 로그인인 경우
profiles,workspaces,workspace_members를 생성하는 서버 액션 또는 RPC 설계를 제안하고 구현해줘. 실패 시 재시도 가능한 온보딩 복구 페이지도 포함해줘.
이런 식으로 주면 Codex가 "가입만 성공하면 끝"이 아니라 "실패한 초기화도 복구해야 한다"는 현실적인 SaaS 감각을 갖고 작업하게 됩니다.
Express + MongoDB 실전 예제: 관리자 대시보드용 사용자 API
이번에는 Express + MongoDB 쪽 예제를 보겠습니다. 예를 들어 한국형 커머스 운영 툴의 관리자 API를 만든다고 합시다. 여기서는 인증은 외부 서비스로 받고, Express는 관리자 화면에서 필요한 사용자 검색과 상태 변경 API를 맡습니다.
초기 모델은 단순할 수 있습니다. users, organizations, audit_logs 정도만 있어도 됩니다. 그런데 운영하다 보면 바로 요구사항이 붙습니다. 휴면 상태, 마케팅 수신 동의 이력, 최근 로그인 디바이스, 관리자 메모, 내부 태그 같은 것들입니다.
이때 MongoDB의 장점은 문서 중심으로 빠르게 붙여 갈 수 있다는 점입니다. 하지만 같은 이유로 구조가 금방 흐려질 수 있으니, 다음 두 가지는 초기에 꼭 잡아두는 편이 좋습니다.
하나는 schemaVersion입니다. 다른 하나는 공통 필드 규약입니다. 예를 들어 createdAt, updatedAt, status, schemaVersion 정도는 거의 모든 핵심 컬렉션에 넣어 둡니다.
그리고 Codex에게 라우트 생성을 맡길 때도 구조를 강제합니다.
Express + Mongoose 기반이다.
usersAPI에 목록 조회, 상세 조회, 상태 변경, 관리자 메모 추가 기능을 만든다. 모든 변경은audit_logs에 남겨야 하고,schemaVersion필드를 기본값 1로 포함한다. Zod 또는 Joi 기반 입력 검증과 테스트까지 작성해줘.
이렇게 해야 나중에 "API는 만들었는데 누가 언제 무엇을 바꿨는지 모르는" 사태를 줄일 수 있습니다.
RAG와 벡터 DB는 인증·DB 설계의 연장선에 있다
많은 팀이 RAG를 완전히 별도 주제로 생각합니다. 하지만 실제로는 아닙니다. 사용자가 업로드한 문서를 임베딩하고, 검색 범위를 사용자 또는 워크스페이스 단위로 제한하고, 답변에 출처를 붙이는 순간 RAG도 결국 인증과 데이터 모델의 일부가 됩니다.
Pinecone 공식 자료도 RAG를 단순히 벡터 DB 하나 꽂는 문제로 보기보다, 더 나은 입력과 검색 품질을 만드는 검색 파이프라인의 문제로 설명합니다. 하이브리드 검색, 리랭킹, 멀티 쿼리 같은 기법이 결국 답변 품질을 좌우한다는 뜻입니다.11
실전 패턴은 대체로 이렇습니다.
원본 문서는 Postgres 또는 MongoDB에 메타데이터와 함께 저장합니다. 본문은 청크로 쪼개 임베딩을 만들고 Pinecone 같은 벡터 DB에 넣습니다. 질의가 들어오면 먼저 사용자의 워크스페이스 범위를 기준으로 필터링하고, 그 안에서 유사 청크를 가져옵니다. 그런 다음 LLM에게 "이 범위 안에서만 답해라"라고 시킵니다.
이때 중요한 건 벡터 검색 자체보다 권한 필터링입니다. 팀 A의 문서를 팀 B가 검색하게 만들면, 모델이 아무리 똑똑해도 바로 사고입니다.
그래서 Codex에게 RAG를 시킬 때도 프롬프트가 달라야 합니다.
Supabase 기반 문서 SaaS다. 업로드된 문서를 청크 분할해 Pinecone에 저장하고, 쿼리 시 현재 사용자의
workspace_id메타데이터로 검색 범위를 제한하는 RAG 파이프라인을 설계해줘. 임베딩 적재 배치와 삭제 동기화 전략도 포함해줘.
이 지시에는 "벡터 검색"뿐 아니라 "누구 문서를 누구에게 보여줄 것인가"가 같이 들어 있습니다. 바로 그 점이 실전입니다.
스키마 변경을 두려워하지 말고, 두렵게 바꾸지 말자
결국 이 장의 핵심은 기술 선택보다 태도에 가깝습니다. 인증은 빠르게 붙일 수 있습니다. DB도 쉽게 연결할 수 있습니다. 하지만 출시 가능한 SaaS와 취미 프로젝트의 차이는, 문제가 생겼을 때 안전하게 바꿀 수 있느냐에서 갈립니다.
Next.js + Supabase에서는 인증 원장과 도메인 테이블을 분리하고, 서버 중심 OAuth와 RLS를 일찍 잡아야 합니다. Express + MongoDB에서는 유연함을 즐기되 schemaVersion과 마이그레이션 규율로 드리프트를 막아야 합니다. 그리고 둘 다에서 Codex는 "코드를 대신 써주는 도구"보다 "현재 상태를 읽고, 안전한 변경 계획을 제안하고, 반복 가능한 마이그레이션 루프를 만드는 에이전트"로 써야 값이 나옵니다.
인증과 데이터 계층을 넘는 순간, 서비스는 비로소 살아 움직이기 시작합니다. 사용자가 들어오고, 데이터가 쌓이고, 구조가 바뀌고, 과거와 미래를 함께 품어야 하니까요.
다음 장에서는 이렇게 쌓인 기능을 실제로 믿고 배포할 수 있게 만드는 마지막 관문, 테스트와 배포를 다뤄보겠습니다.
참고
1Supabase Auth architecture 번역 정리
2Use Supabase Auth with Next.js
3Authentication in Next.js: Complete Guide with Auth.js & Supabase
4Next.js 14, Supabase 인증을 활용한 구글, 카카오 OAuth 구현하기
5Next.js에서 Supabase OAuth 인증하기, 그런데 이제 Google과 Kakao를 곁들인
611편. MongoDB Schema Migration – 운영 환경에서의 전략
7Schema Evolution and Preventing Drift
8mongoDB를 express와 연결하기 (mongoose방법도 추가)
9MongoDB와 Express를 연동하여 RESTful API 확장하기
10Step-by-Step Guide to MongoDB Migrations Using Migrate-Mongo
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.