본문 바로가기
성공지식백과 로고성공지식백과

바이브 코딩 보안 가이드: 앱 배포 전 점검과 중단 기준

AI로 만든 앱의 로그인, Supabase 권한, 비밀 키, HTML 출력, 의존성 설치를 점검합니다. 확인할 파일과 설정, 허용돼야 할 요청과 배포를 멈출 결과를 구분했습니다.

바이브 코딩보안SupabaseRLS의존성 관리기술부채
글 정성준 12분 읽기
공유:

바이브 코딩으로 만든 앱의 배포 전 보안 점검은 실제 요청에서 권한과 데이터 경계가 지켜지는지 확인하는 작업입니다. 다른 계정의 비공개 데이터가 읽히거나 바뀌고, 브라우저에서 비밀 키를 얻을 수 있거나, 외부 입력이 검증 없이 HTML로 삽입된다면 해당 경로를 닫고 배포를 보류합니다.

로그인과 데이터베이스, 외부 API를 연결한 웹앱이 대상입니다. 기준 자료는 2026년 10월 15일 확인한 OWASP·Supabase·PostgreSQL·React·npm 공식 문서와 사고 조사 보고서입니다. 아래 검사와 코드는 테스트 환경에서 적용할 설명용 예시이며, 특정 앱에서 직접 실행한 보안 실험 결과는 없습니다.

테스트 계정과 허용 범위부터 정하기

사용자 A와 B의 테스트 계정을 만들고 각 계정에 가짜 데이터를 넣습니다. OWASP 인가 지침은 사용자 유형·자원·작업별로 허용할 권한을 정하고, 실제 요청에서 그 권한이 지켜지는지 검사하도록 권고합니다.

다음 표는 개인 메모 앱의 판정 예시입니다. 팀 공유 앱이라면 소유자 한 명 대신 실제 조직·팀 멤버십과 역할을 기준으로 허용표를 다시 작성합니다.

요청 주체대상과 작업기대 결과배포를 멈출 결과
비로그인 방문자사용자 A의 비공개 메모 읽기메모 내용이 반환되지 않음본문이나 비공개 필드가 반환됨
사용자 A자신의 메모 읽기·수정·삭제허용한 작업만 성공허용한 작업이 실패하거나 다른 사람의 데이터까지 반환됨
사용자 BA의 메모 ID로 읽기·수정·삭제내용이 보이지 않고 원래 데이터가 유지됨A의 메모가 보이거나 실제로 변경·삭제됨
일반 사용자관리자 전용 작업 요청서버에서 차단버튼을 숨겼지만 API 직접 요청은 성공

점검은 소유하거나 허가받은 테스트 환경에서 수행합니다. 관리자 키나 postgres 역할로 실행한 결과는 일반 사용자의 권한 검사에서 제외하고, 브라우저와 앱이 실제로 보내는 사용자 세션으로 확인합니다.

로그인과 객체 접근 권한을 따로 검사하기

로그인 검사는 요청자가 누구인지 확인합니다. 인가 검사는 그 사람이 해당 메모·주문·파일을 읽거나 바꿀 권한까지 확인하며, OWASP의 요청별 권한 검사 원칙은 이 판단을 서버 측에서 매 요청에 적용하도록 요구합니다.

사용자 B의 세션으로 A의 객체 ID를 지정해 API를 호출합니다. 목록에서 A의 자료가 안 보이더라도 상세 조회, 수정, 삭제 요청이 각각 차단되는지 확인합니다. 서버는 확인한 사용자 신원과 데이터의 소유자·조직 관계를 대조하고, 요청 본문의 owner_id나 role만 믿고 권한을 부여하지 않습니다.

응답의 상태코드와 본문, 실제 저장 결과를 함께 봅니다. Supabase RLS 테스트 문서는 정책에 따라 조회 결과나 변경 대상이 0행이 되는 예시를 제시합니다. HTTP 200만 보고 접근 성공으로 판단하지 않고, 소유자 계정으로 다시 읽어 원본이 유지됐는지 확인합니다.

