바이브 코딩으로 만든 사내 도구, 개인정보를 넣기 전에 점검할 보안 설정

화면이 아니라 데이터베이스에서 막는 권한, 조직 명의 계정, 비밀 키 관리까지 배포 전 확인 순서

AI 코딩 도구에 요청만 하면 회원 관리 화면, 신청서 접수, 결재 흐름 같은 사내 도구가 하루 만에 만들어진다. 개발자가 따로 없는 작은 조직도 직접 시스템을 만들 수 있게 된 것이다. 하지만 만드는 일이 쉬워진 만큼 운영하는 일의 보안 난도가 내려간 것은 아니다. AI가 만들어 주는 것은 "요청한 대로 동작하는 화면"이고, 누가 어떤 데이터까지 볼 수 있는지는 요청하지 않으면 대개 빠져 있다. 이 글은 그렇게 만든 도구에 실제 이름·연락처·상담 기록 같은 개인정보를 넣기 전에 확인할 설정을 순서대로 정리한다.

로그인이 있다고 권한이 있는 것은 아니다

바이브 코딩으로 만든 도구에서 가장 흔한 착각은 "로그인해야 들어올 수 있으니 안전하다"는 것이다. 로그인(인증)은 사용자가 누구인지 확인할 뿐이고, 그 사용자가 어떤 행을 읽고 고칠 수 있는지(권한)는 별개의 문제다. OWASP Top 10:2025는 접근 제어 실패(Broken Access Control)를 여전히 1위로 두고, 테스트한 애플리케이션 전부에서 어떤 형태로든 발견됐다고 밝힌다. 대표 사례로 URL이나 파라미터를 바꿔 검사를 우회하는 경우, 다른 사람의 식별자를 넣어 그 계정 정보를 보는 경우(IDOR), 조회 화면만 막고 수정·삭제 API에는 검사가 없는 경우를 든다.

OWASP가 제시하는 원칙은 세 가지다. 공개 자원이 아니면 기본값은 거부로 두고, 검사는 사용자가 조작할 수 없는 서버 쪽 코드에서 하며, 레코드 소유권을 기준으로 읽기·수정을 허용한다. 화면에서 목록을 20건만 보여 주도록 만든 것은 이 중 어디에도 해당하지 않는다. 브라우저 개발자 도구로 API 응답을 열어 보면 전체 데이터가 그대로 내려오는 경우가 많다.

계층흔한 바이브 코딩 결과확인할 것
화면내 부서 데이터만 보이게 필터링필터는 편의 기능일 뿐, 보호 수단으로 세지 않는다
API로그인 여부만 확인요청한 레코드의 소유자·부서를 서버에서 다시 확인하는가
데이터베이스클라이언트가 직접 조회, 규칙 없음행 단위 정책(RLS, 보안 규칙)이 켜져 있는가
저장소·공유 설정시트·드라이브를 편집자로 공유도구 밖에서 원본 데이터를 누가 열 수 있는가

데이터베이스에서 행 단위로 막기

Supabase: 모든 노출 테이블에 RLS

AI 도구가 자주 고르는 Supabase는 브라우저가 공개 키로 데이터베이스 API를 직접 호출하는 구조다. Supabase RLS 문서는 노출된 스키마의 테이블에 RLS와 정책이 없으면, 그 테이블에 권한(grant)이 부여된 anon·authenticated 역할이 테이블을 읽고 쓸 수 있다고 설명하며, 노출 스키마의 모든 테이블에 RLS를 켜라고 권한다. RLS를 켜면 정책을 만들기 전까지 공개 키로는 아무 데이터도 조회되지 않는다.

-- 1) RLS 켜기
alter table public.applications enable row level security;

-- 2) 본인이 작성한 신청서만 조회 허용
create policy "applicants read own rows"
on public.applications for select
to authenticated
using ( (select auth.uid()) = user_id );

RLS를 우회하는 service_role 계열의 비밀 키는 브라우저 코드나 고객에게 노출하지 말라고 문서가 명시한다. AI가 "권한 오류가 나서 service key로 바꿨다"는 식으로 문제를 해결한 코드가 있다면, 그 키가 프런트엔드 번들에 들어갔는지부터 확인한다.

Firebase: 테스트 규칙을 그대로 배포하지 않기

