happy_various AI 실전 기록

2026년 9월 14일 기준

이 글에는 제휴 링크가 없습니다. 삽화는 GPT 이미지 생성, 표는 직접 제작했습니다.

바이브 코딩의 한계 — AI가 짠 자동화가 실전에서 깨진 다섯 장면

택배 앱에 “배송 완료” 문자가 왔습니다. 현관에 나가 보니 상자가 없어요. 기사님은 거짓말을 한 게 아닙니다. 자기 화면에서는 완료였으니까요. 문제는 그 화면과 내 현관 사이에 아무도 서 있지 않았다는 것입니다.

이번 주 제 블로그 자동화가 정확히 이 방식으로 다섯 번 깨졌습니다. 코드는 매번 “완료”라고 말했고, 결과물은 없었어요. 이 시스템은 전부 AI에게 짜게 한 것이라 — 이른바 바이브 코딩 — 그 한계가 어디에 있는지 몸으로 배운 한 주였습니다. 다섯 장면을 날짜와 함께 그대로 적습니다.

배송 완료 문자를 자신 있게 보내는 로봇과, 비어 있는 상자 (GPT 이미지 생성)

결론 요약

장면 1 — 카드뉴스가 다섯 장 “완료”됐는데 한 장도 안 그렸다 (9월 10일)

인스타용 카드뉴스를 만드는 스크립트가 있습니다. HTML을 그려서 브라우저로 스크린샷을 찍죠. 이날 결과는 완료: 5장. 그런데 카드가 이전 글 것이었습니다.

원인은 두 겹이었습니다. 브라우저에 다른 창이 떠 있으면 스크린샷 명령이 그 창에 주소만 넘기고 조용히 끝납니다 — 오류 코드 0. 그리고 스크립트는 “PNG 파일이 있으면 성공”으로 판단했는데, 지난번 실행의 PNG가 그대로 남아 있었어요. 그리지 않은 카드를 성공으로 센 겁니다.

고친 건 한 줄입니다. 찍기 전에 기존 파일을 지웁니다.

out.unlink(missing_ok=True)   # 이전 실행의 PNG를 남겨두면 실패가 성공으로 보인다

“파일이 있다”와 “이번에 만들었다”는 다른 말입니다. AI는 전자를 검사했고, 제가 원한 건 후자였어요.

장면 2 — 실패한 글이 영영 재시도되지 않았다 (9월 11일)

매일 아침 9시에 예약된 글을 내보내는 릴리스 큐가 있습니다. 문서에는 이렇게 적혀 있었습니다. “실패한 항목은 건너뛰고 다음 날 다시 시도한다.”

코드는 반대로 돼 있었습니다. 예정일을 == 오늘로 비교하고 있었거든요. 어제 실패한 글은 예정일이 어제니까 오늘은 대상이 아닙니다. 내일도, 모레도요. 한 번 실패하면 영영 묶이는 구조였고, 실제로 인스타 게시 하나가 그렇게 이틀을 묶여 있었습니다.

# 전: str(sched.get("instagram", ""))[:10] == today
# 후: 예정일이 오늘이거나 이미 지났으면 대상
return bool(d) and d <= today

문서와 코드가 다를 때 믿어야 하는 건 코드입니다. AI가 쓴 문서는 의도를 적고, AI가 쓴 코드는 정상 경로를 적습니다. 그 둘 사이가 벌어진 자리에 실패가 고입니다.

장면 3 — 어제 열어둔 탭 때문에 오늘 글이 죽었다 (9월 12일)

네이버 블로그 발행은 브라우저의 에디터 탭에 글을 타이핑하는 방식입니다. 스크립트는 “이미 열린 에디터 탭이 있으면 그걸 쓴다”고 돼 있었어요. 합리적이죠.

그런데 그 탭은 어제부터 로딩 스피너에서 멈춰 있었고, 그 위에 네트워크 오류 팝업까지 쌓여 있었습니다. 스크립트는 상태를 보지 않고 탭을 집었고, 문단이 하나도 없는 화면에서 첫 문단을 클릭하려다 죽었습니다. 글 하나가 하루 밀렸습니다.

거울 속 어제 풍경을 보며 오늘 날씨를 보고하는 로봇 (GPT 이미지 생성)

고친 방식은 “열려 있는가”가 아니라 “쓸 수 있는가”를 확인하는 것이었습니다. 문단이 보이고, 클릭을 가로채는 반투명 막이 없을 때만 준비 완료로 칩니다. 아니면 새로고침, 그래도 안 되면 닫고 새로 엽니다.

page.wait_for_selector(".se-text-paragraph", timeout=15000)   # 문단이 실제로 보일 때까지
return not page.query_selector(".se-popup-dim")               # 막이 덮여 있으면 아직 아니다

장면 4 — 같은 사진을 두 번 받았다 (9월 13일)

