AI 생성 코드 테스트 실패를 줄이는 디버깅 흐름

profile_image
작성자 테스트흐름설계자 김하린
댓글 0건 조회 5회

AI 생성 코드가 테스트에서 흔들리는 첫 지점

문제는 코드보다 전제에서 먼저 시작됩니다

AI 코딩 도구로 기능을 빠르게 만들었는데, 막상 테스트를 돌리면 예상 밖의 실패가 이어지는 경우가 많습니다. 이때 바로 프롬프트를 다시 쓰거나 코드를 통째로 갈아엎기보다, 먼저 AI 생성 코드가 어떤 전제를 깔고 작성되었는지 확인해야 합니다.

사람 개발자는 저장소의 암묵적인 규칙, 테스트 데이터의 의도, 예외 처리 관습을 경험으로 이해합니다. 반면 AI 코딩 에이전트는 현재 제공된 파일과 지시문 안에서 판단하기 때문에, 보이지 않는 규칙이 많을수록 테스트 실패 가능성이 커집니다.

  • 도메인 규칙 누락: 할인, 권한, 상태 전이처럼 서비스 내부 규칙이 코드에 반영되지 않은 경우입니다.
  • 테스트 fixture 오해: 샘플 데이터가 실제 운영 데이터와 다르게 구성되어 실패가 발생합니다.
  • 비동기 처리 누락: await, 타이머, 큐, 이벤트 핸들러의 완료 시점을 잘못 가정합니다.
  • 경계값 미처리: 빈 배열, null, 0원, 만료된 토큰처럼 흔한 예외가 빠집니다.
AI 생성 코드를 디버깅할 때는 “왜 틀렸나”보다 “무엇을 알고 있다고 가정했나”를 먼저 묻는 편이 빠릅니다.

특히 팀 저장소에서는 실패 로그 하나만 보고 코드를 수정하면 같은 실패가 다른 파일에서 반복됩니다. 테스트 실패를 줄이려면 실패한 줄을 고치는 것이 아니라, 실패를 만든 입력, 전제, 실행 순서를 분리해서 봐야 합니다.

실패 로그를 읽는 순서와 흔한 오판

에러 메시지는 원인이 아니라 증상입니다

테스트 로그에 보이는 첫 번째 에러가 실제 원인이라고 단정하면 디버깅 시간이 길어집니다. 예를 들어 TypeError가 났다고 해서 타입 정의만 손보면, 실제로는 목 데이터가 잘못 만들어졌거나 API 응답 구조가 바뀐 문제를 놓칠 수 있습니다.

AI 코딩 도구에 로그를 그대로 붙여 넣고 “고쳐줘”라고 하면 표면적인 수정이 나올 때가 많습니다. 더 좋은 방식은 로그를 실패 위치, 실패 조건, 기대값, 실제값으로 나누어 제공하는 것입니다. 그래야 도구가 테스트의 의도를 추론하는 데 덜 헤맵니다.

  1. 가장 먼저 실패한 테스트 이름을 확인합니다. 뒤따르는 실패는 연쇄 오류일 수 있습니다.
  2. 기대값과 실제값을 비교합니다. 값의 차이인지, 타입의 차이인지, 순서의 차이인지 구분합니다.
  3. 최근 변경 파일과 연결합니다. AI가 수정한 파일이 아니라, 그 코드가 참조한 설정 파일까지 봅니다.
  4. 환경 의존성을 확인합니다. 로컬 시간대, Node 버전, DB 시드, 캐시 상태가 원인일 수 있습니다.

AI에게 넘길 로그는 가공이 필요합니다

긴 로그 전체를 넣는 것보다 실패한 테스트 블록, 관련 코드, 기대 동작을 함께 묶어 주는 편이 훨씬 정확합니다. “이 테스트가 왜 실패해?”보다 “이 함수는 빈 권한 목록이면 false를 반환해야 하는데 true가 나옵니다. 원인을 좁혀주세요”처럼 질문을 좁히는 방식이 좋습니다.

보안 관련 테스트라면 더 신중해야 합니다. 인증, 권한, 입력 검증은 단순한 통과 여부보다 공격 가능성과 연결되기 때문입니다. 기본 개념은 코드 보안의 정의코드 보안 요약을 참고해 팀 기준으로 정리해 두면 좋습니다.

  • 그대로 붙여 넣기 좋은 정보: 실패한 테스트명, assert 문, 실제 결과, 관련 함수 본문입니다.
  • 가려야 할 정보: 토큰, 고객 식별자, 내부 API 주소, 운영 DB 접속 정보입니다.
  • 추가하면 좋은 정보: 원래 의도, 이전에 통과하던 조건, 최근 바뀐 요구사항입니다.

