AI가 테스트까지 짜는 팀, 개발자는 무엇을 검증해야 하나

AI가 테스트까지 짜는 팀, 개발자는 무엇을 검증해야 하나

코드와 테스트를 같은 에이전트가 동시에 쓰는 순간, 테스트 스위트는 품질 감시자에서 현재 동작의 공증인으로 전락한다

AI 테스트 자동화 yes-man tests breaking change 계약 기반 개발 CI 품질 게이트 에이전트 코드 검증 AI 코드 리뷰
광고

CI는 초록이었다. 그런데 프로덕션이 터졌다

142개 테스트 통과. 코드 리뷰 승인. CI 파이프라인 전부 그린. 그리고 4시간 후, 모바일 클라이언트에서 500 에러가 쏟아졌다.

dev.to에 올라온 한 테크 리드의 사례다. 그가 AI 에이전트에게 요청한 건 단순했다. "유저 응답 DTO 좀 정리해줘." 에이전트는 합리적인 판단을 했다. phoneNumbernull일 때 필드 자체를 JSON에서 제거한 것이다. 페이로드는 더 깔끔해졌고, 테스트도 그 변경에 맞춰 자동으로 업데이트됐다. 문제는 1년째 아무도 열어보지 않은 구형 Android 빌드였다. 그 앱은 phoneNumber가 없으면 크래시가 났다.

여기서 진짜 공포는 breaking change 자체가 아니다. 모든 안전망이 설계대로 작동했는데도 시스템이 깨졌다는 사실이다. 에이전트는 코드를 바꾸고, 바뀐 코드에 맞는 테스트를 썼다. 테스트는 당연히 통과했다. CI도 당연히 초록이었다. 무엇도 실패하지 않았다. 그런데 무언가가 부서졌다.

"예스맨 테스트"의 구조적 문제

20년 동안 테스트 스위트의 암묵적 계약은 이랬다. 테스트는 구현과 독립적으로 작성된다. 개발자가 "이 시스템은 이렇게 동작해야 한다"고 먼저 선언하면, 코드는 그 선언을 통과하거나 실패한다. 테스트가 증인이 되는 구조다.

에이전트가 코드와 테스트를 같은 컨텍스트에서 동시에 생성하는 순간, 이 독립성이 사라진다. 에이전트는 DTO를 바꾸고, 바뀐 DTO를 검증하는 어서션을 함께 작성한다. 이 테스트는 변경을 감지한 게 아니라 변경을 승인한 것이다. 해당 기사에서 저자가 이걸 "yes-man tests"라고 부르는 이유다. 에이전트가 방금 쓴 것이라면 무엇이든 동의하는 테스트. 초록 체크마크의 감정적 안도감은 제공하지만, 보호는 제공하지 않는다.

더 근본적인 문제는 에이전트가 구조적으로 이 위험을 인식할 수 없다는 점이다. breaking change의 피해는 내 레포 안에 없다. 파트너사의 인테그레이션, 고객이 만든 Zapier 자동화, 지금 이 API를 파싱하고 있는 다른 팀의 LLM 에이전트—에이전트는 경계의 한쪽만 볼 수 있다. 호환성은 시스템 경계의 속성인데, 에이전트는 경계의 내부만 최적화한다.

속도가 올라갈수록 드리프트도 같이 올라간다

코드 리뷰로 커버하면 되지 않냐고? 40줄을 검토할 때의 리뷰와, 에이전트가 9초 만에 생성한 600줄의 잘 포맷된, 테스트 커버리지까지 갖춘 PR을 리뷰할 때는 완전히 다른 인지 작업이다. 출력 속도를 10배 높이면 사일런트 컨트랙트 드리프트도 같이 10배 올라간다. 리뷰어의 인지 한계는 그대로인데 볼륨만 폭증한 상태에서, 코드 리뷰는 품질 게이트가 아니라 러버스탬프가 된다.

그렇다고 AI 에이전트를 끄라는 말이 아니다

이 문제의 해법은 에이전트를 덜 쓰는 게 아니다. 안전 레이어를 다시 설계하는 것이다. 실제로 효과를 보고 있는 접근은 세 가지다.

첫째, 계약을 코드보다 상위에 둔다. OpenAPI 스펙이나 Pact를 동결하고, CI에서 생성된 출력을 동결된 계약과 diff한다. "테스트가 통과하는가"가 아니라 "응답 형태가 컨슈머를 깨는 방식으로 변경됐는가"를 기계가 확인한다. 필드 삭제, 타입 축소, required→optional, 열거값 제거, 200→204—이 다섯 가지는 기계적으로 탐지 가능하다. 사람 눈에 맡길 이유가 없다.

둘째, 에이전트가 쓴 테스트는 유죄 추정으로 취급한다. 코드와 테스트가 같은 커밋에서 함께 변경됐다면, 그 테스트는 증거가 아니다. 에이전트에게 구현을 건드리기 전에, 기존 동작에 대한 특성화 테스트를 별도 단계에서 먼저 작성하게 한다. 번거롭다. 그런데 작동한다.

셋째, breaking change 감지는 CI에, 사람에게는 돌려주지 않는다. 600줄 diff에서 사라진 키 하나를 사람이 잡는 건 구조적으로 무리다. 이건 기계가 해야 할 일이다.

주니어 개발자의 위기: 테스트만의 문제가 아니다

같은 맥락에서 또 다른 문제가 쌓이고 있다. AI 도구에 깊이 의존한 주니어 개발자들이 정작 자신의 코드를 설명하지 못하는 상황이다. dev.to에 올라온 한 주니어 개발자의 고백은 이 문제를 정직하게 드러낸다. 면접에서 기본 개념을 묻자 머릿속이 하얗게 됐다. 수십 번 써봤는데, 매번 AI에게 먼저 물어봤기 때문에 실제로는 한 번도 혼자 생각한 적이 없었던 것이다.

이 두 문제는 같은 뿌리에서 나온다. AI가 출력만 제공하고 과정을 생략하면, 검증 능력도 같이 퇴화한다. 에이전트가 쓴 테스트를 의심할 수 있으려면, 테스트가 왜 독립적이어야 하는지를 먼저 체화하고 있어야 한다. 에이전트가 생성한 DTO 변경이 downstream에 미치는 영향을 판단하려면, API 계약이 무엇인지를 스스로 알고 있어야 한다. 이 판단력은 AI에게 물어봐서 얻어지는 게 아니다. 직접 깨져봐야 생긴다.

개발자가 검증해야 할 것의 위치가 바뀌었다

병목은 코드를 쓰는 속도가 아닌 것으로 드러났다. 에이전트가 그건 이미 증명했다. 진짜 병목은 지금 방금 생성된 것이 방 안에 없는 누군가를 깨뜨렸는지 아닌지를 아는 것이다. 그리고 코드를 더 빠르게 생성할수록 이 문제는 선형이 아니라 지수적으로 어려워진다.

AI-First 팀에서 개발자의 역할은 코드 생성자에서 계약 수호자로 이동한다. 무엇이 외부와의 약속인지를 정의하고, 그 약속이 AI 생성물에 의해 조용히 깨지지 않도록 구조를 설계하는 것. 그 구조 자체를 AI와 함께 만들어도 좋다. 단, 그 구조의 의미를 이해하는 사람은 반드시 팀 안에 있어야 한다.

코드 생산량에 흥분하는 시간만큼, 그 코드가 무엇을 깨지 않았는지를 검증하는 방법에 흥분해야 할 때다.

출처

더 많은 AI 트렌드를 Seedora 앱에서 확인하세요