Firebase 보안 규칙 문서는 클라이언트가 데이터에 직접 접근하는 구조에서 보안 규칙이 악의적 사용자를 막는 유일한 장치라고 강조한다. 또 앱을 배포하면 정식 출시 전이라도 공개적으로 접근 가능하다고 경고한다. 개발 중 쓰던 느슨한 규칙을 문서의 "콘텐츠 소유자만 접근" 형태로 바꾼 뒤 배포한다. 아래 예시는 규칙 파일의 일부이며, 실제로는 service cloud.firestore { match /databases/{database}/documents { … } } 블록 안에 넣어야 동작한다.

match /applications/{userId}/{document} {
  allow read, write: if request.auth != null && request.auth.uid == userId
}

부서장이 부서원 데이터를 봐야 하는 식의 역할 기반 규칙은 요구사항을 AI에게 문장으로 정확히 설명하고, 생성된 정책을 다른 계정으로 로그인해 직접 조회해 보는 방식으로 검증한다. 권한 범위를 설계하는 원칙은 MCP 서버 OAuth와 권한 관리 기초의 최소 권한 설명과 같은 맥락이다.

스프레드시트를 데이터베이스로 쓸 때의 빈틈

Google 시트에 데이터를 두고 Apps Script나 노코드 도구로 화면을 붙이는 구성도 흔하다. 이 경우 도구 화면에서 권한을 아무리 나눠도, 시트 자체를 편집자로 공유받은 직원은 원본 파일을 열어 모든 행을 보고 고칠 수 있다. 결재 도구라면 승인 상태 셀을 직접 바꿔 결재 절차를 건너뛸 수도 있다. 개인정보가 들어가는 순간부터는 다음을 확인한다.

  • 시트 공유 대상이 도구를 실행하는 서비스 계정이나 최소 인원으로 한정돼 있는가, "링크가 있는 모든 사용자" 공유가 꺼져 있는가
  • 결재·승인 기록처럼 고쳐지면 안 되는 데이터가 사람이 직접 편집할 수 있는 셀에 있지 않은가
  • 행 단위 권한이 필요해지면 시트가 아니라 RLS를 지원하는 데이터베이스로 옮길 시점인가

문서 단위 접근 제어를 검색 시스템에 반영하는 문제는 사내 문서용 폐쇄형 RAG의 접근 제어에서 같은 원리로 다룬다.

계정과 소유권은 조직 명의로

담당자 개인 Google 계정이나 개인 GitHub 계정으로 만든 도구는 데이터는 조직 것인데 통제권은 한 사람에게 있는 상태가 된다. 저장소, 데이터베이스 프로젝트, 도메인, 배포 서비스는 처음부터 조직 계정이나 조직 소유 공간에서 만든다. Google Workspace를 쓴다면 퇴사자 파일은 관리 콘솔의 소유권 이전 기능으로 옮기는데, 공식 안내에서 확인할 점이 있다.

  1. 이전 전에 기존 소유자 계정을 정지해 이전 중 새 파일을 만들거나 옮기지 못하게 한다.
  2. 관리 콘솔의 Drive 및 Docs 설정에서 소유권 이전을 실행한다.
  3. 휴지통에 있는 항목은 이전되지 않으며, 사용자를 삭제하면 이전되지 않은 휴지통 파일도 함께 삭제된다.
  4. 이전은 파일 접근 권한을 바꾸지 않는다. 기존 소유자도 계정이 삭제되기 전까지 편집할 수 있으므로 공유 목록을 따로 정리한다.

관리자 계정에는 다단계 인증을 켜고, 퇴사·전보 때 회수할 계정 목록(데이터베이스, 저장소, 배포, 시트 공유)을 도구마다 한 줄씩 적어 둔다.

비밀 키가 저장소와 AI 도구로 새지 않게

AI가 만든 코드는 API 키를 소스에 바로 적어 넣는 경우가 있다. GitHub 푸시 보호 문서에 따르면 사용자 단위 푸시 보호는 기본으로 켜져 있어 공개 저장소로 비밀 값을 푸시하는 것을 막는다. 반면 저장소 단위 푸시 보호는 기본으로 꺼져 있고 GitHub Secret Protection이 활성화돼야 쓸 수 있다. 비공개 저장소라고 안심하지 말고, 키는 .env에 두고 .gitignore에 넣으며, 한 번이라도 커밋된 키는 삭제가 아니라 재발급으로 처리한다.

AI 코딩 도구가 작업 중 .env를 읽어 대화에 싣는 것도 막아 둔다. Claude Code라면 permissions.deny에 Read(./.env) 규칙을 넣는 방법을 Claude Code 설정 글에서 다룬다. 테스트에는 실제 개인정보 대신 가짜 데이터를 쓴다.