외부 유료 API를 대신 호출하는 서버도 점검 대상입니다. 로그인한 호출자라도 다른 사람의 자원에 접근하거나 정해 둔 사용량을 넘겨 비용을 발생시키지 못하도록 검사합니다. Supabase API 보안 문서는 사용자·IP별 요청 제한과 할당량·결제 조건 검사를 RLS 밖에서도 필요한 항목으로 다룹니다. 허용량은 서비스의 비용과 사용 방식에 맞춰 정합니다.

Supabase의 공개 범위와 RLS 확인하기

Supabase에서는 Data API에 노출한 스키마, 테이블의 GRANT, RLS 활성화 여부와 정책을 함께 확인합니다. Supabase의 Data API 보안 문서는 역할의 객체 접근을 결정하는 GRANT와 접근할 행을 제한하는 RLS를 구분합니다.

대시보드의 Data API 설정, Table Editor, Database > Policies, Security Advisor에서 실제 노출과 정책 상태를 확인합니다. anon과 authenticated에 허용한 읽기·추가·수정·삭제 권한을 나눠 적습니다. 테이블이 API로 노출돼 있고 비공개 데이터에 대한 행 제한을 설명할 수 없다면, 공개를 보류하고 필요한 권한부터 다시 정합니다.

공개 공지와 개인 데이터의 정책 구분

USING (true)는 정책이 적용되는 테이블·작업·역할에서 모든 행이 조건을 통과하게 합니다. Supabase의 공개 공지 예시에도 이 조건이 있으며, 누구나 읽도록 만든 공지의 조회 정책에는 맞을 수 있습니다. 비공개 메모를 모든 로그인 사용자에게 보여 주는 정책이라면 허용 범위가 어긋납니다.

개인 소유 데이터의 조회 조건은 TO authenticated와 (select auth.uid()) = owner_id처럼 로그인 역할과 소유자를 함께 검사하는 형태로 읽을 수 있습니다. 여기서 owner_id는 해당 서비스의 실제 UUID 소유자 열이어야 하며, RLS 활성화·테이블 권한·같이 적용되는 다른 정책도 확인합니다. 이 조회 조건만으로 추가·수정·삭제 권한까지 검증되지는 않습니다.

UPDATE에서는 기존 행에 적용하는 USING과 수정 후 행에 적용하는 WITH CHECK의 조건을 나눠 봅니다. PostgreSQL의 CREATE POLICY 문서에 따르면 UPDATE나 ALL 정책에서 WITH CHECK를 생략하면 USING 조건을 새 행에도 사용합니다. 생략 여부만 보고 취약점을 판정하지 않고, 소유자 변경 요청이 서비스의 권한 규칙대로 차단되는지 검사합니다.

테이블을 읽는 뷰, RPC로 호출하는 함수, Storage 파일도 확인 대상에 넣습니다. Supabase RLS 문서는 뷰와 SECURITY DEFINER 함수가 실행하는 권한, 사용자가 고칠 수 있는 user_metadata, JWT 갱신 전까지 남는 권한 정보의 조건을 설명합니다. 뷰나 함수로 다른 접근 경로가 열리는지 일반 사용자 세션으로 다시 요청하고, user_metadata를 관리자 판정에 쓰지 않습니다. JWT로 팀 권한을 판단한다면 멤버십 변경이 토큰 갱신 전에도 요구대로 반영되는지 별도로 확인합니다.

기본값과 사고 사례를 그대로 적용하지 않기

테이블이 public에 있다는 사실만으로 공개 범위를 결정할 수는 없습니다. 2026년 10월 15일 기준 Supabase의 자동 권한 변경 공지는 새 프로젝트에 5월 30일부터 단계 적용하고, 기존 프로젝트 전체에는 10월 30일 적용할 예정이라고 설명합니다. 기존 프로젝트는 먼저 전환할 수 있지만 기존 테이블의 권한은 유지됩니다. 바뀌는 것은 적용 뒤 public에 만드는 새 테이블의 Data API 접근용 기본 GRANT이며, 직접 Postgres 연결에는 이 변경이 적용되지 않습니다.