구글 포토에서 사진을 내려받는 수집기를 만들었습니다. 사진 주소로 이동한 뒤 화면에 뜬 이미지를 받는 구조인데, 첫 시험에서 여섯 장 중 두 쌍이 똑같은 파일이었습니다.

구글 포토는 주소를 바꿔도 이전 사진이 화면에 잠깐 남아 있습니다. 그 틈에 읽으면 앞 사진을 그대로 집습니다. 주소는 바뀌었으니 코드 입장에선 “이동 완료”예요.

for _ in range(20):                      # 이전과 다른 이미지가 나타날 때까지 기다린다
    fife = page.evaluate(BIGGEST_FIFE)
    if fife and fife.split("=")[0] != prev_base:
        break
    page.wait_for_timeout(600)

주소가 바뀌었다고 화면이 바뀐 건 아닙니다. 화면이 바뀌었는지는 내용으로 확인해야 했어요.

장면 5 — 아이콘은 눌렸는데 메뉴가 안 열렸다 (9월 14일)

인스타그램 게시 스크립트는 계정을 바꿀 때 설정 아이콘을 누르고 “계정 전환”을 찾습니다. 이날 아이콘은 정상적으로 눌렸습니다 — 클릭 명령은 성공 — 그런데 메뉴가 열리지 않았어요. 화면이 바뀐 겁니다. 스크립트는 열리지 않은 메뉴에서 “계정 전환”을 찾다가 시간을 다 썼습니다.

고친 건 “눌렀는가”가 아니라 “열렸는가”를 확인하는 것이었습니다. 대화상자가 실제로 화면에 있는지 보고, 없으면 다른 경로로 한 번 더 시도합니다.

page.get_by_role("button", name="전환").first.click()
page.wait_for_timeout(3500)
if page.locator('div[role="dialog"]').count():   # 대화상자가 떴을 때만 성공
    return True

다섯 장면의 공통점

날짜코드가 말한 것실제로 있던 것
9/10카드 5장 완료지난번 카드 5장
9/11오늘 몫 없음어제 실패한 글 1건
9/12에디터 탭 있음멈춘 탭 + 오류 팝업
9/13사진 6장 저장4장 + 중복 2장
9/14아이콘 클릭 성공열리지 않은 메뉴

다섯 장면 — 코드가 말한 것과 실제로 있던 것 (직접 제작)

전부 오류 없이 끝났습니다. 그래서 무섭습니다. 오류가 나면 고치면 되는데, 오류가 안 나면 며칠 뒤에 “어, 이거 왜 안 올라갔지”로 발견하거든요.

깨진 자리도 같습니다. 어제의 잔재(남은 파일, 멈춘 탭, 지난 예정일), 바뀐 화면(SPA의 잔상, 달라진 메뉴), 한 번의 실패 이후. AI는 “처음 실행, 깨끗한 상태, 화면은 그대로”를 전제로 코드를 짭니다. 그 전제가 무너지는 건 둘째 날부터예요.

그래서 바이브 코딩은 쓰면 안 되나

아니요. 이 다섯 건이 깨진 시스템 자체가 전부 바이브 코딩으로 만든 것입니다. 네이버·인스타 발행, 사진 수집, 매일 아침 릴리스까지 사람이 코드를 한 줄도 안 쳤어요. 그게 돌아갑니다.

한계는 “못 만든다”가 아니라 “만들고 난 뒤 깨지는 방식이 사람 코드와 다르다”는 데 있습니다. 사람은 삽질을 겪은 자리에 방어 코드를 넣습니다. AI는 삽질을 겪지 않았으니 넣을 이유가 없어요. 낙관적으로 짭니다. 그 낙관을 메우는 게 쓰는 사람 몫입니다.

체크리스트 대신 선반을 직접 만져 확인하는 사람과 로봇 (GPT 이미지 생성)

대비법 셋 — 코드를 못 읽어도 시킬 수 있는 것

AI에게 자동화를 시킬 때 아래 세 문장을 같이 넣으세요. 다섯 장면이 전부 이 셋 중 하나로 막힙니다.

이 셋은 코드를 읽을 줄 몰라도 시킬 수 있는 말입니다. 그리고 AI는 이런 요구를 받으면 꽤 잘 넣어요. 문제는 시키지 않으면 안 넣는다는 것뿐입니다.

정리

바이브 코딩이 무엇인지부터 보시려면 바이브 코딩이 뭐길래를, 이 시스템에 검증을 넣게 된 첫 사고는 AI 검증 자동화 — 사고 한 번 나고 배운 것에서 이어 볼 수 있습니다.

이 글에는 제휴 링크가 없습니다. 삽화는 GPT 이미지 생성, 표는 직접 제작했습니다. 다섯 장면은 2026년 9월 10일~14일 이 블로그 저장소의 커밋 기록 기준입니다.