개발 철학

바이브코딩의 위험성 ① — 어제는 분명히 괜찮았다

27
이온디
시리즈   다음 편 →

바이브코딩의 위험성 ① — 어제는 분명히 괜찮았다

AI에게 코드를 맡기는 시대, 우리는 어떤 안전망을 가지고 있을까? 한 번의 자동화가 30개 테이블을 날릴 뻔한 이야기. — 시리즈 1편 / 사건 발견과 추적

평범한 아침, 작은 위화감

오늘 아침 관리자 화면에 접속했더니 몇몇 메뉴가 비어 있었다. SEO 설정, 재무 거래내역, 호스팅 생성 로그. 그리고 발송 로그도. 처음에는 단순히 "아직 데이터를 안 채워서 그런가 보다" 싶었다. 신규 기능 위주의 메뉴들이라서 그럴 만도 했다.

그런데 이상했다. 며칠 전 분명히 본 적이 있는 데이터들이었다. 이게 왜 비어 있지?

처음 떠올린 가설은 단순했다.

eondcms는 Rhymix(xe_* 테이블)를 그대로 쓰면서 신규 기능은 eond_* 테이블에 적재하는 구조다. 신규 테이블이 새로 만들어진 거라, 이전 데이터가 없는 게 자연스럽다.

깔끔한 설명이었다. 그런데 깔끔한 설명일수록 의심해야 한다는 걸, 8년 프리랜서 생활이 가르쳐준 본능이 있었다.

"원래 있었다"는 증언

테이블 행 수를 직접 세어 봤다.

  • eond_site — 4개 행. SEO는 사이트별로 채우면 되는 정상 상태.
  • eond_bank_transactions0개. 이전엔 있었다.
  • eond_hosting_setup_log0개. 이것도 있었다.

"원래 있었다"는 기억이 옳다면, 신규 테이블 가설은 무너진다. 데이터가 사라진 것이다.

이쯤에서 가장 먼저 점검하는 건 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_log
  • eond_marketing_* 시리즈 거의 전부
  • eond_newsletter_*, eond_post_seo, eond_board_seo
  • eond_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였다 — 폭탄 마이그레이션 해체

#바이브코딩 #alembic #사고분석 #eondcms #개발철학

프로젝트를 함께 만들고 싶다면

지금 바로 문의해 보세요

댓글 0

첫 번째 댓글을 작성해 보세요.