가장 많이 실수하는 자리
여기서부터는 AI가 짜준 사이트에서 가장 흔하게 발견되는 사고 자리를 짚어드립니다. 각 자리는 같은 흐름으로 정리했습니다.
- 증상: 사고가 화면에 어떻게 드러나는지
- 왜 일어나는지: 어떤 흐름으로 사고가 시작되는지
- AI에게 시킬 점검 프롬프트: AI에게 코드 점검을 맡길 때 그대로 복사해 쓸 수 있는 문장
- 법적 위험: 사고가 났을 때 어느 법에 어떻게 걸리는지
1. 회원가입에서 동의 절차를 건너뜀
증상: 회원가입 폼이 이메일·비밀번호·이름만 받고 가입 버튼이 끝입니다. 또는 "이용약관과 개인정보 처리방침에 모두 동의합니다"가 한 줄짜리 체크박스 하나로 묶여 있습니다. 마케팅 수신 동의 체크를 끄면 가입 버튼이 비활성화됩니다.
왜 일어나는지: AI에게 "회원가입 폼 만들어줘"라고 하면 기능 동작에 필요한 칸만 만들어 줍니다. 동의 화면은 법이 요구하는 절차라서, 따로 시키지 않으면 AI는 개발하지 않습니다. 동의 화면을 만들더라도 약관·개인정보·마케팅을 한 묶음 체크박스로 만들어 두는 경우가 흔합니다.
개인정보보호법은 회원가입 시점에 다음을 요구합니다.
- 수집 항목·이용 목적·보유 기간을 알리고 동의를 받기: 동의 없이 수집한 개인정보는 그 자체가 위법입니다.
- 필수 동의와 선택 동의를 분리: 약관과 개인정보 수집·이용은 필수, 마케팅 수신과 제3자 제공은 선택입니다.
- 선택 동의를 거절해도 서비스 이용이 가능해야 합니다. "선택 동의 안 하면 가입 불가"는 같은 조항으로 위법이에요.
- 만 14세 미만은 법정대리인 동의가 필요합니다. 우리 서비스가 14세 미만도 쓸 수 있다면 별도 흐름이 들어가야 합니다.
여기서 가장 자주 걸리는 자리는 선택 동의를 가입의 전제 조건으로 묶어둔 코드입니다. 폼 화면에서는 별도 체크박스로 분리되어 보여도, 가입 처리 함수가 마케팅 수신 동의 값을 함께 검증하면 그 자체가 위법입니다.
AI에게 시킬 프롬프트:
이 프로젝트의 회원가입과 개인정보 수집이 일어나는 자리를 모두 찾아줘. 각 자리에 대해 법률 위반이 있는지, 위반되면 어떤 법률 위반인지, 법률 위반이 없어도 개선할 점이 있는지 점검해줘.
이렇게 간단히 프롬프트를 작성한 이유는 항목으로 정해두면 그 항목만 검사하기 때문입니다. 서비스와 법은 시간에 따라 계속 바뀌고, AI의 성능은 날이 갈수록 높아지기 때문에 프롬프트를 유연하게 바꾸는 것이 중요합니다. 또한 나온 결과물은 꼭 관련 법 조항을 확인해보세요.
법적 위험: 동의 없이 개인정보를 수집하면 개인정보보호법 위반이고, 선택 동의를 가입 조건으로 묶으면 동의 분리·선택 강요 금지 위반으로 둘 다 과태료 대상입니다.
2. 관리자 페이지가 인터넷에 그대로 노출됨
증상: 주소창에 https://내도메인.com/admin을 치면 관리자 로그인 화면이 뜹니다. 비밀번호를 걸어 두었으니 괜찮다고 생각하고 그대로 둡니다.
왜 일어나는지: 요즘 AI는 관리자 페이지에 로그인을 안 거는 실수는 거의 하지 않습니다. 다만 더 근본적인 문제는 따로 있습니다. 관리자 페이지가 외부 인터넷에서 접근 가능하다는 사실 그 자체가 위험입니다. 로그인 화면이 떠 있다는 건 공격자에게 "여기로 시도하세요"라고 문 앞에 표지판을 세워둔 것과 같아요. 사람들은 이걸 잘 모릅니다. "비밀번호만 잘 걸면 되지"라고 생각하지만, 외부에 노출되어 있는 한 다음 공격이 끊임없이 들어옵니다.
- 무차별 로그인 시도(Brute Force):
admin/admin,admin/1234,admin/password같은 흔한 조합 수만 개를 자동으로 시도 - 크리덴셜 스터핑(Credential Stuffing): 다른 사이트에서 유출된 아이디/비밀번호 목록을 그대로 가져와 대입
- 로그인 폼 자체의 취약점 탐색: SQL 인젝션, 인증 우회, 세션 고정 같은 공격
- 0-day 발견 시 즉시 표적: 우리가 쓰는 프레임워크나 라이브러리에서 새 취약점이 공개되면, 그 순간 노출된 모든 관리자 페이지가 자동 스캔 대상이 됩니다
비밀번호를 아무리 잘 걸어도 로그인 폼 자체에 결함이 생기면 그 순간 뚫립니다. 그 결함은 우리 코드가 아니라 우리가 쓴 프레임워크 안에 있을 수도 있어요. 관리자 페이지를 그냥 외부에 노출해 두는 것 자체가 사고를 기다리는 일입니다.
AI에게 시킬 프롬프트:
이 프로젝트에서 관리자 페이지가 어디 있는지 찾아줘. 그 페이지가 외부 인터넷에 노출되어 있는지, 노출되어 있다면 어떤 공격이 들어올 수 있는지, 제대로 막혀져 있는지, 어떻게 막아야 하는지 점검해줘.
법적 위험: 관리자 페이지가 뚫리면 웹 서비스는 거의 모든 정보가 해킹당한 것이라 볼 수 있습니다. 정보통신망법, 개인정보보호법, 약관 위반 등 모든 법적 책임이 한꺼번에 몰려올 수 있습니다. 피해 규모에 따라서는 형사 처벌까지 이어질 수 있습니다.
3. 에러 메시지가 외부로 그대로 새어 나감
증상: 사이트에서 무언가 실패했을 때 화면이나 API 응답 본문에 ValidationError: ..., PrismaClientKnownRequestError: ..., Cannot read properties of undefined 같은 메시지가 그대로 나타납니다. 비밀번호나 환경 변수가 직접 보이지는 않지만, 에러 종류 이름과 짧은 설명이 그대로 노출됩니다.
왜 일어나는지: 요즘 AI는 비밀번호나 환경 변수를 화면에 그대로 토해내는 디버그 화면을 만들지는 않습니다. 다만 에러 처리는 꼼꼼히 짜지 않아서, 에러 종류 이름과 메시지가 사용자 화면이나 API 응답 본문에 그대로 흘러나가는 경우는 여전히 흔합니다. 사람들은 "비밀번호도 아닌데 그게 뭐 어때서"라고 생각합니다.
문제는 공격자가 그 짧은 메시지 한 줄에서 다음을 알아낸다는 점이에요. 이걸 정보보안에서는 정보 수집(Reconnaissance) 또는 핑거프린팅(Fingerprinting) 이라고 부릅니다.
공격자는 처음부터 큰 공격을 하지 않습니다. 작은 메시지를 모아 표적의 프로파일을 만들고, 그다음에 그 프로파일에 맞는 공격을 정조준해서 보냅니다. 에러 메시지를 외부로 흘리는 건 그 첫 단추를 공격자에게 무료로 넘기는 일입니다.
AI에게 시킬 프롬프트:
이 프로젝트에서 에러가 발생했을 때, 에러 메시지가 사용자 화면이나 API 응답 본문에 그대로 노출되는 자리가 있는지 점검해줘. 만약 있다면 어떤 정보가 노출되는지, 그 정보로 공격자가 무엇을 알아낼 수 있는지, 어떻게 막아야 하는지 알려줘.
법적 위험: 에러 메시지로 시스템 정보가 노출된 그 자체로 즉시 위법은 아니지만, 나중에 사고가 났을 때 "안전성 확보조치 의무 위반"의 과실 정도를 판단하는 근거가 됩니다.
4. 시크릿이 운영자의 손을 통해 새어 나감
증상: 깃허브에서 우리 도메인이나 서비스명으로 검색했더니 .env 내용이 그대로 떠 있습니다. 또는 사이트 자바스크립트 번들에서 누군가 sk-... 같은 키를 발견해 트위터에 공유합니다.
왜 일어나는지: 요즘 AI는 .env를 public 폴더에 두거나 const API_KEY = "sk-..."처럼 키를 코드에 직접 입력하는 실수는 거의 하지 않습니다. 키가 새는 자리는 이제 대부분 운영자(우리 자신)의 손에서 만들어집니다.
.env를 깃에 푸쉬한 사고:.gitignore에 한 줄이 빠져 있거나, 다른 위치에 백업본(env.txt,.env.local.bak)을 만들어 두면 그대로 따라갑니다. 깃허브의 모든 push는 봇이 5분 안에 스캔하고, 한 번 푸쉬하면git rm으로 지워도 늦습니다.- 블로그 등에 키 복붙: 예제 코드의 빈 자리에 자기 키를 적어 그대로 운영에 올리는 경우.
- AI에게 디버깅 도와달라고 키를 그대로 붙여 보내기: 그 대화 로그가 어디로 흘러가는지 알 수 없습니다.
이 중 압도적으로 많은 건 깃 푸쉬입니다. 이미 올렸다면 누군가가 키를 가져간 뒤일 가능성이 큽니다.
AI에게 시킬 프롬프트:
이 프로젝트에서 API 키, DB 키, 결제 키 같은 시크릿이 운영자의 실수로 노출될 수 있는 자리가 있는지 점검해줘. 만약 있다면 어떤 식으로 노출되는지, 그 노출로 공격자가 무엇을 할 수 있는지, 어떻게 막아야 하는지 알려줘.
이미 push 해버렸다면
키를 즉시 무효화(revoke) 하는 것이 가장 먼저입니다. 깃 히스토리에서 지우는 건 그다음입니다. 순서가 반대면 안 됩니다.
- 해당 서비스 콘솔에 로그인해 그 키를 즉시 비활성화 (OpenAI, AWS, Stripe 모두 한 번 클릭)
- 새 키를 발급받아
.env에 넣기 - 그 다음에 깃 히스토리 정리 (필요하다면)
히스토리 지우는 것이 어렵다면 레파지토리를 새로 만들어도 됩니다. 깃 히스토리를 아무리 지워도, 이미 봇이 가져간 키가 살아있을 가능성을 배제할 수 없습니다.
법적 위험: 키 자체가 새는 순간은 금전 손해가 먼저 옵니다. 다만 그 키로 회원 DB나 결제 시스템, 클라우드 콘솔에 접근할 수 있다면 키 유출은 곧 개인정보 유출 사고로 번집니다. 그때부터는 개인정보보호법상 안전성 확보조치 의무 위반으로 과징금과 손해배상 책임이 따라옵니다. 시크릿 관리는 "기본적인 보안 조치"의 가장 첫 줄로 보기 때문에, 사고가 났을 때 과실이 매우 무겁게 잡힙니다.
5. 데이터베이스 안을 누구나 들여다볼 수 있음
증상: 사이트는 멀쩡해 보이는데, 누군가 브라우저 개발자 도구로 요청 한 번을 보내자 회원 전체 정보가 그대로 응답으로 돌아옵니다. 비밀번호 해시, 이메일, 전화번호까지요.
왜 일어나는지: AI에게 "회원 가입 만들어줘"라고 시키면 자주 추천하는 외부 서비스가 있습니다. Supabase, Firebase 같은 BaaS(Backend as a Service)입니다. 둘 다 "프론트엔드 코드에서 DB로 바로 요청을 보내는 구조"라 백엔드 서버를 따로 만들 필요가 없어 편한 대신, DB 쪽에 "누가 무엇을 볼 수 있는지"를 손수 설정해 두지 않으면 모든 데이터가 공개됩니다.
꼭 Supabase나 Firebase 같은 서비스가 아니더라도 권한이 없는 사용자가 비밀게시물을 F12를 통해 Network 탭에서 볼 수 있다거나 하는 사고도 같은 범주라고 보시면 됩니다.
AI에게 시킬 프롬프트:
이 프로젝트에서 데이터베이스에 접근하는 자리를 모두 찾아줘. 권한이 없는 사용자가 그 데이터에 접근할 수 있는지, 그 노출로 공격자가 무엇을 할 수 있는지, 어떻게 막아야 하는지 점검해줘.
법적 위험: 회원 전체 정보가 그대로 응답으로 돌아오는 것은 가장 전형적인 개인정보 유출 사고입니다. 개인정보보호법상 안전성 확보조치 의무 위반으로 매출액 기준 과징금 대상이고, 유출된 이용자 한 명 한 명에게 손해배상 책임이 생깁니다. 비밀번호 해시·주민등록번호·결제 정보처럼 민감한 항목이 함께 새면 형사 처벌까지 이어질 수 있습니다. 권한 설정을 안 한 것은 "몰랐다"로 면책되지 않습니다.
6. 임시 계정과 임시 비밀번호가 운영까지 따라감
증상: 운영 사이트의 관리자 계정 비밀번호가 여전히 changeme, TempPass123!, admin1234 같은 임시 비밀번호 그대로입니다. 또는 시드 파일에 적혀 있던 테스트 계정이 운영 DB에 그대로 살아 있고, 그 계정으로 로그인이 됩니다.
왜 일어나는지: 요즘 AI는 admin / admin 같은 노골적인 시드 계정은 잘 만들지 않습니다. 대신 다음 패턴이 자주 보입니다. 특히 README.md나 시드 파일에 "관리자 계정: admin / TempPass123!" 같은 식으로 적어 두는 경우가 많습니다.
봇은 사이트가 떠 있는 걸 보면 흔한 아이디·비밀번호 조합 수백 개를 1초 안에 시도합니다. 그 목록에 TempPass123!, Welcome2024!, Changeme1! 같은 "임시 비번 패턴"이 다 들어 있어요. AI가 추천하는 임시 비번은 봇의 사전에도 이미 들어가 있다고 봐야 합니다.
AI에게 시킬 프롬프트:
이 프로젝트에서 운영 사이트에 남아 있는 임시 계정이나 임시 비밀번호가 있는지 점검해줘. 만약 있다면 그 계정을 어떻게 삭제할 수 있는지, 내가 어떻게 새로 만들어야 하는지 알려줘.
법적 위험: 임시 비밀번호를 그대로 운영에 띄워두는 것은 안전성 확보조치 의무 위반의 전형적인 사례입니다. 사고가 나기 전에는 즉시 처벌받지 않지만, 그 계정으로 뚫려 정보가 유출되는 순간 "기본적인 비밀번호 관리도 하지 않았다"는 과실이 그대로 잡힙니다. 과징금 산정에서는 가중 사유가 되고, 책임 분쟁에서 운영자 측에 거의 모든 책임이 돌아갑니다.
7. HTTPS
배포할 때 도메인 앞에 https://가 붙어 있는지 확인하세요. http://(s 없음)는 모든 통신이 평문입니다. 같은 카페 와이파이에 앉아 있는 사람이 우리 사용자가 보내는 비밀번호를 그대로 볼 수 있습니다.
다행히 요즘은 거의 모든 배포 환경(Vercel, Netlify, Cloudflare Pages, Railway, Render)이 자동으로 HTTPS를 켜 줍니다. 따로 설정할 게 없습니다.
서비스를 띄운 직후 브라우저 주소창에 http://내도메인.com(s 없이)을 직접 쳐 보세요. 자동으로 https://로 리디렉트되어야 정상입니다. 안 되면 AI에게 "HTTP 요청을 HTTPS로 강제 리디렉트하도록 설정해줘"라고 한 줄 더 시키세요.
법적 위험: 평문 HTTP로 비밀번호나 개인정보를 주고받는 것은 개인정보보호법이 정한 "송수신 시 암호화" 의무 위반입니다. 도청 사고가 실제로 일어나지 않아도 의무 위반 자체로 시정명령과 과태료 대상이 됩니다. 사고가 났을 때는 "전송 단계부터 암호화하지 않았다"는 점이 명백한 과실로 잡혀, 안전성 확보조치 의무 위반의 가중 사유가 됩니다.