실제 데이터를 넣기 전 확인 순서

  1. 도구에 들어갈 데이터 항목을 적고, 없어도 되는 항목(주민번호 전체, 상세 주소 등)은 수집하지 않도록 뺀다.
  2. 데이터베이스 모든 테이블에 행 단위 정책이 있는지 확인하고, 권한이 다른 두 계정으로 로그인해 서로의 데이터가 조회되지 않는지 직접 시험한다.
  3. 브라우저 개발자 도구에서 API 응답에 화면에 없는 데이터가 섞여 오지 않는지 본다.
  4. 시트·드라이브·저장소의 공유 대상과 링크 공유 설정을 확인한다.
  5. 저장소, 데이터베이스, 도메인, 배포 계정이 조직 소유인지 확인하고 관리자 계정에 다단계 인증을 켠다.
  6. 코드와 커밋 이력에 비밀 키가 없는지 확인하고 푸시 보호를 켠다.
  7. 백업이 있는지, 그 백업으로 실제 복구해 봤는지, 누가 언제 어떤 데이터를 조회·수정했는지 남는 기록이 있는지 확인한다.

급여, 인사 평가, 상담·건강 기록처럼 유출 피해가 큰 데이터를 다루는 시스템은 이 목록만으로 충분하지 않다. 운영 전에 보안 전문가의 검토를 받고, 개인정보 처리에 관한 법적 의무는 개인정보보호위원회 등 공식 안내를 따로 확인한다. AI가 만든 코드의 리뷰 기준은 AI 생성 코드 리뷰 규칙에서 이어서 다룬다.

핵심 요약

  • 로그인(인증)과 데이터 권한은 별개이며, 화면 필터링은 보호 수단이 아니다. 권한 검사는 서버나 데이터베이스에서 한다.
  • Supabase는 노출 스키마의 모든 테이블에 RLS를 켜고, RLS를 우회하는 service_role 키는 브라우저에 두지 않는다.
  • Firebase 앱은 정식 출시 전이라도 배포되면 공개 접근이 가능하므로, 배포 전에 소유자 기반 보안 규칙으로 바꾼다.
  • 시트를 편집자로 공유받은 사람은 도구의 권한 설정과 무관하게 원본 전체를 볼 수 있다.
  • 저장소·데이터베이스·도메인은 조직 명의로 만들고, 퇴사자 파일 이전 후 공유 목록을 따로 정리한다.

초보자가 자주 실수하는 포인트

  • 로그인 화면이 있으니 다른 사용자의 데이터도 보호된다고 생각하는 경우
  • 권한 오류를 없애려고 RLS를 끄거나 service_role 키를 프런트엔드 코드에 넣는 경우
  • 결재 상태나 승인 기록을 직원이 직접 편집할 수 있는 시트 셀에 두는 경우
  • 담당자 개인 계정으로 저장소와 데이터베이스를 만들어 퇴사 후 통제권을 잃는 경우

체크리스트

  • 권한이 다른 두 계정으로 서로의 데이터가 조회되지 않는지 직접 시험했는가
  • 데이터베이스 모든 테이블에 RLS 또는 보안 규칙이 적용돼 있는가
  • 시트·드라이브 링크 공유가 꺼져 있고 공유 대상이 최소 인원인가
  • 저장소·데이터베이스·배포 계정이 조직 소유이고 관리자 계정에 다단계 인증이 켜져 있는가
  • 코드와 커밋 이력에 비밀 키가 없고 푸시 보호가 켜져 있는가
  • 백업 복구를 실제로 시험했고 접근 기록이 남는가

자주 묻는 질문

AI에게 "보안에 신경 써서 만들어 줘"라고 요청하면 충분하지 않나요?

막연한 요청은 막연한 결과를 낳는다. "직원은 자기 신청서만, 부서장은 자기 부서 신청서만 조회"처럼 역할별 허용 범위를 문장으로 명시하고, 생성된 정책을 다른 계정으로 로그인해 직접 확인해야 한다.

비공개 저장소에 올린 API 키도 바꿔야 하나요?

커밋 이력에 남은 키는 파일을 지워도 이력에서 확인할 수 있고, 저장소 접근 권한이 있는 사람이나 연동된 서비스가 볼 수 있다. 한 번이라도 커밋된 키는 재발급해 기존 키를 폐기한다.

참고 자료 · 검증 기준

위 자료와 내용을 대조한 날짜: . 도구·서비스 정책은 이후 바뀔 수 있으므로 적용 전 공식 문서를 다시 확인하세요.

이 글은 위 참고 자료를 바탕으로 정리했으며, 내용은 운영 과정에서 순차적으로 보완될 수 있습니다.