바이브코딩의 위험성 ① — 어제는 분명히 괜찮았다
AI에게 코드를 맡기는 시대, 우리는 어떤 안전망을 가지고 있을까? 한 번의 자동화가 30개 테이블을 날릴 뻔한 이야기. — 시리즈 1편 / 사건 발견과 추적
평범한 아침, 작은 위화감
오늘 아침 관리자 화면에 접속했더니 몇몇 메뉴가 비어 있었다. SEO 설정, 재무 거래내역, 호스팅 생성 로그. 그리고 발송 로그도. 처음에는 단순히 "아직 데이터를 안 채워서 그런가 보다" 싶었다. 신규 기능 위주의 메뉴들이라서 그럴 만도 했다.
그런데 이상했다. 며칠 전 분명히 본 적이 있는 데이터들이었다. 이게 왜 비어 있지?
처음 떠올린 가설은 단순했다.
eondcms는 Rhymix(
xe_*테이블)를 그대로 쓰면서 신규 기능은eond_*테이블에 적재하는 구조다. 신규 테이블이 새로 만들어진 거라, 이전 데이터가 없는 게 자연스럽다.
깔끔한 설명이었다. 그런데 깔끔한 설명일수록 의심해야 한다는 걸, 8년 프리랜서 생활이 가르쳐준 본능이 있었다.
"원래 있었다"는 증언
테이블 행 수를 직접 세어 봤다.
eond_site— 4개 행. SEO는 사이트별로 채우면 되는 정상 상태.eond_bank_transactions— 0개. 이전엔 있었다.eond_hosting_setup_log— 0개. 이것도 있었다.
"원래 있었다"는 기억이 옳다면, 신규 테이블 가설은 무너진다. 데이터가 사라진 것이다.
이쯤에서 가장 먼저 점검하는 건 MySQL의 binlog. 점-시간 복구(point-in-time recovery)가 가능한 유일한 안전망이다.
SHOW VARIABLES LIKE 'log_bin';OFF.
이 한 줄로 모든 복구 옵션이 사라졌다. 백업 디렉터리도 비어 있었다. 추적할 수 있는 흔적이 통째로 사라진 셈이다.
어제는 정상이었다
다행인지 불행인지, 사라진 건 "단순 로그 정도"였다. 글, 회원, 댓글, 파일 같은 핵심 데이터는 멀쩡했다. 다시 채워 넣으면 되는 수준. 그렇다고 그냥 넘어갈 일은 아니었다. 이런 사고는 다음에도 일어날 수 있고, 다음엔 운이 안 좋을 수도 있으니까.
추적의 단서를 찾기 위해 시점부터 좁혔다.
어제는 괜찮았던 걸로 기억함
이 한 줄이 결정적이었다. 어제까지 정상이었고, 오늘 사라졌다. 그렇다면 그 사이에 누군가 무엇을 했다.
git log를 펼쳤다.
efd252f 2026-04-28 14:51:03 feat: major update — inquiry-to-project flow,
notification logging, market price,
xe_ table integration
오늘 오후 2시 51분에 거대한 커밋이 하나 들어가 있었다. "major update"라는 말이 이미 의심스러웠지만, 그보다 눈에 띈 건 변경된 파일 수였다. 모델 추가, 라우터 추가, 서비스 추가, 마이그레이션 파일들 — 그중에서 한 줄이 유독 튀었다.
1091 +++ alembic/versions/a6ae466f8b07_add_random_order_to_board_config.py
마이그레이션 파일 하나가 1091줄. 게다가 이름은 "board_config에 random_order 추가". 컬럼 하나 추가하는 데 1091줄?
이름과 다른 내용
파일을 열어봤다.
"""add_random_order_to_board_config
Revision ID: a6ae466f8b07
Create Date: 2026-04-27 16:36:16.654089
"""
def upgrade() -> None:
op.create_table('eond_hosting_plan', ...)
op.drop_table('eond_project_quote_items')
op.drop_table('eond_outreach_template')
op.drop_table('eond_notification_log')
op.drop_table('eond_marketing_activity')
...이름은 컬럼 추가인데, 내용은 30개가 넘는 테이블을 DROP하는 코드였다. 사라진 테이블 목록을 훑어보니 정확히 오늘 사라진 데이터들이 거기에 있었다.
eond_bank_transactions(재무 거래내역) ✓eond_hosting_setup_log(호스팅 생성 로그) ✓eond_clients(고객 관리) ✓eond_audit_log,eond_blog_posts,eond_member_login_logeond_marketing_*시리즈 거의 전부eond_newsletter_*,eond_post_seo,eond_board_seoeond_publish_queue,eond_writing_material,eond_wiki_pages- ...
범인을 찾았다고 생각했다. 어제(4/27 16:36) 만들어진 이 파일이, 오늘 배포(4/28 14:51) 시점에 production에서 실행되며 데이터를 다 날려버렸다고. 시간 순서도 완벽하게 맞아떨어졌다.
그런데 정말 그랬을까?
결정적 한 줄
확신을 굳히기 전에 production에서 alembic 상태를 확인했다.
$ alembic current
c3d4e5f6a1b2이 한 줄이 모든 추리를 뒤집었다.
c3d4e5f6a1b2는 폭탄
마이그레이션(a6ae466f8b07)의 바로 직전
단계였다. 즉 production은 아직 폭탄을 실행하지 않은 상태였다. 1091줄의
DROP 문은 production DB에 한 줄도 닿지 않았다.
그렇다면 오늘 비어버린 데이터는 누가 지웠나? 솔직히 말하자면 — 모른다. binlog가 꺼져 있어서 추적할 흔적이 없다. 어쩌면 어떤 수동 작업, 어쩌면 다른 환경과의 혼동, 어쩌면 우리가 모르는 어떤 reset 스크립트의 흔적. 영원히 미궁이다.
하지만 진짜 무서운 건 그게 아니다. 폭탄은 아직 안 터졌을 뿐,
신관은 빠져 있는 상태로 차에 실려 있다는 것. 다음 배포 때 누가
무심코 alembic upgrade head를 누르는 순간, 그제서야 30개
테이블이 진짜로 사라진다. 이번엔 운 좋게 발견했지만, 발견하지
못했다면?
이 시점부터 작업의 성격이 바뀌었다. 사고 조사가 아니라 사고 예방으로.
다음 편 — ② 범인은 autogenerate였다 — 폭탄 마이그레이션 해체
첫 번째 댓글을 작성해 보세요.