AI 코딩 도구로 테스트 실패를 고치는 단계

한 번에 수정하지 말고 재현부터 고정합니다

테스트가 실패하면 가장 먼저 해야 할 일은 수정이 아니라 재현 조건을 고정하는 것입니다. AI에게 바로 패치를 맡기면 실패가 사라진 것처럼 보여도, 실제로는 테스트를 약하게 만들거나 예외를 삼켜버리는 코드가 생길 수 있습니다.

좋은 디버깅 흐름은 작은 단위로 움직입니다. 실패 하나를 골라 재현하고, 원인을 가설로 세운 뒤, 가장 작은 코드 변경으로 검증합니다. 이 흐름을 지키면 AI 생성 코드의 장점인 속도는 살리면서도 품질 하락을 막을 수 있습니다.

  1. 실패 테스트 하나만 선택합니다. 전체 테스트 실패를 한 번에 해결하려 하면 원인과 결과가 섞입니다.
  2. 동일 명령으로 두 번 실행합니다. 한 번은 실패하고 한 번은 통과한다면 비결정성 문제가 먼저입니다.
  3. AI에게 원인 후보를 요청합니다. “수정해줘”가 아니라 “원인 후보를 우선순위로 나열해줘”라고 요청합니다.
  4. 가장 작은 패치를 적용합니다. 함수 시그니처, 조건문, fixture 중 하나만 바꿉니다.
  5. 회귀 테스트를 추가합니다. 같은 입력이 다시 깨지지 않도록 실패 사례를 테스트로 남깁니다.

프롬프트는 수정 지시보다 검증 지시가 중요합니다

AI 코딩 도구에 “테스트 통과하게 수정”이라고 지시하면 테스트 자체를 기대값에 맞게 바꾸는 결과가 나올 수 있습니다. 더 안전한 프롬프트는 “프로덕션 코드의 의도를 유지하면서 테스트 실패 원인을 설명하고, 수정 범위를 최소화해 주세요”처럼 제한을 분명히 둡니다.

아래처럼 역할을 나누면 결과가 안정됩니다. 첫 요청은 분석만, 두 번째 요청은 수정안, 세 번째 요청은 리스크 검토로 분리합니다. 이 방식은 느려 보이지만 되돌림 비용을 줄여 전체 시간은 오히려 짧아집니다.

  • 분석 프롬프트: “실패 로그와 관련 코드를 보고 가능한 원인을 우선순위로 정리해 주세요.”
  • 수정 프롬프트: “가장 가능성 높은 원인 하나만 해결하는 최소 변경안을 제안해 주세요.”
  • 검증 프롬프트: “이 변경이 깨뜨릴 수 있는 기존 동작과 추가 테스트를 알려 주세요.”
테스트를 통과시키는 코드는 많지만, 다음 변경에도 버티는 코드는 실패 원인을 좁힌 뒤에 나옵니다.

실무에서는 고객 문의 자동화나 운영성 기능처럼 AI가 업무 흐름에 깊게 들어오는 사례가 늘고 있습니다. 관련 흐름은 AI 활용 고객문의 처리 사례처럼 운영 영역에서도 확인할 수 있습니다. 개발팀도 같은 맥락에서 AI 결과물을 그대로 믿기보다 테스트와 로그로 검증하는 습관을 가져야 합니다.

테스트 코드를 고쳐야 할 때와 제품 코드를 고쳐야 할 때

기대값이 틀렸는지 구현이 틀렸는지 나누기

AI 생성 코드의 테스트 실패에서 가장 어려운 지점은 “테스트가 낡았는가, 구현이 틀렸는가”를 판단하는 일입니다. 기능 요구사항이 바뀌었는데 테스트가 예전 기대값을 들고 있다면 테스트를 고쳐야 합니다. 반대로 요구사항은 그대로인데 구현이 달라졌다면 제품 코드를 고쳐야 합니다.

