SESSION 04 / 06
F12 · 6 방어선 · 보안 감사 · account.md
지준영
비전공(경영학과) → 기자 · 해외영업 → 개발자 전향
iOS · Android · Frontend 약 5년 반 (6년차)
대기업 협업툴 iOS/macOS 앱 개발
2026~ 바이브코딩으로 웹 · 서버 1인 개발 · 사업화
PART 1 — 3화 복기
WHY WEB IS WILD
저도 보안 담당자 무서워합니다. 저는 보안 전문가가 아니에요.
모바일 vs 웹 — 개발자 책임 영역이 다릅니다
Sandbox · Code Signing · ATS · Keychain · 앱마켓 심사 — OS·플랫폼 차원의 기본 보안
HTTPS · CORS · CSRF · XSS · SQL Injection · DDoS · 서버 OS · 인증·인가 — 전부 직접
웹은 AI가 가장 많이 학습한 분야
로그인·게시판·대시보드 — 학습 분포의 *평균값*. 기능 동작에 강함.
엣지 케이스, 비정상 입력, 특수 조건. 학계 용어 — adversarial robustness
챙기면 잘 굴러갑니다. 안 챙기면 망합니다.
오늘 6가지 방어선 = 챙기는 최소한.
EDGE CASE · 결제
"5분 안에 된다? 튜토리얼대로 하니까 되더라?"
해보십시오. 매출 안 나오면 모르고, 폐업하고 묻고 넘어갈 수도 있습니다.
매출이 많아지고, 표적이 되면 — 그때 알게 됩니다.
결제 = 수많은 절차와 분기가 한겹 한겹 계층으로 쌓이는 가장 복잡한 기능.
그 계층들 간의 모순이 없어야 함. AI 평균치 코드가 거의 안 다루는 엣지가 폭발.
왜 무서운가 — 익숙한 두 가지
• iOS 인앱결제 — 옛날 게임사들이 고통받았던 그 영역. Apple 30% 수수료 · 자동갱신 · 환불 · 영수증 검증 …
• 중소기업 CS — 결제 사고 시 고객 분노 직격. "내 돈 어디 갔냐" 폭언, 별점 1점 폭주, 평판 한 달 만에 붕괴.
강사 본인 고민
제가 강의 때 소설 올리는 서비스 몇 번 보여드렸죠?
제가 지금 제일 고민을 많이 하는 부분이 이겁니다 —
결제 기능의 공격 포인트 방어하기.
F12 · DEVTOOLS
크롬 기준 — 아무 페이지에서 마우스 오른쪽 → 검사.
또는 클로드한테 *"내 컴퓨터가 윈도우/맥 어떤 거야? '웹개발자 도구' 어떻게 열어?"*
Network 탭에 보이는 것
API 호출 경로 · 요청 내용 · 응답 내용
어떤 AI 모델을 쓰는지 · 환경변수 · localStorage · 쿠키
전부 공개 상태입니다.
병원 X-ray로 뼈가 보이는 건 정상입니다.
내가 내 컴퓨터에서 확인하는 것도 해킹이 아닙니다.
문제는 — 누구나 열 수 있다는 것.
브라우저는 개발자 편인지 해커 편인지 구분하지 않습니다.
TWO RISKS
F12는 사용자 보호이면서 동시에
내 아이디어 보호의 문제입니다.
ANALOGY
방 서랍 비유
내 방에서 내 일기장 꺼내보는 건 사고 아님.
진짜 사고는 도둑이 창문 깨고 들어와 훔쳐가도록 방치하는 것.
놀이공원 팔찌 — 어디에 보관하느냐가 전부
같은 팔찌여도 어디 두느냐에 따라 달라집니다.
"도둑"의 정체 = XSS 공격자
누가 페이지에 악성 자바스크립트를 심어놓은 상황 (Cross-Site Scripting).
localStorage는 같은 도메인 JS가 다 읽음 → 악성 스크립트가 토큰 탈취.
HttpOnly 쿠키는 JS에서 아예 안 보임 → 못 훔침. HttpOnly의 본업 = XSS 발생해도 토큰 못 훔치게.
PART 2
해커가 1인개발자 사이트를 터는 데
10초도 안 걸립니다.
INCIDENT 01
문제 — 기본 방어선 4가지가 전무
창업자가 "한 줄도 안 썼다"고 자랑한 B2B 리드 SaaS.
API 키 프론트 노출 · 인증 없음 · DB 무방비 · rate limiting 없음.
공격 경로
브라우저 콘솔로 결제 우회 → 유료 기능 무료 사용 → API 키 소진.
Cursor로 고치려 시도 → "다른 부분만 계속 깨뜨렸다" → 포기·폐업.
KEY TYPES · 두 종류 구분
apiKey · Google Maps · Stripe pk_* · Supabase anonsk-ant-* · OpenAI sk-* · Stripe sk_* · Supabase service_role자가 진단 — *"이 키 노출되면 누구나 호출해서 *돈* 나가거나 *권한* 얻나?"* YES → 시크릿. NO → 공개.
교훈 — 시크릿 키는 안전한 곳에.
웹·서버 구조면 백엔드 환경변수에 격리. iOS·Android 앱은 자체 백엔드 거쳐 호출. 공개 키는 박아도 OK 단 *정책 반드시*.
INCIDENT 02
사고 경위 — 이중 실수
창업자 Matt Schlicht가 "한 줄도 안 썼다"고 선언한 AI 에이전트 소셜 플랫폼.
Supabase 기반 · RLS 꺼짐 + 권한 있는 키가 클라이언트 JS에 노출.
→ anon 키 자체는 공개해도 OK. 단 *RLS 꺼짐* + *시크릿 키 노출* 조합이 사고 원인.
결과 — API 키 150만 건 · 이메일 3.5만 건 · 에이전트 개인 대화 전체 유출.
보안회사 Wiz Research가 조사 공개.
교훈 — Supabase RLS · Firebase Security Rules 무조건 켠다.
Claude한테 매번 체크시키기.
INCIDENT 03
1차 유출 (2025년 7월)
여성 전용 앱. 가입 시 운전면허·셀피 수집.
Firebase Storage 권한을 누구나 접근 가능한 상태로 방치.
이미지 7.2만 건 유출 — 운전면허 포함 셀피 약 1.3만 건.
2차 유출 (며칠 뒤)
개인 메시지 110만 건까지 추가 유출.
낙태 상담, 불륜 고민 등 극히 민감한 대화 포함.
교훈 — 파일 업로드 기능 있으면
Storage 권한 반드시 체크.
KBS 창 540회 · 봐야 할 두 구간
"나의 완벽한 비서 · AI 에이전트 시대" · youtu.be/QQJpyIO014A
사건 ① · 영상 도입부 (초반) — 다큐 주인공
보안업계 스타트업 CEO · 발리 거주 · 하루 30분 근무 · 에이전트 결과만 승인
그 사람이 거기까지 가는 데 우리가 짐작만 할 수 있는 4가지 —
(참고 — 팔란티어 엔터프라이즈 월 2천만원+ 내는 회사도 있어요.)
사건 ② · 28~32분 구간
호텔 예약 자동화 에이전트에게 *"50만원만 쓰라"* 지침이 76만원 결과.
KAIST 연구진 + KBS 스태프가 만든 통제된 공격 실험. 외부 웹페이지에 심어둔 공격적 코드·프롬프트가 에이전트를 오동작시키는 시나리오. 실제 피해자 아님.
강사 출신 — 잡지사 기자 (1화 첫날 소개). 미디어 작동 방식은 편집부 의도의 결과.
집에서 영상 보면서 두 가지 확인 —
① 사건 ① CEO의 노력·공부·시행착오·비용 — 화면에 나오나?
② 사건 ② 공격 메커니즘(어텐션·툴 콜링·판단·IDPI) — 명확하게 나오나?
안 나왔다면 — 편집에 잘려나간 것. 그게 미디어의 본질.
결정적 질문 —
"내가 만드는 서비스는, 그 공격을 방어할 준비가 되어 있는가?"
↓ 4화 본론(6가지 방어선)으로 가는 다리
PART 3
외울 필요 없습니다. 사진 찍어가세요.
Claude한테 "이것도 같이" 한 줄이 핵심.
TODAY · 6 BASIC DEFENSES
데이터베이스의 한 줄(행)마다 *누구 소유*인지 표시 → 본인 행만 읽기·쓰기.
예: "내 글은 나만, 남의 글은 못 보게"
Supabase·Firebase 디폴트 OFF — 안 켜면 누구나 모든 행 접근.
하드코딩한 키는 GitHub에 올라가는 순간 전 세계 노출. .env로 분리.
NEXT_PUBLIC_·VITE_·REACT_APP_ 접두사 붙은 키는 번들에 박혀서 브라우저 노출.
OpenAI·Anthropic 키를 클라이언트(브라우저·앱)에 박아두고 호출하면 즉시 탈취. BFF/API Proxy 패턴.
Production에 .map 노출되면 난독화 코드 → 원본 복원. productionBrowserSourceMaps: false
실수로 .env 커밋되면 — push 후 30분 내 봇이 키 자동 수집.
이 여섯, 하나씩 풀어 갑니다.
IF YOU SKIP — WORST CASE
API 키 노출 → 자동 봇이 30분 내 수집 → OpenAI·AWS 청구서 폭주.
한 달 만에 수천만 원 ~ 수억 가능.
개인정보보호법 위반 → 매출의 최대 3% 과징금 + 피해자 1인당 손해배상.
집단소송 시 영세 사업자도 사장 개인 파산 가능.
랜섬웨어로 DB 암호화 → 비트코인 몸값 요구.
백업 없으면 사업 자체 종료. 평균 몸값 글로벌 80만~150만 달러.
별점 1점 폭주·X(트위터) 박제 → 한 달 안에 신뢰 회복 불가.
"그 사이트 결제 사고 났대" 한 줄이 곧 매출 0.
이 네 개 — 6방어선 중 한 개만 빠뜨려도 발생합니다.
패가망신. 과장 X. 실제 사례 매주 나옵니다.
이 한 줄로 Moltbook 사고는 예방됩니다.
RLS — 쉽게
비유
아파트 1층 우편함, 100세대 우편함이 다 있어요.
"내 집 우편함은 나만 열 수 있다" — 이게 정상.
→ RLS 켠 상태 = 정상
안 켜면?
입주민 누구나 100세대 우편함 다 열 수 있다.
이웃집 통장, 카드 청구서, 등기우편 다 열람 가능.
→ Supabase·Firebase 디폴트 OFF. 안 켜면 누구나 모든 사용자 데이터 읽기·수정 가능.
RLS = "이 데이터 한 줄(행) 소유자만 열 수 있다"
한 줄로: 우편함마다 자물쇠 달아두는 것.
Vercel · Netlify는 대시보드 '환경변수' 입력칸에 넣으면 됩니다.
API 키 — 쉽게
비유 (시크릿 키 한정)
호텔 직원이 가진 마스터 키 — 모든 객실 다 열림.
OpenAI·Anthropic·AWS *시크릿 키*도 똑같아요. "이 키만 있으면 그 회사 서비스 마음대로 쓸 수 있음."
→ 사용량은 키 주인(나)에게 청구. *공개 키*는 다른 종류 — S10 분류 참조.
코드에 박으면?
호텔 마스터 키를 호텔 정문에 자물쇠 안 채우고 걸어둔 상태.
지나가는 누구나 떼서 객실 다 열고 미니바·금고 털어감.
→ GitHub에 키 올라가면 30분 내 봇이 수집 → OpenAI 청구서 폭주, 한 달 만에 수천만 원~수억.
코드에 박지 말고 — .env 라는 별도 파일에 분리.
.env는 절대 Git에 올리지 말 것 (다음 슬라이드에서).
EnrichLead 사고가 정확히 이 실수였습니다.
다른 프레임워크도 같은 룰 — VITE_ (Vite) · REACT_APP_ (CRA). 이름은 달라도 *'클라이언트에 노출'* 은 동일.
단, *공개 키*에는 붙여도 OK
Firebase apiKey, Stripe pk_*, Supabase anon 같은 *공개 키*는 NEXT_PUBLIC_*·VITE_* 붙여도 OK. 어차피 공개 의도된 키니까요.
→ 시크릿 키만 절대 X. S10 분류 참조.
NEXT_PUBLIC_ — 쉽게
비유
가게에 두 종류 글자가 있죠.
간판 = 행인 누구나 봄 (전화번호·주소·메뉴).
사장 금고 안 = 직원도 못 봄 (현금·도장·통장).
→ NEXT_PUBLIC_ 접두사가 붙은 키 = 간판에 적힌 글자. 빌드 시 브라우저로 그대로 새어나감.
실수로 *시크릿 키*에 붙이면?
사장 금고 비밀번호를 간판에 써두는 격.
OpenAI sk-*·Supabase service_role 같은 시크릿 키에 NEXT_PUBLIC_ 붙이면 → F12 한 번에 도둑 손에.
→ VITE_·REACT_APP_도 같은 원리. 다른 프레임워크의 같은 함정.
규칙: 접두사 = '클라이언트로 새어나감'이라는 표시.
→ 이 자리에는 *공개 키*만 (Firebase apiKey, Supabase anon, Stripe pk_*). *시크릿 키*는 절대 X — 사장 금고 비번을 간판에 박는 순간.
Claude에게: "서버 사이드 API Route에서 호출해줘" 꼭 붙이기
PLATFORM · 플랫폼별 적용
/api/*, Vite는 별도 Express·Hono·Vercel Functions)에서만 호출. 키는 백엔드 환경변수.→ 공통 원리 — *시크릿 키*(OpenAI·Anthropic·Stripe `sk_*`·Supabase service_role 등)는 *반드시* 자체 백엔드에서만 사용. 사용자 인증 토큰(JWT·OAuth)은 OS Keychain/Keystore에. 셋은 다른 종류.
자주 나오는 혼동 — "Firebase는 Info.plist에 키 그냥 넣으라던데?"
맞아요. Firebase apiKey는 *공개 키* — *그 자체로 권한 없음*. 그래서 앱에 박아도 OK.
단 진짜 방어선은 Firebase Security Rules + App Check. Google Maps key·Stripe `pk_*`·Supabase `anon`도 같은 결.
→ S10 *공개 키 vs 시크릿 키* 표 다시 떠올리기. 시크릿만 백엔드, 공개는 앱 OK 단 *정책 켜기 필수*.
BFF — 쉽게
비유 — 식당
손님 = 사용자 (브라우저)
직원 = 내 서버 (BFF · Backend For Frontend)
사장 = 외부 API (OpenAI·은행·결제)
→ 손님이 사장 사무실 직접 들어가서 금고 만지면 X. 직원이 손님 부탁 받아 사장에게 전달.
손님이 사장 직접 만나면?
손님이 사장 금고 비번(API 키) 다 알게 됨.
그 다음 손님은 다른 손님인 척하고 매일 식당 와서 금고 털어감.
→ 클라이언트에서 OpenAI·은행 직접 호출 = API 키 노출. 봇이 수집해서 청구서 폭주.
규칙: 손님은 직원만 만난다. 직원이 사장에게 전달.
즉 — AI·결제·DB 호출은 반드시 내 서버(BFF)에서. 클라이언트 X.
Source Map이 뭐길래?
여러분 코드(TS·JSX·최신 JS) → 빌드 도구가 압축·번역·하나로 묶기 4단계 변환 → 브라우저로 보냄. 변환 후 코드는 사람이 못 읽음.
버그 디버깅 위해 — *원본 ↔ 압축본 번역 대조표* 를 빌드가 따로 만듭니다. 그게 .map 파일 = Source Map.
비유 — 한국어 책 영역(英譯)본의 *번역 대조표*. 영역본에 오타 나면 한국어 어디였는지 찾을 때 쓰는 사전.
같은 함수 — 원본 vs 빌드 후 (사람이 짠 거 vs 브라우저로 가는 거)
Source Map 켠 채로 운영 올리면 → F12에서 왼쪽(원본) 그대로 보임. 함수가 뭘 하는지 · 비즈니스 로직 · 주석 메모 다 노출.
DEFENSE 05 · 설정 + 의도 분류
"근데 왜 다른 회사는 켜놨던데요?" — 의도 5가지 분류
모르고 켜놓음 — 빌드 기본값, F12 점검 안 함
70~80% ②"프론트는 어차피 공개" 철학 — 시간 차이(5초 vs 며칠) 무시
15~20% ③디버깅 편의 — Sentry·Datadog 안 쓰는 작은 팀
5~10% ④오픈소스·마케팅 — Vue·React, Stripe·Linear
5% ⑤"moat는 코드가 아니다" — Netflix·Spotify 류 대기업
극소수→ 1인 창업자·소상공인에게 ⑤ 적용 X. 여러분의 moat = 핵심 로직·프롬프트. 80%(몰랐음) 카테고리에 있을 가능성이 큼 — 한 번 확인하고 끄세요.
Claude에게: "이 프로젝트 production build에서 source map 노출되는지 확인해줘"
ADVANCED · 고급 옵션
hidden-source-map — 보안 + 디버깅 둘 다 잡는 표준 패턴옵션 둘 중 선택
① 완전 끄기 (`sourcemap: false`) — 가장 안전. 단 운영 에러 추적 어려움.
② hidden-source-map — *생성*은 하되 sourceMappingURL 주석을 안 박음. 일반 사용자 F12에는 안 보임.
hidden-source-map 동작 방식
생성된 .map 파일을 서버 배포에 포함하지 않고 — Sentry·Datadog 같은 에러 추적 서비스에 *별도 업로드*.
→ 운영 중 에러가 나면 Sentry 대시보드에서 *원본 라인까지* 추적 가능. F12로는 못 봄.
프레임워크별 옵션
Next.js — productionBrowserSourceMaps: false + Sentry 연동
Vite — build.sourcemap: 'hidden'
Webpack — devtool: 'hidden-source-map'
CRA — GENERATE_SOURCEMAP=false (CRA는 hidden 미지원)
한 줄 — 완전 끄기는 가장 안전, hidden은 *보안 + 디버깅* 둘 다 챙김.
규모가 커져서 Sentry·Datadog 쓸 때 자연스럽게 hidden으로 전환.
Source Map — 쉽게
비유
건물 다 짓고 외관만 보면 — 일반인은 환기구·비밀통로·금고 위치 못 찾음.
설계도가 있어야 어디에 뭐가 있는지 다 보임.
→ Source Map = 압축된 코드 ↔ 원본 코드 *번역 대조표*. 이게 있으면 F12에서 원본 그대로 보임.
설계도 외부에 공개하면?
도둑이 건물 전체 환기구·비밀통로·금고 위치 다 알게 됨.
건물 외관은 그대로인데 들어오는 길이 무한히 많아짐.
→ Production에 .map 노출되면 비즈니스 로직·보안 검증 코드·주석 메모 다 보임. 약점 즉시 발견.
규칙: 건물 다 지었으면 설계도는 회사 금고에. 외부 공개 X.
productionBrowserSourceMaps: false 한 줄.
실수로 커밋한 상태면 — Git 히스토리에 남습니다.
키를 즉시 재발급하세요.
Git · .gitignore · .env — 쉽게
비유
Git = 일기장 자동 백업 시스템 (매일 클라우드에 사진 찍어 저장)
.env = 비밀일기 (비밀번호·통장 비번·일기 속 누구 험담)
.gitignore = "이건 백업하지 마" 명단
→ Git은 모든 파일을 자동으로 클라우드에 올림. 비밀일기는 .gitignore에 적어둬야 안 올라감.
.gitignore에 안 적으면?
비밀일기까지 클라우드에 자동 백업됨. 그것도 *영원히* 히스토리에 박힘. 한 번 올라간 비번은 — 키 즉시 재발급해야.
→ GitHub에 .env 실수로 커밋되면 30분 내 봇이 키 자동 수집. AWS·OpenAI 청구서 폭주. 사후 삭제해도 히스토리에 남음.
규칙: .gitignore에 .env·.env.local·.env.*.local 무조건 추가.
새 프로젝트 만들 때 가장 먼저 할 일.
6 DEFENSES — CHECKLIST
이 여섯 개만 체크해도
오늘 본 사고 세 건 전부 예방됩니다.
KEY MANAGEMENT · 통합 정리
한 서비스 — Supabase anon · Firebase apiKey · OpenAI sk- · Stripe pk_·sk_ · Google Maps · Anthropic sk-ant- ... 키만 5~10개 흔함.
Firebase apiKey · Google Maps · Stripe pk_* · Supabase anon
→ *식별용*. 그 자체로 권한·돈 없음.
Anthropic sk-ant-* · OpenAI sk-* · Stripe sk_* · Supabase service_role
→ 백엔드 환경변수만.
간단 자가 진단 — "이게 털리면 — 내가 *요금*을 내는가? / 내 *데이터베이스*가 뚫리는가?"
YES → 시크릿. 백엔드만. | NO → 공개. 클라이언트 OK 단 *추가 방어법 필수*.
공개 키를 안전하게 — 추가 방어법
DB 행/문서 단위로 *"이 사용자는 자기 것만"*. Supabase RLS · Firebase Security Rules.
Application Restrictions — Google Maps key는 *내 도메인·번들 ID에서만 호출 가능*. 다른 곳에서 쓰면 거절.
Firebase App Check — 진짜 내 앱에서 온 호출인지 검증. 봇·스크래핑 차단.
+ 시크릿 키는 무조건 — .env 분리 · .gitignore에 등록 · 백엔드 환경변수에만.
한 줄 — 공개 키 + 정책 = 안전. 공개 키만 + 정책 X = 그냥 폭망.
키만 박는 게 보안의 끝이 아니라, *정책까지 켜는 것*이 보안의 절반.
잠시 후 돌아와서
"클로드는 까먹는다" 얘기를 하겠습니다.
PART 4
TODAY · 10원칙 추가 2개
후반부에 — 10원칙 중 2개를 더 추가합니다.
이 둘, 후반부에서 풀어 갑니다.
먼저 — 클로드의 *"기록해놨습니다"* 거짓말 + account.md 해결책부터.
PART 4 — CLAUDE FORGETS
강사 실제 경험
Claude에게 — "이거 좀 기록해놔라" 라고 명령.
"네, 기록해놨습니다" 라고 답함.
다음 세션에 물어봤더니 — 모름. 사실 기록 안 한 일이 비일비재.
Claude는 매 세션마다 처음부터 시작합니다.
기억이 없어요. 3화에서 얘기했죠.
더 심한 경우
심하면 — 같은 세션 안에서도 2시간 전에 얘기한 걸 기억 못 합니다.
→ 컨텍스트가 길어질수록 앞쪽을 흐릿하게 처리. 3화에서 박은 *Context Rot* 그대로.
Claude가 "기록했다"고 하면 — 반드시 확인.
중요한 건 여러분이 직접 적어둡니다.
account.md (.gitignore에 추가)
키 발급 출처 · 클라우드 계정 이메일 · 인프라 설정값 · 컨테이너 이름
암호는 절대 넣지 말 것
규칙이 늘어나면 — 별도 파일로 분리
보안 규칙이 길어지면 SECURITY.md로 빼고 CLAUDE.md에서 *참조*만 거는 것도 좋습니다.
→ 3화 *정본·참조* 패턴 — CLAUDE.md는 짧게 유지, 세부는 파일별 분리.
3화 정본 개념의 보안 실전 적용. Claude가 매 세션 이 규칙을 읽고 인식.
PART 5
2화 원칙 — 문서화 · 감시 · 갈굼.
보안은 그중에도 감시가 핵심.
AUDIT PROMPT
Claude의 감사 결과를 Gemini · Codex에 다시 던져라.
같은 AI가 자기 코드 감사하면 "문제 없는데요" 나옴. Gemini가 결과 보고서에 훈수 두고 다음 단계 잘 제시해주는 경우도 많음.
요지 — 교차 검증이 핵심.
이게 끝이 아닙니다
웹·백엔드가 방어해야 하는 항목은 무지하게 많습니다.
이 6개는 *시작점*. OWASP Top 10 · 인증 토큰 위치 · CSP · CORS · Rate Limit · SQL Injection · CSRF · SSRF · Race Condition — 끝없이 갑니다.
→ 오늘 박는 6개는 *바이브코더가 가장 자주 빼먹는* 6개.
REAL · 강의 직전 외부 점검
S36은 자기 코드 정적 분석용. 이건 결이 다름 — 사이트 한 페이지만 보고 외부 런타임 점검 (인증 토큰 위치·응답 헤더·노출 경로)
대상: 한 한국 AI 글쓰기 SaaS · 도구: Claude Chrome MCP · 명령: "보안 감사 해봐" 한 마디 · 익명 처리
① 인증 토큰 — localStorage에 박혀 있음
키 *_token, JWT 형식, 길이 120자.
→ 4화 핵심 안티패턴. F12 한 번이면 누구든 토큰 확인.
② 토큰 디코드 — 24시간 long-lived
HS256 · payload sub·exp 2개뿐 (iat·jti·iss·aud 누락) · 만료 +24시간.
→ 표준 access는 15분~1시간. 24시간 + jti 없음 = 탈취 시 강제 무효화 불가, 24시간 무제한 사용.
③ 보안 응답 헤더 — 5개 누락
CSP · X-Frame-Options · X-Content-Type-Options · Referrer-Policy · Permissions-Policy = 모두 없음.
→ HSTS만 켜져 있음. CSP 한 줄 있었으면 XSS 인라인 스크립트 차단됐을 텐데 — 방어선 0겹.
④ 서드파티 다수 + CSP 부재 = 공급망 공격 면적 확대
GTM · GA · 외부 CDN 다수 로드. CSP 없음 → 그 도메인 침해 시 사이트 사용자 전체에게 악성 코드 전파 가능.
결제 받는 정식 서비스 · 4화 안티패턴을 거의 다 갖춘 상태로 운영 중.
— 아직 안 털렸을 뿐, *털리기 매우 쉬운* 상태.
PRECISELY · 정확하게 설명하자면
① localStorage 토큰만 박은 것 — 토론 가능 영역
시니어 웹개발자 중 *반*은 욕하고, *반*은 *"CSP·XSS 방어 잘 했으면 OK"* 라고 답함.
② 조합(localStorage + CSP 없음 + 24h + jti 없음) — 명백한 위반
토론 영역이 아니라 표준 위반. 어떤 시니어한테 보여줘도 "이건 안 돼요" 답함.
③ 한 줄로
localStorage엔 위험한 값(인증·결제·개인식별정보)은 절대 X.
다크모드·언어·UI 상태는 OK. 기밀은 X.
④ 이 서비스는
후자(② 조합)에 가까움.
localStorage 한 가지만 봐서 욕하는 게 아니라 — 조합 때문에 위험.
SO — 최소한이라도
하나 — 못해서가 아니라 안 한 것
Vite + React + Vercel로 깔끔하게 만든 분들. 똑똑한 분들 맞음.
인증 토큰을 HttpOnly 쿠키로 박는 5분짜리 작업 하나를 안 한 것.
둘 — 1조원 회사도 안 합니다
EnrichLead · Moltbook · Tea — 다 결제 받던 회사들.
최소한이라도 챙기지 않았고 — 사고 한 번에 1주일 만에 폐업 (EnrichLead).
셋 — 여러분도 같은 위협 안에
바이브코딩으로 결제 붙이고 사용자 받는 그 순간 — F12 한 번이면 다 보입니다.
최소한 = 6 방어선 + account.md + 보안 감사 프롬프트.
이 셋은 무조건. 재기 불능 사고는 한 번이면 끝입니다.
마지막 한 마디
제가 던진 명령은 "보안 감사 해봐" 한국어 한 마디였습니다.
클로드가 그 한 마디로 이 정도까지 잡아왔어요.
그러면 — 공격에 *도가 튼 사람들*이 같은 사이트를 노리면 어떨까요?
TEST
유닛테스트 · E2E 테스트 · UI 테스트 — 지금 외울 필요 없음.
쉽게 말하면, 자동 검증 프로그램입니다.
전통적 개발: 개발자가 직접 짬.
바이브코딩: Claude한테 시키면 됩니다.
한 줄: "이 기능에 대한 테스트 파일도 같이 만들어줘"
MARTIN FOWLER · 1999
— Any fool can write code that a computer can understand.
Good programmers write code that humans can understand.
『Refactoring: Improving the Design of Existing Code』 (1999)
27년 전 말입니다.
1화 콜백 — "책이다 / 전문가 폄하 금지 / 앤스로픽도 책 학습"
이 아저씨가 그 예시. 소프트웨어 업계의 신입니다.
물론 다익스트라 알고리즘의 다익스트라, 리스코프 치환 원칙의 리스코프도 있죠.
정확히는 — 이론의 신이 아니라 엔터프라이즈 실무의 신.
분야는 다르지만, 천 년 전부터 코딩 배워도 따라갈 수 없는 신 맞습니다.
2023~2025 — 지금도 현역
martinfowler.com · Exploring Generative AI 시리즈 운영 중.
27년 전 책의 저자가, AI 시대 코딩에 대해서도 계속 글을 씁니다.
즉 — 여러분의 클로드도, 이 양반 글을 다 학습했을 겁니다.
바이브코딩 시대로 한 번 비틀면 —
"어떤 AI라도 컴퓨터가 이해할 수 있는 코드는 작성합니다.
좋은 사용자는 — AI와 사람 둘 다 이해할 수 있는 코드와 문서를 작성한다."
그 시작이 — 기본기이고,
개발자들이 고민하는 아키텍처 · 디자인 패턴 · 코드 복잡도 같은 기술 용어이다.
F12 · RLS · NEXT_PUBLIC_ · source map · BFF 프록시 · 권한 체크 —
이 단어들을 모르면 AI가 내놓은 코드를 갈굴 수가 없습니다.
Claude가 "안전합니다" 할 때 던질 질문:
"RLS는 켰어? 이 키 클라이언트로 노출 안 돼?"
5화에서 만날 단어들도 — 다 무기가 됩니다:
클린 아키텍처 · MVVM · FSD · 멱등성 · 원자성 · 디자인 패턴 …
2회차 · 3회차 숙제를 하신 분 —
오늘 F12 눌러보면 "아 이게 이렇게 다 보이네" 실감 옵니다.
한 번도 배포 안 해본 사람은 머리로만 압니다.
눈으로 본 사람만 감각이 생깁니다.
PRINCIPLE 08 · 실전
코드보다 단순. 누구나 가능.
이미지 생성 AI에 — 일러스트, 풍경화, 유화, 수채화 다 시도.
강사 사례 — 제미나이 앱 첫 출시부터 100장+ 깎음. 가입한 바이크 모임방 엠블렘 직접 제작.
AI 비교 — 직접 깎아본 사람만 안다
"덕테이프가 나노바나나를 꺾을지도" — 직접 비교.
"코덱스로 탈주? 코덱스는 리뷰만? 일은 클로드?"
강사가 직접 써본 두 모델 비유
브레인스토밍 강함. 장문 글에서 선 넘는 비약 드러남.
구체화·기승전결·논리 정합성 강함. 똑똑하지만 뺀질이 — 끊임없이 갈궈야.
AI 갈구기 방법론 — 개발자들이 활발히 연구 중
• 하네스 엔지니어링 — *큰 우산.* AI 작업 환경 자체를 어떻게 설계할지
• 에이전트 — *그 환경 안의 자율 실행 단위.* AI가 도구를 자율적으로 선택·계획·실행 (Claude Code, Cursor Composer)
같은 연구 흐름 안에 있음. 6화에서 다시.
10 PRINCIPLES — 10/10 완성
10원칙 전부 다뤘습니다.
이 10개가 6회 과정의 뼈대입니다.
PART 6 — HOMEWORK
SESSION 04 / 06
다음 시간 — 5회차.
"알아서 해줘"는 통하지 않는다 — 기술 어휘의 힘.
질문은 카카오톡 오픈채팅으로.