Wiz가 2월 2일 공개한 Moltbook 조사에서는 잘못된 Supabase 접근 제어로 약 150만 개의 API 인증 토큰과 3만 5,000개 이메일 주소 등에 접근할 수 있었다고 보고했습니다. 조사팀은 읽기를 제한한 뒤에도 남은 쓰기 권한을 찾아 추가 수정을 요청했습니다. 이는 조사팀이 확인한 노출 범위이며, 모든 정보가 제3자에게 실제 탈취됐다는 확인과는 구분됩니다.

브라우저로 나가는 키의 종류 확인하기

키 이름에 API가 들어 있다는 이유만으로 모두 비밀은 아닙니다. Supabase API 키 문서는 공개 클라이언트에 넣는 키와 RLS를 우회하는 서버용 키를 구분합니다.

키 종류둘 수 있는 위치함께 확인할 조건
Supabase publishable, 기존 anon브라우저·모바일 등 공개 클라이언트노출 스키마, 테이블 권한, 사용자별 RLS 정책
Supabase secret, 기존 service_role관리하는 서버·함수 환경브라우저 유출 차단, 서버 자체의 호출자 인증과 인가
외부 유료 API의 비밀 키해당 공급자가 정한 비밀 저장 위치클라이언트 번들·응답·로그·저장소 이력의 노출 여부

sb_publishable_로 시작하는 키가 보이는 것만으로 유출 사고로 판정하지 않습니다. sb_secret_ 또는 service_role 키가 공개 코드나 응답에 들어 있다면 배포를 멈추고 노출 경로를 제거한 뒤 공급자 절차에 따라 키를 교체하거나 폐기합니다. 이미 노출된 키는 파일에서 지웠다는 이유로 다시 안전해지지 않습니다.

Next.js 환경변수 문서에 따르면 코드에서 process.env.NEXT_PUBLIC_변수명처럼 정적으로 참조한 값은 빌드할 때 브라우저용 JavaScript에 포함됩니다. 비밀 키를 .env에 옮겨도 이 방식으로 참조했다면 브라우저에 전달될 수 있습니다. 배포할 빌드의 번들과 네트워크 응답을 확인하고, 서버 전용 값도 응답이나 로그에 실어 보내지 않는지 봅니다.

일반 텍스트와 HTML 출력 경로 나누기

댓글이나 채팅 메시지를 글자로 보여 줄 때와 HTML 서식을 허용할 때는 처리 방식이 다릅니다. OWASP XSS 방어 지침은 출력 문맥에 맞는 인코딩과, HTML을 허용할 때의 정화를 구분합니다.

React의 일반 텍스트는 <p>{content}</p>처럼 출력합니다. 반면 React의 HTML 직접 삽입 문서는 신뢰하지 않는 내용을 dangerouslySetInnerHTML에 전달할 때 XSS 위험이 생긴다고 경고합니다. 코드에서 dangerouslySetInnerHTML과 innerHTML을 찾아 사용자 입력·외부 문서·AI 응답이 어디서 들어오는지 추적합니다.

HTML이 필요하면 허용할 태그와 속성을 정하고 DOMPurify 같은 HTML 정화 도구를 적용합니다. DOMPurify 사용 지침은 정화한 뒤 다른 문자열이나 라이브러리로 HTML을 바꾸면 보호 효과가 사라질 수 있다고 설명합니다. 서버에서 쓰는 경우에는 DOMPurify와 함께 사용하는 jsdom 등의 DOM 구현도 보안 업데이트를 확인합니다.

허용하지 않은 스크립트가 실행되거나, 외부 입력이 정화 없이 HTML로 들어가는 경로가 남으면 배포를 보류합니다. URL·HTML 속성·스크립트 문맥은 각각의 처리 규칙을 확인합니다. HTML 정화는 데이터 접근 권한이나 SQL 쿼리의 안전성을 검사하는 단계와도 분리합니다.

의존성 이름과 설치 과정 확인하기

