AI 시대의 개발자는 검증을 설계한다 (3) 기능을 검증하는 Test

"방금 구현한 것 검증하는 테스트도 짜줘"

2026. 07. 10·linkedin에 발행

> “방금 구현한 것 검증하는 테스트도 짜줘”

AI가 몇번 고치더니 통과합니다. Pass 가 주르륵 뜹니다. 그런데 이게 정말 유효한 건가? 테스트 파일을 열어봅니다. 뭔가 그럴듯하게 짠 것 같은데 아리송합니다. ‘이게 통과했다고 이 코드를 믿고 배포할 수 있을까?’

사실 저도 그동안 테스트를 열심히 짜지 않았습니다. 테스트에 들어갈 시간 투입을 생각하면 ‘그렇게 까지 해야할까’ 하며 미루게 되더라고요. 그렇지만 이젠 정말 상황이 달라졌습니다.

> “AI 시대에 개발자가 테스트를 안 짜면 직무 유기예요, 진짜.”

우리 회사의 모 리드 분이 저한테 한 말입니다. 기억에 남았습니다. 저도 AI 시대에 테스트의 ROI가 훨씬 올라갔다고 생각하기 때문입니다.

AI가 코드를 쏟아내니 병목이 바뀌었습니다. 얼마나 빨리 짜느냐가 아니라 짠 걸 얼마나 빨리 믿고 배포하느냐로 옮겨갔습니다. 그만큼, 잘 짠 테스트 코드의 가치가 높아졌죠.

게다가 테스트의 비용도 낮아졌습니다. 이제는 AI가 테스트를 짜줄 수 있으니까요.

그래서 테스트 코드를 짜야겠다, 마음 먹었습니다.

일단 AI한테 테스트 코드를 “짜줘” 해보았습니다. AI가 진짜로 짜주긴 짜줍니다. 그럴듯해 보입니다. 테스트 라인 커버리지도 금방 올라갔습니다.

하지만 이 테스트가 버그를 제대로 잡는지는 여전히 알수가 없었습니다. 다 통과했지만, 믿고 배포할 수는 없었습니다.

코드만 주면, AI는 놓친다

한번 실험을 해봤습니다. A 에이전트에게는 코드만 주고 테스트를 짜게 했습니다. B 에이전트는 테스트를 짜기 전에 저를 ‘인터뷰’하라고 해보았습니다.

이 기능을 ‘프리미엄 회원인지 확인하고 맞으면 유료 기능 페이지로 보내주는 화면’이라고 해보겠습니다. (실제는 회사 코드라 좀 바꿔봤습니다.)

A는 코드를 읽고 테스트 케이스를 짰습니다. 무료 회원이면 막힌다. if 무료 회원 -> Block. 코드에 그렇게 적혀있으니까 그런 건 잘 읽어냅니다.

B는 코드를 보고 저를 먼저 인터뷰했습니다. ‘프리미엄 회원만 유료 기능을 쓸 수 있는 게 맞나요?’ 라고 물어봤습니다. 등급에는 ‘프리미엄’ 말고도 ‘정지’나 ‘만료’ 회원도 있다는 걸 알려줬습니다.

이제 둘 다 테스트를 짰고, 둘 다 통과했습니다.

코드를 바꿔서 버그를 일부러 심어봅니다. ‘유료 회원’이면 통과시키던 검사를 ‘무료 회원이 아니면’ 통과시키도록 조건을 바꿔봅니다.

‘무료 회원이 아닌 회원’에는 정지나 만료도 포함돼있기 때문에, 이건 당연히 버그가 됩니다.

하지만 A 테스트는 버그를 통과시켰습니다. B의 테스트는 실패를 뱉었습니다.

회원 등급에는 무료와 유료만 있는 게 아니었습니다. B는 정책을 알고 있었으니 유료가 아닌 등급에 대한 테스트 케이스를 자세히 넣었고, A는 코드에 표현되지 않은 등급을 넣을 수가 없었습니다.

또 다른 상황. 반대로 테스트 케이스에 넣지 말아야할 것을 넣는 경우도 있었습니다.

‘충전 한도’를 검사하는 기능이 있었는데요. ‘잔액과 충전 금액을 더해서 한도가 넘으면 에러를 보여줘야 한다’였습니다.

사실 잔액은 외부 데이터에서 오는 구조였습니다. 클라이언트는 잔액을 몰랐습니다. 충전에 대한 검증은 외부에서 오는 것이었는데, 실제로는 그냥 Mocking으로 채워넣고 있었습니다.

필요없는 테스트를 짜두고, Pass를 띄웁니다. 없는 능력을 검증했으니 당연히 통과하죠. 겉으로는 그럴 듯해보였죠. 문제가 없어 보여서 문제를 더 찾기 어렵습니다.

