
새 기능을 넣은 뒤 필터를 바꿀 때 완료·미완료를 합친 전체 건수가 틀어지거나, 새로고침 뒤 저장한 내용이 사라진다면 어떨까? 개발자는 이런 일을 ‘회귀’라고 부른다. 비개발자에게는 한 곳을 고쳤는데 전에 되던 다른 곳이 고장 난 것이라고 이해하면 충분하다.
로컬 할 일 앱 하나에 우선순위, 마감일, 제목 편집을 차례로 추가했다. 이번 실행에서는 실제로 수행한 자동 검사와 화면 확인 범위 안에서 새 기능 오류나 기존 기능 회귀를 발견하지 못했고, AI에 수정 요청도 보내지 않았다. 다만 이 결과에는 조건이 있다. 기준 앱부터 테스트와 저장 오류 처리를 요청했고, 매번 실행한 검사가 통과한 버전에서 다음 단계를 시작했다. 계획한 화면 검사를 전부 실행한 것도 아니어서 네 단계 모두 ‘부분 확인’으로 판정했다.
이 글의 목차
먼저 가져갈 결론
- 이번 한 사례에서는 기능 세 개를 추가한 뒤에도 실행한 검사가 모두 통과했다.
- ‘오류 0’은 앱 전체가 안전하다는 뜻이 아니라 수행한 검사에서 오류를 찾지 못했다는 뜻이다.
- 이번 사례에서는 기능과 함께 코드·테스트·다시 확인할 항목도 늘었다. 이 결과는 새 기능을 맡긴 뒤 예전 동작과 저장 상태를 함께 재검사하는 습관을 뒷받침한다.
이 한 사례에서 가져갈 실용적인 판단 기준은 “AI가 첫 코드를 만들어줬는가”에 그치지 않는다. 새 기능을 넣을 때마다 같은 확인 순서를 반복할 수 있는가도 함께 봐야 한다.
기능을 추가할 때 다시 볼 다섯 가지
- 새 기능보다 먼저 예전 버튼을 같은 순서로 다시 누른다.
- 필터를 바꾼 뒤 목록과 전체 건수가 어긋나지 않는지 본다.
- 새로고침하거나 다시 열어 입력한 데이터가 남는지 확인한다.
- 새 기능이 완료 상태나 날짜처럼 관계없는 값까지 바꾸지 않았는지 살핀다.
- 문제가 생기면 구체적으로 다시 요청하고 처음부터 전체 순서를 반복한다.
이번에는 수정 요청이 필요하지 않았지만, 마지막 항목도 실험 전에 미리 정해 둔 대응 절차였다. 결과를 보고 나서 유리하게 만든 규칙은 아니다.
로컬 할 일 앱을 네 단계로 바꿨다
외부 서버나 실제 개인정보가 없는 로컬 앱 ‘Pocket Tasks’를 AI 코딩 도구 Codex로 만들었다. 도구 화면에 정확한 모델명이 표시되지 않아 이 글에서는 모델명을 적지 않는다. 기준 앱 요청에는 할 일 추가·완료·삭제, 상태 필터, 전체·진행 중·완료 건수 요약, 브라우저 저장 기능과 함께 단위 테스트와 저장 오류 처리를 처음부터 포함했다.
그 뒤에는 직전 단계에서 실행한 검사가 통과한 스냅숏, 즉 그 시점의 저장된 버전만 이어받아 기능을 하나씩 추가했다.
- S0: 기준 앱
- S1: 우선순위와 상태·우선순위 결합 필터
- S2: 마감일과 ‘기한 지남’ 필터
- S3: 목록 안에서 제목 편집
각 단계에서는 JavaScript 문법을 확인했다. S1부터는 이전 단계의 자동 테스트를 고치지 않은 채 전부 다시 실행하고 새 기능 테스트를 더했다. 화면 확인은 브라우저 도구로 진행했다. 추가·완료·필터·요약을 다시 확인했으며, 새로고침 때는 그 단계까지 존재한 제목·완료 상태·우선순위·날짜가 남는지 살폈다.
실행한 검사에서는 회귀를 찾지 못했다
| 단계 | 추가 기능 | 자동 테스트 | 판정 |
|---|---|---|---|
S0 | 기준 앱 | 7/7 통과 | 부분 확인 |
S1 | 우선순위·결합 필터 | 10/10 통과 | 부분 확인 |
S2 | 마감일·기한 지남 | 15/15 통과 | 부분 확인 |
S3 | 목록 안 제목 편집 | 18/18 통과 | 부분 확인 |
제품 오류는 새 기능 자체의 문제, 회귀는 이전에 되던 기능이 깨진 문제로 셌다. 네 단계에서 수행한 검사 기준 제품 오류는 0건이었고, S1~S3에서 관찰된 회귀도 0건이었다. AI에 보낸 수정 요청도, 검증 뒤 사람이 직접 코드를 고친 일도 0회였다.
화면 확인도 기능이 추가된 단계별로 나눴다. S1에서는 우선순위 기능이 생기기 전에 만든 할 일이 요청한 대로 중간 우선순위로 표시됐다. S2에서는 상태·우선순위·기한 조건을 모두 만족하는 항목만 남도록 필터가 함께 작동했고, 화면에 일부 항목만 보여도 전체 건수 요약은 바뀌지 않았다. S3에서는 제목을 편집해도 완료 여부·우선순위·마감일이 유지됐고, 새로고침 뒤에도 저장한 값이 남았다. 이 확인 과정에서 생긴 검사 도구 문제는 아래에서 설명한다.
자동 검사는 Node.js의 내장 테스트 러너를 사용했다. 테스트 중 예외가 생기면 실패로 표시된다. 브라우저 데이터는 같은 출처(origin)에 값을 보존하는 localStorage에 저장했다. 자동 테스트로 확인한 상태·저장 로직과 별도로, 브라우저에서 실제 새로고침 뒤 값이 남는지도 확인했다. (Node.js Test Runner, MDN Web Storage API)
왜 네 단계 모두 ‘부분 확인’인가
사용한 브라우저 도구로는 저장소 값을 직접 바꿀 수 없었다. 그래서 손상된 저장값을 만났을 때의 동작은 화면에서 재현하지 못했고 자동 테스트로만 확인했다. 삭제 동작은 S0 화면에서는 실행했지만, S1 이후에는 검사 도구에서 동작 시점의 별도 안전 확인이 필요해 화면에서 반복하지 않았다. 대신 이전 단계부터 그대로 유지한 자동 테스트로 확인했다.
마지막 새로고침 검사에서는 검사 도구가 화면의 특정 요소를 찾는 두 번의 시도에서 시간 초과가 났다. 화면 전체 구조와 항목 목록을 한꺼번에 읽는 방식으로 저장된 제목과 나머지 값이 남아 있음을 다시 확인했다. 다만 이 도구 문제를 제품 오류로 세지도 않았고, 첫 시도에 완전히 성공한 것으로 기록하지도 않았다.
이 범위 때문에 표의 통과와 ‘0건’은 검사한 동작에 대한 관찰값이다. 실제 사용자 환경 전체, 다른 앱, 다른 프롬프트, 이미 고장 난 코드 위에서의 유지보수까지 보증하지 않는다.
참고: 코드 크기와 시간도 함께 기록했다
앱 코드는 빈 줄을 제외하고 214줄에서 361줄로, 테스트 코드는 37줄에서 123줄로 늘었다. 같은 날 같은 ESLint 9.35.0 classic 규칙으로 측정한 함수별 최대 순환 복잡도는 8에서 10으로 올라갔다. 순환 복잡도는 조건에 따라 코드 실행 경로가 얼마나 갈라지는지 세는 값이다. 미리 정한 기준인 10을 넘는 함수는 없었다. 이 ESLint 버전이 지원 종료 경고를 냈기 때문에 당일 비교용으로만 사용했다. 줄 수와 복잡도는 확인할 표면이 커졌다는 보조값이지 품질 점수가 아니다. 국제 표준 ISO/IEC 25010 역시 제품 품질을 하나의 점수가 아니라 여러 특성과 하위 특성으로 나눠 보는 참조 모델이다. (ESLint complexity, ISO/IEC 25010:2023)
요청부터 첫 파일 전달까지는 단계별 52~122초, 검증은 72~126초였다. 단계마다 요구와 검사 수가 달라 이 시간만으로 AI가 더 좋아지거나 나빠졌다고 해석할 수는 없다. 마지막 검증 시간에는 화면 요소를 찾지 못한 원인이 앱인지 검사 도구인지 구분한 시간도 포함됐다.
결론: 기능 추가는 재검사가 끝나야 끝난다
이번 한 앱에서는 기능 세 개가 수정 요청 없이 추가됐고, 실행한 검사에서 기존 기능이 깨지는 모습은 발견하지 못했다. 그러나 매 단계 실행한 검사가 통과한 스냅숏에서 시작한 한 번의 연속 사례다. 이미 깨진 앱에 계속 기능을 얹는 비용은 측정하지 않았다.
바이브코딩의 유지보수는 “AI가 코드를 써줬다”에서 끝나지 않는다. 이전에 되던 것이 지금도 되는지 확인하는 일까지 포함해야 비로소 기능 추가가 끝난다.
이 글은 AI를 활용해 자료 조사와 초안 작성을 보조하고, 작성자가 직접 검증·편집했습니다.
답글 남기기