판단 기준은 문서가 아니라 사용자에게 보장한 동작입니다. 예를 들어 결제 실패 시 재시도 메시지를 보여주기로 했다면, 내부 함수명이 바뀌어도 그 동작은 유지되어야 합니다. 이런 경우 테스트는 내부 구현보다 결과 화면, 반환값, 이벤트 발생 여부를 중심으로 잡는 편이 안전합니다.

  • 제품 코드를 고칠 상황: 명세와 다른 반환값, 누락된 예외 처리, 권한 우회, 데이터 손실 가능성이 있을 때입니다.
  • 테스트 코드를 고칠 상황: 요구사항 변경이 확정되었고, 기존 기대값이 더 이상 사용자 동작과 맞지 않을 때입니다.
  • 둘 다 봐야 할 상황: 테스트가 구현 세부사항에 과하게 묶여 있고, 제품 코드도 경계값을 충분히 다루지 못할 때입니다.

팀에서 바로 쓰기 좋은 판단 표

아래 표는 AI 코딩 도구가 만든 패치를 리뷰할 때 유용합니다. 테스트 실패를 만났을 때 감으로 결정하지 말고, 실패 유형과 수정 위치를 먼저 맞춰 보세요.

실패 유형먼저 볼 곳권장 조치
기대값만 달라짐요구사항 문서와 테스트 설명변경된 정책인지 확인 후 테스트 기대값 조정
null 또는 undefined 오류입력 검증과 fixture제품 코드의 방어 로직 추가, fixture 현실화
순서가 매번 바뀜정렬 조건과 비동기 처리명시적 정렬 기준 추가 또는 테스트 안정화
권한 테스트 실패인증 미들웨어와 역할 매핑제품 코드 우선 점검, 보안 회귀 테스트 추가

팀 규모가 작다면 이 표를 PR 템플릿에 넣는 것만으로도 효과가 있습니다. 리뷰어는 “왜 이렇게 고쳤나요?” 대신 “이 실패는 어느 유형인가요?”라고 물을 수 있고, 작성자는 AI가 만든 변경을 더 명확하게 설명하게 됩니다.

테스트가 계속 흔들릴 때 프롬프트보다 먼저 볼 것

자주 묻는 질문: AI가 고친 테스트가 다시 깨지는 이유

가장 흔한 이유는 테스트가 실제 사용자 흐름이 아니라 현재 구현 모양에 붙어 있기 때문입니다. AI가 한 번 고친 테스트가 다음 주에 다시 깨진다면, 프롬프트가 나빠서라기보다 테스트의 관찰 지점이 너무 낮은 곳에 있을 가능성이 큽니다.

예를 들어 버튼 클릭 후 API 함수가 정확히 한 번 호출되는지만 검사하면, 내부 구현이 배치 요청으로 바뀌는 순간 테스트가 깨집니다. 하지만 사용자가 최종적으로 성공 메시지를 보고 목록이 갱신되는지를 검사하면 구현 변경에도 테스트가 더 오래 버팁니다. AI 코딩 도구는 이런 테스트 설계 의도까지 자동으로 알지 못하므로 사람이 먼저 기준을 잡아야 합니다.

  1. 사용자 결과를 기준으로 다시 씁니다. 내부 함수 호출보다 화면, 응답, 저장 결과를 우선합니다.
  2. 불안정한 시간을 제거합니다. 현재 시각, 랜덤값, 네트워크 지연은 고정값으로 통제합니다.
  3. fixture를 현실에 가깝게 만듭니다. 성공 케이스 하나만 두지 말고 빈 값, 권한 없음, 중복 데이터를 포함합니다.
  4. AI에게 테스트 의도를 설명시킵니다. 생성된 테스트가 무엇을 보장하는지 한 문단으로 쓰게 하면 허술한 부분이 드러납니다.

계속 흔들리는 테스트는 도구 문제가 아니라 설계 신호일 때가 많습니다. 이럴 때는 AI에게 “테스트를 통과시켜줘”라고 하기보다 “이 테스트가 구현 세부사항에 너무 의존하는지 검토해줘”라고 묻는 편이 좋습니다. 질문의 초점이 바뀌면 답도 달라집니다.

마지막으로, 실패가 반복되는 모듈은 별도의 작은 테스트 전략 문서를 두는 것이 좋습니다. 인증, 결제, 권한, 동시성처럼 위험도가 높은 영역에는 “무엇을 단위 테스트로 보고, 무엇을 통합 테스트로 볼지”를 적어 두세요. 그러면 AI 생성 코드도 팀의 테스트 철학 안에서 움직이기 시작합니다.

AI 생성 코드 테스트 실패를 줄이는 디버깅 흐름

댓글목록

등록된 댓글이 없습니다.