복잡한 기능들에는 이런 ‘미묘한 차이’가 정말 많습니다. 그리고 그런 미묘한 버그를 잡아내는 게 테스트의 역할이죠.

코드만 주고 AI가 짠 테스트는 힘없이 뚫려버렸습니다. 혹은 불필요한 테스트를 했고요.

그 이유는 테스트를 짤 줄 몰랐던 게 아니라, 무엇을 테스트해야할지 몰랐기 때문이었습니다.

AI가 더 똑똑하면 해결되는 거 아닌가?

물론 똑똑한 AI는 코드를 보고 의도를 꽤 추론해냅니다. AI는 상식적인 패턴을 많이 학습했으니까요.

  • 게시판에 글을 쓰는 기능이 있네? 👉 쓰고 나서, 상세 페이지로 가야한다.

  • 비공개 글이 있네? 👉 그럼 남의 피드에 안 보여야겠다.

이런 건 상식으로 알아서 센스있게 채워넣어요.

하지만 요구사항은 ‘상식적으로 그럴 것 같은데’로만 흘러가지 않잖아요.

  • 찜하기는 사실 유료회원 전용이다.

  • 결제 한도는 최대한도가 아니라 최소한도다.

  • 구독이 만료되면 사용을 막지 않고 연장 화면으로 보낸다…

이런 규칙들은 우리 앱/제품이 정한 규칙이지, 세상의 상식이 아닙니다.

Fable 5 같은 고성능 AI 모델을 써도 마찬가지였습니다. 상식과 코드만 가지고 정답을 쓰게 되면 문제가 생깁니다. 경험상 10-20%의 테스트 케이스는 불필요하거나 놓치게 되더라고요.

앞으로 AI가 똑똑해져도 마찬가지라고 생각합니다. 애초에 코드에 단서가 없거나, 혹은 코드가 짜여진 그대로 믿어버리면 결국 AI는 불완전한 재료만 갖게 됩니다.

재료가 이상하면 똑똑해도 소용이 없죠. 아무리 똑똑해도 코드와 상식만으로는 제품의 요구사항을 정확히 읽을 수 없습니다.

결국 ‘테스트해야할 것’의 기준은 코드 밖에 있습니다.

정책, 불변조건, 요구사항. 스펙.

결국 이 코드가 어떤 기능을 해야하는지에 대한 기준을 잡아야 합니다.

예전부터 테스팅에서는 ‘오라클(Oracle)‘이라고 부르던 필수 재료였습니다. 오라클은 진실의 원천이라는 뜻입니다. 시스템을 검증하는 진실의 원천을 어떻게 확보할까?

이게 ‘무엇을 테스트할 것인가’를 결정하고, 그게 테스트의 퀄리티를 만듭니다.

스펙 문서요? 그건 누가 다 쓰나요

사실 ‘코드’ 말고도 ‘정책과 스펙’이 있어야 테스트 케이스를 잘 짤 수 있다는 건 당연히 알았습니다. 그럼에도 불구하고 제가 인트로에서처럼 그냥 코드만 주고 ‘짜줘’라고 했던 이유는… 스펙 문서가 없었기 때문이죠.

물론 이미 문서화가 잘 되어있다면 걱정이 없겠지만, 대부분은 그렇지 않죠. 이미 오래되어 내용이 달라졌거나, 부분부분 파편화됐거나.

저도 제품 정책을 하나하나 문서로 옮긴다고 생각하면 한숨부터 나옵니다. 테스트를 미루던 이유와도 같습니다. 맞는 건 알지만 시간과 노력이 많이 들어가니까요.

어떻게 해야할까 고민하던 중… 아이디어가 하나 떠올랐습니다.

AI에게 답을 시키지 말고, 질문을 시키자.

스펙을 작성할 때 중요한 건 스펙에 들어간 정답의 기준은 사람이 책임져야 한다는 점입니다. 그러면서 백지에서 사람이 다 쓰는 것보다는 효율적이어야 합니다.

책임지려면 사람이 봐야하고, 효율적이려면 사람이 덜 써야 합니다.

일단 AI가 코드를 보고 초안을 만들도록 했습니다. (코드 외에 다른 자료나 git 히스토리에서 fix 커밋도 보게했습니다.) 그리고 이 초안이 맞는지 질문을 하도록 합니다.

코드를 보고 추론한 건 못 믿는다고 했는데? 하지만 코드를 보고 질문을 하는 것과 답을 내는 것은 달랐습니다. 내가 답을 하기에 책임을 지면서도, AI가 준비한 질문에서 시작하기 때문에 훨씬 빠릅니다.

한번 코드를 보고 저에게 스펙 확인 질문을 하라고 시켰습니다.

