<!doctype html>
2026년 7월 2일 | 바이브코딩 Tips
코딩 에이전트에게 버그 수정을 맡기면 가끔 애매한 초록불이 돌아온다. 코드도 바뀌었고 테스트도 바뀌었고 마지막 줄에는 통과가 찍혀 있다. 예전에는 그 조합을 보면 일단 안심했다. 그런데 몇 번 당하고 나니, 내가 먼저 봐야 할 곳은 초록불이 아니라 테스트 파일이 왜 같이 바뀌었는지라는 쪽에 가까웠다.
초록불보다 먼저 보는 파일 종류
테스트 수정 자체가 나쁜 것은 아니다. 버그를 재현하는 테스트를 새로 넣거나, 오래된 fixture를 실제 스펙에 맞게 고치는 일은 오히려 좋은 신호다. 문제는 에이전트가 실패를 없애기 위해 assertion을 약하게 만들거나, 경계값을 지우거나, 실패하던 케이스를 skip으로 돌리는 경우다. 이때는 통과 로그가 있어도 실제로는 검증 장치가 얇아졌을 수 있다.
그래서 나는 diff에 테스트 파일이 섞이면 먼저 파일을 두 묶음으로 나눈다. 하나는 실제 제품 코드, 다른 하나는 검증 코드다. 둘을 같은 변경량으로 보지 않는다. 제품 코드는 요구사항을 따라갔는지 보고, 테스트 코드는 그 요구사항을 더 선명하게 만들었는지 본다. 코드가 맞았는가와 테스트가 무엇을 묻도록 바뀌었는가를 분리하는 순간, 에이전트의 완료 보고를 훨씬 덜 믿고 더 잘 쓸 수 있다.
내가 나누는 세 가지 칸
요즘은 에이전트가 테스트까지 만졌을 때 세 칸만 빠르게 적어 본다. 첫째, 원래 실패가 무엇이었는지다. 예를 들어 빈 배열, 시간대, 한글 파일명, 권한 없음처럼 실패 입력이 구체적으로 남아 있어야 한다. 둘째, 테스트 diff가 그 실패 입력을 새로 고정했는지다. 새 assertion이 생겼다면 좋은 방향일 가능성이 크다. 반대로 기존 assertion이 느슨해졌다면 바로 멈춘다.
셋째, 구현 diff가 테스트 diff 없이도 설명되는지다. 테스트를 바꿔야만 통과하는 수정이라면, 그 테스트 변경이 스펙 변경인지 테스트 버그 수정인지 따로 이름을 붙여야 한다. 이 이름을 못 붙이면 나는 보통 `HOLD`로 둔다. 여기서 HOLD는 실패 판정이 아니라, 아직 같은 diff 안에서 계속 고치면 범위가 흐려진다는 표시다.
특히 pull request 요약만 보는 날에는 이 구분이 더 중요하다. 에이전트가 “테스트 업데이트 포함”이라고 짧게 적어 놓으면, 그 말은 너무 넓다. 새 실패 케이스를 추가했다는 뜻일 수도 있고, 기대값을 지금 구현에 맞춰 다시 썼다는 뜻일 수도 있다. 둘은 완전히 다르다. 전자는 버그를 다시 부르지 않게 해 주지만, 후자는 아직 합의되지 않은 동작을 사실처럼 굳힐 수 있다.
내가 보는 순서는 거의 고정돼 있다. 먼저 삭제된 assertion을 찾고, 그다음 skip이나 xfail 같은 우회 표시를 찾고, 마지막으로 기대값이 덜 구체적인 형태로 바뀌었는지 본다. 이 세 가지가 없고 새 입력이 늘었다면 대체로 좋은 테스트 수정이다. 반대로 세 가지 중 하나가 보이면 에이전트에게 구현 설명보다 테스트 설명을 먼저 요구한다.
좋은 테스트 수정과 위험한 테스트 수정
좋은 테스트 수정은 대체로 실패를 더 좁힌다. 재현 입력이 작아지고, 예상 출력이 구체화되고, 실패하던 경계가 다시 열 수 있는 이름으로 남는다. 예를 들면 “빈 문자열은 빈 리스트로 처리한다”처럼 애매한 문장을 실제 입력과 출력으로 고정하는 식이다. 이런 변경은 제품 코드 diff와 함께 있어도 받아들일 수 있다.
위험한 테스트 수정은 반대로 질문을 흐리게 만든다. 정확히 같아야 하던 값을 포함 여부로 바꾸거나, 실패하던 케이스를 공통 fixture 밖으로 밀거나, timeout을 길게 늘려서 느린 실패를 숨기는 식이다. 특히 에이전트가 “테스트가 오래된 기대값을 보고 있어서 업데이트했습니다”라고 말할 때는 더 조심한다. 오래된 기대값일 수도 있지만, 그 기대값이 사실상 사용자 계약이었을 수도 있기 때문이다.
한 번은 날짜 파싱 버그를 고치던 중에 이런 일이 있었다. 원래 테스트는 잘못된 날짜 문자열을 넣으면 명확한 예외가 나야 한다고 기대했다. 에이전트는 구현을 조금 고치고, 동시에 테스트를 “결과가 비어 있으면 된다”로 바꿨다. 겉으로는 실패가 사라졌지만, 실제로는 오류를 조용히 삼키는 방향으로 계약이 바뀐 셈이었다. 그때부터 나는 테스트 변경을 구현 변경의 부록으로 보지 않기로 했다.
반대로 좋은 경우도 있었다. 한글 파일명 업로드 문제를 고칠 때, 에이전트가 기존 정상 케이스는 그대로 두고 “공백이 섞인 한글 파일명” 샘플을 하나 추가했다. 기대값도 원래 경로 규칙에 맞춰 정확히 박혀 있었다. 이 경우 테스트 diff는 위험 신호가 아니라 증거에 가까웠다. 같은 테스트 수정이라도 방향이 완전히 달랐다.
에이전트에게 다시 돌려보내는 말
이 상황에서 나는 긴 설명을 붙이기보다 질문을 짧게 던지는 편이다. “테스트 변경 중 스펙을 바꾼 줄과 재현을 추가한 줄을 나눠 달라.” 이 정도면 충분할 때가 많다. 답변이 “테스트를 최신 동작에 맞췄다”에서 멈추면 아직 부족하다. 어떤 동작이 최신인지, 그 근거가 사용자 요구인지, 기존 코드의 암묵적 동작인지, 새로 만든 가정인지가 보여야 한다.
작업이 조금 더 중요하면 판정을 세 가지로만 닫는다. `ACCEPT`는 테스트가 실패 입력을 더 정확히 고정했고 구현 diff도 그 입력을 해결한 경우다. `SPLIT`은 구현 수정과 테스트 정리를 별도 커밋이나 별도 요청으로 나눠야 하는 경우다. `HOLD`는 테스트가 느슨해졌거나 스펙 변경 근거가 부족한 경우다. 이렇게 닫아 두면 다음 에이전트 세션도 무작정 “계속 고쳐”로 들어가지 않는다.
이 기준을 너무 무겁게 만들 필요는 없다. 매번 완전한 리뷰 문서를 쓰려 하면 바이브코딩의 속도가 사라진다. 대신 나는 댓글이나 작업 메모에 한 줄만 남긴다. “테스트 변경은 재현 추가, assertion 완화 없음.” 또는 “기대값 변경 근거 부족, 구현과 테스트를 분리.” 이 정도만 남아도 다음 판단이 훨씬 쉬워진다.
중요한 것은 테스트를 절대 못 바꾸게 막는 태도가 아니다. 테스트도 코드이고, 낡은 테스트는 고쳐야 한다. 다만 에이전트가 테스트를 바꿨다는 사실을 완료 근거로 삼는 순간 흐려진다. 테스트 diff는 완료 증거가 아니라 별도의 검토 대상이다. 이 관점만 유지해도 “통과했으니 됐다”라는 짧은 착각을 많이 줄일 수 있었다.
작은 기준선 하나면 충분할 때
바이브코딩을 하다 보면 에이전트가 생각보다 빠르게 초록불을 만든다. 그 속도는 분명히 유용하다. 다만 테스트 파일까지 같이 바뀐 순간에는 속도를 그대로 믿기보다 기준선을 한 번 세우는 편이 낫다. 나는 이제 테스트 diff를 보면 “통과했네”보다 “검증 대상도 바뀌었네”를 먼저 떠올린다.
이 습관은 거창한 리뷰 프로세스가 아니다. 바뀐 테스트가 실패를 더 잘 붙잡는지, 아니면 실패를 덜 보이게 만드는지만 확인하는 작은 분리선이다. 그 선이 있으면 에이전트를 덜 의심해도 된다. 반대로 그 선이 없으면 초록불 하나가 구현 변경, 스펙 변경, 검증 약화를 전부 덮어 버린다.
'[개발 깨알 상식_Tips] > [바이브코딩 Tips]' 카테고리의 다른 글
| PASS 로그 앞의 작업 위치 확인 (0) | 2026.07.06 |
|---|---|
| 중단된 작업의 기준선과 미확인 영역 (0) | 2026.07.04 |
| 빈 diff가 만든 완료 착각 (0) | 2026.07.01 |
| 오래된 검증 로그가 만든 엉뚱한 재시도 (0) | 2026.06.29 |
| 원본 줄이 빠진 패치 리뷰 (0) | 2026.06.28 |