// docs / security guides / pre-launch SaaS
SaaS 출시 전 보안 체크리스트: 35+가지 항목
Cursor, Claude Code, Lovable 또는 Bolt으로 구축된 SaaS 제품을 출시한 지 며칠이 지나지 않았습니다. 이 체크리스트는 AI 도구가 지속적으로 놓치고 있는 보안 표면과 빠르게 배송하는 창립자가 고객의 돈을 받기 전에 해결해야 하는 보안 표면을 다루는 go/no-go 감사입니다. 8개 섹션, 35개 이상의 항목, 각 항목을 30~90분 안에 해결할 수 있습니다. 인쇄하고, 줄을 그어 자신 있게 배포하세요.
아래의 각 항목은 필수 항목입니다. 녹색은 배송 및 검증되었음을 의미합니다. 빨간색은 해결되지 않았으며 실행이 차단되었음을 의미합니다. 코드 조각과 실제 실패 패턴이 포함된 각 범주에 대한 더 긴 연습을 보려면 How to secure an app built with AI coding tools 및 The vibe coding security checklist을 참조하세요.
고객 데이터 격리
다중 테넌트 SaaS에서 첫 번째 보안 경계는 데이터 격리입니다. 모든 고객의 데이터는 다른 모든 고객이 접근할 수 없어야 하며 애플리케이션 계층이 아닌 데이터베이스 계층에서 시행되어야 합니다.
ALTER TABLE public.table_name ENABLE ROW LEVEL SECURITY; ALTER TABLE public.table_name FORCE ROW LEVEL SECURITY;이 포함된 모든 Supabase 테이블에서 행 수준 보안(RLS)을 활성화합니다. FORCE은 테이블 소유자가 이를 우회하는 것을 방지합니다.- 각 RLS 정책에 대해 인증된 사용자 또는 조직에 대한 조건자 범위를 확인합니다. 예:
CREATE POLICY "users_see_own" ON public.items FOR SELECT USING (auth.uid() = user_id);. 두 번째 사용자 계정으로 테스트하여 데이터가 격리된 상태로 유지되는지 확인하세요. - Firebase / Firestore를 사용하는 경우 규칙은 테넌트 모델과 일치해야 합니다.
allow read, write: if true;또는 시간 제한 테스트 규칙을 사용하지 마세요.allow read, write: if request.auth.uid == resource.data.owner_uid;또는 이에 상응하는 조직 범위 일치를 사용합니다. - 파일 액세스에는 서명된 URL 또는 단기 토큰을 사용하고 공개 버킷은 사용하지 마십시오. Supabase 스토리지:
objects테이블에ENABLE ROW LEVEL SECURITY을 설정하고 파일 액세스 범위를 인증된 사용자로 지정하는 정책을 작성합니다. 다른 사용자로 다운로드를 테스트합니다. - API 레이어에서 모든 요청에는
auth.uid()또는 조직 ID 컨텍스트가 포함되어야 합니다. 모든 데이터베이스 쿼리는 해당 컨텍스트를 기준으로 필터링해야 합니다. 예: 아니요SELECT * FROM items WHERE id = $1; 항상SELECT * FROM items WHERE id = $1 AND user_id = auth.uid().
청구 및 결제
Stripe 통합은 고객의 신뢰와 재정적 안전이 만나는 곳입니다. 여기서 잘못된 구성은 결제 도난, 환불 루프 또는 수익 손실을 의미합니다.
- 프로덕션에서는 live Stripe keys을 사용합니다. 준비 시 별도의 테스트 모드 키를 사용하여 테스트하세요. 최종 라이브 모드 스캔 없이 테스트에서 라이브로 전환하지 마십시오.
- 모든 인바운드 이벤트에서 웹훅 서명을 확인하세요:
const event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret);. 서명이 실패하면 던집니다. 웹훅 비밀을 환경 변수에만 저장하고 코드에는 저장하지 마세요. event.id으로 입력된 데이터베이스 테이블을 사용하여 웹후크 처리기에서 멱등성을 구현합니다. 동일한 웹훅이 두 번 도착하면(그럴 것입니다) 두 번째 실행은 작동하지 않습니다. 상태 변경과 동일한 트랜잭션에 멱등성 행을 작성합니다.customer.subscription.updated및customer.subscription.deleted에서는 즉시 액세스 권한을 취소합니다. 크론을 기다리지 마십시오. Stripe 대시보드에서 구독을 취소하고 5초 이내에 사용자가 잠기는지 확인하여 테스트하세요.- Stripe 고객 ID 및 구독 ID만 데이터베이스에 저장하고 전체 카드나 API 키는 저장하지 마세요. 모든 인증 경계(페이지 로드, API 호출, cron 확인)에서 Stripe에서 실시간 구독 상태를 검색합니다. 1분 이상 구독 상태를 캐시하지 마세요.
인증 및 세션
인증은 SaaS의 2차 공격 대상입니다. 사용자 계정은 데이터 및 결제 방법에 대한 벡터입니다.
getSession()이 아닌 모든 보호된 경로에supabase.auth.getUser()을 사용하세요.getSession()은 확인되지 않은 쿠키를 읽습니다.getUser()은 JWT 서버 측의 유효성을 검사합니다. Next.js:const { data: { user } } = await supabase.auth.getUser();보호된 콘텐츠를 제공하기 전입니다.- 인증 쿠키에
SameSite=Lax을 설정합니다(Supabase 인증은 기본적으로 이 작업을 수행합니다). DevTools → 애플리케이션 → 쿠키에서 확인하세요.SameSite=None이 표시되면 세션 구성에sameSite: 'Lax'을 추가하세요. - 자신의 관리자 계정에서 MFA을 활성화합니다. 사용자 대상 MFA의 경우 출시 전에 엔드투엔드를 테스트하세요. 가입하고, TOTP 장치를 등록하고, 로그아웃하고, TOTP 토큰으로 다시 로그인하고, 작동하는지 확인하세요.
- 매직링크 토큰은 15분 이내에 만료되어야 합니다. 비밀번호 재설정 토큰은 1시간 이내에 만료되어야 합니다. 세션 토큰(JWTs)은 더 오래(24시간~7일) 지속될 수 있지만 사용할 때마다 유효성을 검사해야 합니다. 인증 공급자의 기본값을 확인하세요.
- 로그아웃 완전성 테스트: 사용자가 로그아웃을 클릭하면 브라우저가 인증 세션을 삭제하고 서버가 모든 토큰을 취소하며 사용자는 보호된 페이지에 액세스할 수 없습니다. Supabase:
await supabase.auth.signOut()을 호출하고 다음 요청에서 JWT이 더 이상 유효하지 않은지 확인합니다.
PII 및 규정 준수
이메일, 이름, 결제 정보 또는 PII을 수집하는 경우 데이터 최소화, 보안 저장, 요청 시 삭제 및 DPA 준비와 같은 법적 의무가 있습니다.
- 개인 정보 보호 정책을 작성하고 게시합니다(인디 SaaS의 경우에도 선택 사항 아님). 귀하가 수집하는 데이터, 이유, 보관 기간 및 사용자 권리(액세스, 수정, 삭제)를 명시하십시오. Termly 또는 이와 유사한 템플릿을 사용하되 사용자 정의하세요.
- 데이터베이스에서 PII을 제거하는 삭제 계정 API 엔드포인트를 구현합니다. 테스트: 계정 생성, 데이터 추가, 계정 삭제, 데이터가 사라졌는지 확인(직접 데이터베이스 검사 사용).
- GDPR / CCPA 규정 준수를 위해 정보주체의 요청(접근/정정/삭제)에 30일 이내에 응답합니다. 프로세스를 문서화하세요. 앱이 EU- 기반이거나 EU 사용자에게 서비스를 제공하는 경우 Stripe, Supabase이 포함된 데이터 Processing 부록(DPA) 및 모든 프로세서가 필요합니다.
- 저장된 민감한 필드를 암호화합니다(비밀번호는 인증 공급자에 의해 해시되지만 신용카드 토큰화, API 키, 비밀은
pgcrypto또는 외부 저장소를 사용해야 함). 일반 텍스트 신용 카드 번호를 저장하지 마십시오(대신 Stripe 토큰화 사용).
운영 준비
보안은 지속적입니다. 사고 대응, 모니터링, 런북은 첫날부터 시작됩니다.
- 상태 페이지(Statuspage.io, Uptime Robot 또는 간단한 index.html)를 설정합니다. 고객은 서비스 중단 여부를 알아야 합니다. 사건이 발생할 때마다 업데이트하세요.
- 통화 중 순환을 문서화하고 테스트하십시오. 새벽 2시에 깨어나는 사람은 누구입니까? 배포 키는 누구에게 있습니까? 누가 손상된 토큰을 취소할 수 있나요? 이를 문서화하고 발사 전에 소방 훈련을 실시하세요.
- 보안 사고 대응 런북을 작성하십시오. 고객이 침해를 보고한 경우, 키를 분실한 경우, 서비스가 다운된 경우 수행할 작업을 작성하십시오. 팀에 배포하세요. 하나의 시나리오(e.g., 키 유출 시뮬레이션)를 테스트하여 계획이 작동하는지 확인합니다.
- 백업 및 복원 절차는 이론적인 것이 아니라 테스트되어야 합니다. 백업에서 복원할 수 있나요? 시간을 정하세요. Supabase: 자동 백업을 활성화합니다(무료로 7일 보관, 유료로 30일 보관). 분기별로 별도의 프로젝트로 복원을 테스트합니다.
- Stripe 대시보드 로그인, Supabase 관리자 API 호출, 데이터베이스 스키마 변경, 결제 조정 등 권한 있는 작업에 대한 감사 로깅을 활성화합니다. 도구: CloudTrail(AWS), Supabase 감사 로그, PostgreSQL
pgaudit확장.
외부 공격 표면
API 경계는 지속적인 공격자 검사를 받고 있습니다. 악의적인 트래픽이 발생하기 전에 차단하세요.
- 모든 공용 엔드포인트의 속도를 제한합니다. 예: 가입 시 IP당 분당 100개 요청, 비밀번호 재설정 시 분당 10개 요청. Vercel KV, Redis 등을 사용하세요. 429(요청이 너무 많음)로 인해 실패합니다.
- 봇을 물리치려면 가입 및 비밀번호 재설정 엔드포인트에 CAPTCHA(hCaptcha 또는 reCAPTCHA)를 추가하세요. 요청을 수락하기 전에 서버 측 토큰을 확인하세요.
- 가능한 경우 WAF(웹 응용 프로그램 방화벽)을 사용하세요. Cloudflare, Vercel 웹 응용 프로그램 방화벽 또는 AWS WAF. 알려진 악성 IP 및 패턴을 자동으로 차단합니다.
- 열려 있는 API 엔드포인트를 검색합니다. 매월 프로덕션 도메인에 대해 수동 FixVibe 검사를 실행하세요. 노출된 디버그 경로, GraphQL 검사, API 키 유출 또는 구성 노출에 대한 결과를 검토합니다.
- 자격 증명(API 키, OAuth 토큰, 데이터베이스 비밀번호)을 분기별로 교체합니다. 교체 절차를 문서화하고 가능한 경우 자동화합니다.
관찰 가능성 및 로깅
문제가 발생하면 로그가 포렌식 기록이 됩니다. 첫날부터 설정하세요.
- 로그 중앙 집중화: Supabase 로그, Vercel 로그, 애플리케이션 로그 및 인증 로그를 단일 대시보드(Datadog, LogRocket 또는 자체 호스팅 ELK)에 저장합니다. 검색 가능하며 최소 90일 동안 보관됩니다.
- 보안 이벤트에 대한 경고: 반복되는 로그인 실패(계정 탈취 가능성), 비정상적인 API 사용(스크래핑 가능성), 오류 급증(공격 가능성 또는 합법적인 사고). 임계값 및 Slack 통합을 설정합니다.
- 사용자 역할 변경, 새 관리자 계정 생성, 결제 방법 추가, API 키의 범위 변경 등 모든 권한 있는 작업에 대한 감사 로그를 내보냅니다. 불변 보존을 통해 이를 애플리케이션 로그와 별도로 저장합니다.
최종 검증
발표하기 전에 전체 FixVibe 검사를 실행하고 보안 감시를 통해 결과를 검토하세요.
- 프로덕션 도메인에 대해 FixVibe Pro 활성 스캔을 실행합니다. 활성 테스트를 위해 도메인을 구성합니다(DNS TXT 또는 HTTP 파일 확인). 스캔을 승인하고 모든 결과(특히 중요하고 심각도가 높은 결과)를 검토합니다. 각 항목을 명시적으로 수정하거나 수락합니다.
- 예약된 재검색 활성화: Pro 계획 → 3시간, 6시간, 12시간 또는 매일. Unlimited 계획 → 6시간, 12시간, 매일, 2일마다 또는 매주. 확인된 도메인에서 active IDOR walking, SQL injection 및 reflected XSS 검사와 페어링합니다.
- 웹후크 구성: FixVibe을 Slack에 연결하거나 이메일을 보내면 중요한 결과가 실시간으로 알림을 트리거합니다. 설정하려면 /docs/webhooks을 참조하세요.
- /docs/security-guides/ai-generated-code-security-scanner의 문제(번들 내 비밀, RLS/rules, 인증 경계, CSP, 미들웨어 배치)에 초점을 맞춰 최종 수동 코드 검토를 수행합니다. vibe coding security checklist을 리뷰 템플릿으로 사용합니다.
출시일
체크리스트를 지웠습니다. 자신 있게 배포하세요. 출시 후 적극적으로 모니터링하세요. 첫 주 동안 매일 FixVibe 결과를 확인하고, 1시간 이내에 알림에 응답하고, 검색 일정을 계속 실행하세요. 코드 조각이 포함된 단계별 강화 가이드는 How to secure an app built with AI coding tools을 참조하세요.