쓰여진 코드 중에 이런 게 있었습니다. ‘3만원 ‘미만’이면 확인 다이얼로그를 띄운다.’ 그런데 일반적으로는 특정 금액을 ‘초과’하면 확인 다이얼로그를 띄웁니다. 그러니까 AI가 바로 물어보더라고요. 이게 의도인가요? 버그인가요? 저는 그 질문에 1초만에 ‘아 그건 의도야. 3만원 미만은 환불이 안 되거든’이라고 대답할 수 있었습니다.

AI가 질문을 만듭니다. 제가 답합니다. 제가 답으로 확정하면서 이 호흡이 꽤 좋다는 걸 느꼈습니다. `이나 `grill-me` 같은 도구를 써보신 분들이라면 아실 겁니다. 의도를 정렬하는 가장 적절한 스윗 스팟인 거 같아요.

질문이 없었다면 ‘그냥 단순히 다이얼로그를 띄운다’로 마무리되었을 겁니다. 하지만 질문이 있었고 답변을 통해서 ‘환불이 안되면 안내를 해준다’ 라고 더 정확하게 잡을 수 있었습니다. 아마 빈 페이지에 이 정책을 쓰라고 했으면 쉽게 떠오르지 않았을 텐데 말이죠.

한꺼번에 쓰고 빈칸과 물음표를 리뷰하기

질문을 하나씩 주고받는 건 좋았지만, 좀 느린 감이 있었습니다. 질문 하나, 답 하나. 이렇게 하니 핑퐁이 너무 길었어요.

하다보니 경험상 10개 중 8-9개 정도는 정확하고, 1-2개 정도만 바로잡으면 된다는 걸 느꼈습니다. 하나씩 물어보던 방식을 바꿨습니다.

먼저 통째로 채우게 합니다. 발견한 규칙을 전부 적게 합니다. 사람은 이미 쓰인 문서를 한번에 검토합니다. 훨씬 빨랐습니다.

그런데 쓰인 문서를 읽다보니 읽지 않고 괜찮겠지 하고 넘어가는 부분이 있었습니다. 아무래도 완성된 문서는 다 읽지 않게 됩니다.

그래서 프롬프트를 다시 좀 더 수정했습니다. 애매한 부분은 질문으로 남기거나, 빈칸을 뚫어서 표시하도록 했어요. 확신이 없는 부분에는 명확한 물음표 기호가 들어갔습니다.

또 ‘내가 보지 않은 것’들에 대해서도 명시하라고 적어주었습니다. 사람이 추가 힌트를 줄 수 있는 섹션도 만들었고요. AI가 아예 놓친 사각지대를 잡습니다.

이렇게 조금씩 조정을 하다보니, 드디어 만족스러운 하나의 워크플로우가 나왔습니다. 코드를 보고, 초안을 생성하고, 의문을 표시하고, 사람이 리뷰하고, 추가 작성하고 최종 승인합니다.

처음엔 단단하지 않았던 스펙 문서가 금방 완성됐습니다.

7개로 시작했던 규칙이, AI가 비워둔 빈칸을 채우면서 9개가 되었습니다. 물음표가 있던 정책을 승인했습니다. 왕복은 딱 2번에 끝났고요. 이 왕복을 거치면서, ‘제가 알고 있는 정책이 다 들어갔다’는 걸 확신할 수 있었습니다.

이 흐름을 Agent Skill로 만들어서 지금은 테스트 짤 때마다 돌리고 있습니다.

스펙 문서는 첫번째 필수 재료입니다

AI한테 “테스트 짜줘”라고 했을 때 빠져있던 건, ‘무엇을 테스트해야하는가’ 였습니다.

AI에게 테스트를 맡기기 전에 스펙 문서라는 ‘정답지’를 먼저 확보해야합니다.

다만 그 정답지를 혼자 쓸 필요는 없습니다. AI에게 답을 시키지 말고, 질문을 시키면 됩니다. 사람은 답을 하고, 답에 책임을 집니다. AI는 테스트를 짜고, 개발자는 무엇을 검증할지를 설계합니다.

스펙 문서를 확보했습니다. 이제 테스트를 쓰라고 하면 될까요?

그런데 여기서도 저는 시행착오를 좀 겪었습니다. 스펙 문서가 있으면 버그를 잘 잡기는 하는데, 코드를 조금만 고쳐도 자꾸 깨지는 테스트가 나왔습니다. 그런 테스트는 결국 슬며시 끄게 됩니다.

마치 갑옷은 튼튼한데, 움직이기가 너무 힘든 느낌이었습니다. 금방 벗어던지고 싶어졌죠.

다음 편에서는 어떻게 테스트가 불편한 갑옷이 되지 않게 만들수 있는지, 여기에 대해 얘기해보겠습니다.