바이브코딩으로 프로토타입을 만드는 것과 실제 사용자가 쓰는 서비스를 운영하는 것은 완전히 다른 문제다. 많은 개발자들이 보안과 운영환경 결정을 뒤로 미루고 코드부터 짠다. 그 대가는 나중에 전체를 뜯어고치는 것으로 돌아온다.
보안 — 설계에 늦게 반영할수록 기술부채가 된다
보안을 “나중에 붙이면 된다”고 생각하는 순간, 그것은 이미 기술부채가 된다. 단순히 코드 몇 줄을 추가하는 문제가 아니라 인증 아키텍처, DB 스키마,API 전체에 영향을 미치기 때문이다.
패스워드 – 단방향 암호화는 협상 대상이 아니다
패스워드를 평문이나 양방향 암호화로 저장하는 서비스는 아직도 존재한다. 이는 해킹 피해 발생 시 사용자의 다른 서비스 계정까지 연쇄 피해가 발생하는 원인이 된다. bcrypt, Argon2 같은 단방향 해시를 사용하면 DB가 통째로 털려도 원본 패스워드는 복원할 수 없다
흔한 실수: SHA-256 같은 일반 해시를 패스워드 암호화에 사용하는 경우, 일반 해시는 레인보우 테이블 공격에 취약하다. 패스워드에는 반드시 salt가 포함된 패스워드 전용 해시 알고리즘(bcrypt, Argon2)을 사용해야 한다
인증 체계 – JWT와 세션의 실질적 차이
OAuth 소셜 로그인 구현 여부와 별개로, 로그인 상태를 어떻게 유지할지도 초기에 결정해야 한다
| 방식 | 장점 | 실전 리스크 |
| 세션(서버 저장) | 강제 로그아웃 즉시 가능 | 서버 수평 확장 시 세션 공유 문제 (Redis 필요) |
| JWT(토큰 기반) | 서버 무상태(stateless), 확장 용이 | 토큰 탈취 시 만료 전까지 강제 무효화 어려움, Refresh Token 관리 필요 |
바이브코딩 초기 서비스에서 JWT를 선택하는 경우가 많은데, “stateless라서 좋다”는 이유만으로 선택하는 것은 위험하다. 관리자 계정 탈취 시 즉각 세션을 끊을 수 없다는 것이 실전에서 생각보다 큰 문제가 된다. 관리자 영역은 세션 기반, 일반 사용자는 JWT로 이원화하거나, JWT쓰더라도 Refresh Token 블랙리스트 설계에 포함시켜야 한다
HTTPS와 인증서 – 선택이 아닌 기본값
2024년 이후 브라우저는 HTTP 사이트에 경고를 표시한다. 사용자 신뢰 문제 이전에, HTTP 환경에서는 중간자 공격(MITM)으로 토큰과 쿠기가 그대로 노출된다. AWS ALB 혹은 CloudFront에 ACM(AWS Certificate Manager) 인증서를 붙이는 방식이 가장 간단하다. Let’s Encrypt는 홈서버 환경에서의 대안이다
환경변수와 시크릿 관리
API 키, DB 접속 정보, JWT 시크릿을 코드에 하드코딩하거나 GitHub에 올리는 사고는 생각보다 자주 발생한다. AWS를 사용한다면 Secrets Manager 또는 Parameter Store를 활용하고, 로컬 개발 환경에서는 .env파일을 반드시 .gitignore에 포함시켜야 한다
추가로 고려해야 할 것들
강의에서 다루지 않았지만 실전에서 반드시 마주치는 보안 이슈들이 있다
- SQL Injection / XSS: ROM을 쓰더라도 Raw Query 사용 시 주의. 사용자 입력값을 항상 검증 후 사용
- Rate Limiting: 로그인 시도 횟수 제한이 없으면 브루트포스 공격에 무방비. 단순 기능이지만 반드시 초기에 포함해야 한다
- CORS 설정: “*” 허용은 개발 편의를 위한 설정이지 운영 설정이 아니다. 허용 도메인을 명시적으로 지정해야 한다
서비스 운영 환경 — 선택 기준과 냉정한 평가
| 옵션A | 옵션B | 옵션C – 권장 |
| 비용 최소 | 출시 속도 최고 | 운영 유연성 최고 |
| 추가 고정비 없음 | 인프라 관리 불필요 | 트래픽 단가 합리적 |
| Cloudflare로 IP 은닉 | 인증 · DB · 스토리지 원스톱 | WAF · CDN · ALB 통합 |
| 물리 장비에 운영 종속 | Serverless 자동 확장 | 인프라 직접 제어 |
| WAF 직접 구성 필요 | 대역폭 비용 상승 구조 | 초기 셋업 진입장벽 |
| 가용성 확보 어려움 | 커스텀 인프라 제한 | 고정 운영비 발생 |
Vercel+Supabase에 대해
바이브 코딩 시 프로덕션 출시까지 상대적으로 “쉽다”는 점이 최대 장점으로 뽑히지만, Supabase는 PostgreSQL 기반의 오픈소스 프로젝트지만, 관리형 서비스로 사용하는 순간 벤더 락인(vendor lock-in)이 발생한다. Row Level Security(RLS)나 Supabase 전용 인증 방식에 깊이 의존한 구조를 만들면, 나중에 AWS나 자체 DB로 이전할 때 생각보다 큰 공수가 든다. 빠르게 검증하고 버리거나, 장기적으로 이전 계획 없이 간다면 최선의 선택이다. 하지만 처음부터 “언젠가 AWS로 이전”을 계획하고 있다면 처음부터 AWS로 가는 것이낫다
홈 서버에 대해
비용 면에서는 최선이지만, 서비스 가용성과 운영자의 자유를 맞바꾸는 선택이다. 개인 포트폴리오나 사이드 프로젝트 수준이라면 충분하지만, 유료 사용자가 생기는 순간 SLA책임이 발생하고 홈서버로는 그것을 감당하기 힘들다
AWS 환경에서 핵심 네트워크 구조
Internet
│
▼
[CloudFront] ←─ WAF 부착 (첫 번째 방어선)
│
├──────────────────────┐
▼ ▼
[S3] [ALB (Application Load Balancer)]
(정적 파일/영상) │ ← HTTPS 인증서 여기 부착
▼
[EC2: API 서버]
(Private Subnet)
│
[RDS: Database]
(Private Subnet, 외부 직접 접근 불가)
관리자 접근:
내 PC ──SSH 터널링──▶ EC2 ──▶ RDS
(키 기반 인증, IP 화이트리스트)
DB와 API 서버는 Private Subnet에 격리. 외부에서 직접 접근 불가 구조.
WAF 두 지점 정리
CloudFront에 하나, 그리고 프론트엔드 배포 앞에 하나다. CloudFront를 통해 S3와 ALB를 통합하면 WAF를 CloudFront 한 곳에 붙이는 것으로 두 경로를 동시에 보호할 수 있다
관리자 시스템 — 실제로는 더 무겁다
이 섹션이 이 글에서 가장 중요하다. 대부분의 초기 서비스 기획이 여기서 현실을 직면하게 된다
| 사용자 기능 30% | 관리자 시스템 70% |
사용자가 보는 화면은 서비스의 30%에 불과하다. 나머지 70%는 그 화면이 작동하도록 뒤에서 움직이는 관리자 시스템이다. 이것을 설계 초기에 인지하지 못하면, “거의 다 됐다”고 생각한 순간에 실제로는 절반도 안 되는 상황을 마주하게 된다
관리자 시스템의 실제 기능 범위
| 회원 관리 • 전체 회원 목록 조회 • 회원 상세 정보 열람 • 계정 정리 / 탈퇴 처리 • 로그인 이력 및 세션 관리 • 비정상 접근 탐지 및 차단 | 콘텐츠 / 상품 관리 • 상품 등록 / 수정 / 삭제 • 카테고리 및 태그 관리 • 리뷰 필터링 및 삭제 • 공지사항 / 배너 / 로고 관리 • 인기 콘텐츠 수동 편집 |
| 구매 / 환불 관리 • 구매 내역 조회 • 환불 정책 설정 및 처리 • 쿠폰 발행 / 이벤트 설정 • 결제 오류 대응 인력 관리 • 매출 통계 및 정산 내역 | 시스템 운영 • 관리자 계정 생성 및 권한 부여 • 관리자 저체 활동 로그 • 알림 발송 이력 관리 • 시스템 설정값 관리 • 서비스 점검 모드 전환 |
관리자 시스템이 비대해지는 이유
- 운영 예외 상황은 사전에 완전히 예측할 수 없다. 환불 요청, 리뷰 어뷰징, 계정 도용 신고 등은 서비스를 실제로 운영해봐야만 알게 되는 케이스들이다. 이 케이스들을 처리하기 위한 도구가 관리자 시스템에 계속 추가된다
- 마케팅과 운영이 연결되면서 기능이 폭발한다. 쿠폰 하나를 만들기 위해 쿠폰 생성 · 조건 설정 · 사용자 발급 이력 · 통계까지 연결되는 흐름이 생긴다. 이런 기능들은 처음 설계할 때 “나중에 하면 되겠지”라고 넘어갔다가 나중에 코드 구조를 크게 바꿔야 하는 상황을 만든다
계정 유형 설계와 권한 통제
계정 유형은 인증 · 인가(Authorization) 아키텍처의 근간이다. 나중에 추가하면 전체 라우팅, 미들웨어, API 설계를 다 손봐야 한다. 반드시 초기에 정의해야 한다
계정 유형 설계 예시 (LMS 서비스 기준) ┌─────────────────────────────────────────┐ │ 계정 유형 │ │ │ │ 슈퍼어드민 (최고관리자) │ │ └─ 전체 권한 / 관리자 계정 생성 │ │ │ │ 관리자 │ │ └─ 회원·콘텐츠·구매 관리 │ │ └─ 개인정보 직접 열람 불가 (제한) │ │ │ │ 강사 │ │ └─ 자신의 강의만 편집 가능 │ │ └─ 수강생 목록 열람 (익명 처리) │ │ │ │ 일반 사용자 (학생) │ │ └─ 수강 · 구매 · 리뷰 작성 │ └─────────────────────────────────────────┘ ※ 계정 유형 중첩 허용 여부 결정 필요 예) 슈퍼어드민 = 강사 + 학생 + 최고관리자 동시 가능?
계정 유형 중첩 미지원 시 발생하는 실제 문제
계정 유형이 단일 역할만 허용되는 구조에서, 서비스 운영자가 자신의 강의를 직접 수강해보려 한다면 일반 사용자 계정을 별도로 만들어야 한다. 같은 이메일로 두 계정을 만들 수 없으니 다른 이메일을 써야 하고, 그 결과 한 사람이 여러 계정을 관리하는 비정상적인 구조가 만들어진다
RBAC vs ABAC
강의 수준에서는 Role-Based Access Control(RBAC)로 충분하다. 하지만 “강사는 자신의 강의만 편집 가능”처럼 소유권 기반 통제가 필요한 순간부터 Attribute-Based Access Control(ABAC) 요소가 들어온다. 이 구분을 초기에 어느 수준까지 구현할지 결정하지 않으면, 권한 로직이 여기저기 흩어진 스파게티 코드가 된다
관리자 활동 로그 – 왜 모든 API 콜을 기록해야 하는가
관리자가 실수로, 혹은 의도적으로 데이터를 변경하거나 삭제했을 때, 로그가 없으면 무엇이 언제 어떻게 바뀌었는지 추적이 불가능하다. 관리자 계정의 모든 API 호출에 대해 누가(account_id), 언제(timestamp), 무엇을(endpoint + payload 요약), 어디서(IP + User-Agent)를 기록해야 한다
보안 연결 지점
관리자 활동 로그는 단순 검사(audit) 목적만이 아니다. 비정상 패턴 탐지에도 사용된다. 예를 들어 특정 관리자 계정이 새벽 3시에 해외 IP에서 대량 회원 정보를 조회한다면, 이것은 계정 탈취 신호일 수 있다. 로그 없이는 이 사실을 사후에도 알 수 없다
관리자 시스템 분리 전략
“초기에는 함께 두고 나중에 분리” 판단 자체는 옳다. 다만 분리를 고려하는 시점을 좀 더 명확히 이해할 필요가 있다
| Phase 1 — 초기 | Phase 2 — 성장기 | Phase 3 — 성숙기 |
| 단일 서버 통합 | 관리자 서버 분리 | 알림 시스템 분리 |
| 사용자 API와 관리자 API가 같은 서버에서 동작. 라우팅으로 /admin 경로 분리만 해도 충분 | 관리자 트래픽이 사용자 서비스 성능에 영향을 주기 시작할 때. 또는 팀이 분리될 때 | 이메일 · 카카오 ·앱 푸시 등 외부 비동기 연동이 늘어날 때, 별도 큐(Queue) 시스템 도입 |
분리 시점에 대해
관리자 분리를 “향후 문제”로 정리할 수 있지만, 한 가지 현실적인 위험을 추가하고 싶다. 관리자 API에 적절한 인증 없이 서비스를 배포하는 케이스가 생각보다 많다. 단일 서버에서 /admin 경로를 단순히 URL로만 숨기고 적절한 인가 미들웨어를 붙이지 않으면, URL을 아는 사람은 누구나 접근할 수 있는 치명적인 구멍이 생긴다
분리는 나중에 하더라도, 관리자 엔드포인트에 대한 인증 · 인가 미들웨어는 처음부터 반드시 붙여야 한다. 이것은 분리 전략과 무관하게 초기 설계에 포함되어야 할 사항이다
알림 시스템을 별도로 분리해야 하는 이유
알림 시스템 내부 흐름
서비스 로직
(구매 완료 이벤트 발생)
│
▼
[알림 큐 (Queue)] ← 여기서 분리
│
┌────┴──────────────────────┐
▼ ▼ ▼
[이메일] [카카오 알림톡] [앱 푸시]
(SES) (카카오 API) (FCM/APNs)
│ │ │
응답 빠름 응답 불확실 iOS/Android 별도
핵심: 외부 서비스의 응답 지연이 메인 서비스에 영향을 주지 않도록 비동기 분리
이메일 발송 API가 느려졌다고 해서 구매 완료 응답이 함께 느려지면 안 된다. 알림은 발송 이벤트를 큐에 넣고, 메인 서비스는 바로 응답을 돌려줘야 한다. 이 구조를 처음부터 설계에 반영하지 않으면, 나중에 큐 시스템을 붙이는 것이 생각보다 큰 리팩토링이 된다
바이브코딩 전 최종 체크리스트
아래 항목에 답하지 못한 상태로 코드를 짜기 시작하면, 중간에 전체를 뜯어고칠 가능성이 높다
- 패스워드 단방향 해시 알고리즘 결정 (bcrypt / Argon2)
- 인증 방식 결정 — JWT, 세션, 혹은 영역별 이원화
- OAuth2 소셜 로그인 연동 범위 확정
- 서비스 운영환경 결정 (홈서버 / Vercel+Supabase / AWS)
- AWS 선택 시: VPC 구조, Private Subnet, WAF 배치 계획
- 계정 유형 정의 및 중첩 허용 여부 결정
- RBAC 권한 테이블 초안 작성
- 관리자 기능 범위 전체 목록 작성 (생각보다 길다)
- 관리자 API 인증·인가 미들웨어 설계 포함
- 관리자 활동 로그 구조 설계
- 알림 시스템 필요 채널 확정 및 비동기 처리 여부
- 환경변수 및 시크릿 관리 방식 결정
- Rate Limiting 적용 범위 결정 (로그인, API 전체 등)
결론
이 목록이 완성된 상태에서 프롬프트를 작성하면 AI가 생성하는 코드의 품질이 달라진다. 보안 요구사항, 계정 구조, 관리자 기능 범위가 명확할수록 AI는 그것을 반영한 아키텍처를 제안한다. 준비가 프롬프트의 품질을 결정하고, 프롬프트의 품질이 코드의 품질을 결정한다