새 의존성을 추가한 변경에서는 package.json과 lockfile을 함께 읽습니다. 패키지의 공식 프로젝트와 배포처, 정확한 이름, 내려받을 버전·출처, 설치 스크립트를 확인하고, 용도를 설명할 수 없는 패키지는 설치를 보류합니다. Unit 42의 바이브 코딩 보안 지침도 존재하지 않는 패키지를 제안하는 위험과 변경 검토의 필요성을 다룹니다.

npm ci 문서에 따르면 npm ci는 기존 package-lock.json이나 npm-shrinkwrap.json을 사용하고, 선언과 lockfile이 맞지 않으면 오류로 종료합니다. 설치 중 lockfile을 갱신하지 않으므로 package.json에 ^가 있다는 이유만으로 배포 때마다 새 버전을 받는다고 판단하지 않습니다. 검토한 lockfile을 저장소에 보관하고 실제 설치 명령도 확인합니다.

--ignore-scripts는 설치 시 패키지 스크립트 실행을 막는 옵션입니다. 필요한 빌드 단계가 멈출 수 있어 적용 후 호환성을 확인하며, npm run처럼 명시적으로 요청한 스크립트와 패키지의 런타임 코드는 별도로 검토합니다. 고정 설치와 스크립트 제한은 검토한 구성을 재현하고 실행을 줄이는 수단입니다. lockfile에 악성 버전이 들어 있으면 그 버전도 그대로 설치됩니다.

npm audit 문서의 검사 범위는 의존성과 알려진 보안 취약점 정보의 대조입니다. 통과 결과로 새 악성 코드, 서버의 인가 오류, 이전 실행에서 생긴 침해 흔적까지 없다고 판단할 수는 없습니다. 경고의 영향과 필요한 조치를 확인하고, 스캔 결과와 설치 기록을 따로 남깁니다.

Axios 사고에서 확인할 설치 조건

Axios 유지관리자의 사고 보고서에 따르면 2026년 3월 31일 배포된 악성 버전 1.14.1·0.30.4에는 plain-crypto-js@4.2.1이 추가됐습니다. 악성 버전은 약 3시간 동안 배포됐으며, 영향 조사에서는 해당 버전의 설치 여부와 설치 과정에서 코드가 실행됐는지를 확인합니다.

당시 lockfile과 설치 로그, CI 실행 기록에서 문제 버전의 사용 여부를 확인합니다. 문제 버전을 설치한 흔적이 있다면 실행 여부가 불명확하더라도 해당 장비나 CI 환경을 잠재 침해 대상으로 조사합니다. 패키지 교체에 더해 그 환경에 전달된 자격증명과 접근 기록도 사고 대응 범위에 넣습니다. 설치 여부 자체를 확인할 수 없는 의심 정황도 추가 조사 대상으로 남기며, 당시 복구 권고 버전을 새 프로젝트의 안전 버전으로 그대로 지정하지 않습니다.

오류 수정 뒤 권한과 유지보수 상태 검토하기

권한 오류를 고친 변경에서는 인증 검사를 지웠는지, RLS를 껐는지, 관리자 키로 호출을 바꿨는지 diff를 읽습니다. OWASP 인가 지침은 오류 처리 과정에서도 권한 검사가 우회되지 않도록 확인하고, 오류 응답에 내부 정보가 드러나지 않게 하도록 권고합니다. 정상 요청과 차단돼야 할 요청을 모두 다시 실행합니다.

기술부채 검토도 변경한 파일과 그 영향을 기준으로 진행합니다. AI 작성 커밋을 분석한 기술부채 연구의 10월 13일 개정판은 공개 GitHub 저장소에서 정적 분석 이슈가 남아 있는지를 추적했습니다. 코드 스멜과 보안 이슈는 별도로 집계했으며, 이 연구는 사람만 작성한 커밋과의 비교군이나 2년 뒤 유지비 배수를 제시하지 않습니다.

변경에서 발견한 상태확인할 영향남길 기록
같은 권한 검사 코드가 여러 곳에 존재일부 경로만 수정돼 다른 경로가 남는지검사하는 함수·API와 회귀 테스트
새 패키지 또는 하드코딩한 설정 추가설치 과정과 개발·운영 환경에 생기는 차이의존성 용도, 설정 위치, 변경 이유
오류를 무시하거나 정상 값으로 대체실패한 작업이 성공처럼 처리되거나 권한 검사를 건너뛰는지실패 조건, 응답, 저장 상태
수정한 함수의 호출 관계를 모름어떤 기능을 다시 검사할지 정할 수 있는지호출 위치와 담당자, 추가 검토 항목

앤트로픽(Anthropic)의 Trio 학습 실험에서는 새 라이브러리 과제를 수행한 뒤 AI 보조 집단의 이해도 점수가 대조군보다 낮았습니다. 관측 범위는 해당 학습 과제이며, 모든 개발자의 장기 실무 능력 저하로 확대할 수는 없습니다.

AI에게 검토를 요청할 때도 파일 위치와 허용·차단 조건을 적습니다. 다음은 개인 메모 앱을 검토하기 위한 요청 예시이며, 응답의 정확성이나 보안 개선 효과를 실험한 프롬프트는 아닙니다.

markdown복사
개인 메모 앱의 이번 변경을 검토합니다.
사용자는 자신의 메모만 읽고 수정하고 삭제할 수 있습니다.
비로그인 방문자와 다른 사용자의 요청은 비공개 데이터에 접근할 수 없습니다.

1. 이 권한을 검사하는 서버 코드와 데이터베이스 정책의 파일 위치를 적습니다.
2. 공개용 키와 비밀 키가 브라우저에 전달되는 경로를 각각 찾습니다.
3. HTML 직접 삽입과 새 의존성·설치 스크립트의 변경을 표시합니다.
4. 정상 요청과 차단 요청의 테스트를 제안하고 예상 결과를 나눠 적습니다.
5. 실행하지 않은 테스트와 확인하지 못한 조건을 표시합니다.

권한 오류를 없애기 위해 RLS나 인증 검사를 제거하지 않습니다.

검토자가 권한을 검사하는 위치와 실패했을 때의 영향을 설명할 수 없다면, 해당 기능의 공개를 보류하고 범위를 좁혀 다시 검토합니다. 코드 설명과 정적 분석 결과는 실제 요청의 허용·차단 검사와 함께 확인합니다.

검사 결과와 연구 수치의 범위 기록하기

검사 기록에는 배포할 커밋, 테스트 계정의 역할, 데이터·작업, 기대 결과, 실제 응답과 저장 상태를 남깁니다. 실행하지 않은 항목은 미실행으로 표시하고, 실패를 고쳤다면 같은 요청의 재검사 결과를 연결합니다. 키나 실제 개인정보 대신 테스트 데이터의 식별자를 사용합니다.

Veracode의 2025년 자체 시험은 100개가 넘는 모델에 4개 언어·4개 약점 유형으로 구성한 80개 함수 완성 과제를 주었습니다. 보안에 특화한 프롬프트를 쓰지 않았으며, 구문·컴파일 검사를 통과한 코드를 자체 정적 분석(SAST)으로 검사했습니다. 보고서의 평균 보안 검사 실패율은 약 45%, XSS 관련 과제의 실패율은 약 86%였습니다. 이 수치는 해당 시험의 결과이며, 배포할 앱의 취약 확률로 사용할 수 없습니다.

연구 수치는 어떤 검사를 준비할지 참고하는 자료입니다. 배포 판단에는 해당 앱의 접근 권한, 키 노출, 출력과 설치 경로에서 확인한 결과를 사용합니다. 이 점검을 통과한 범위와 별도 보안 검토가 필요한 범위를 나눠 기록하며, 체크리스트를 앱 전체의 안전 인증으로 표시하지 않습니다.

AI 개발과 보안 소식 받기

성공지식백과 뉴스레터에서 바이브 코딩, AI 보안, 생산성 도구 관련 내용을 전합니다.