"변경하지 말아야 할 것" 섹션: 조용히 문제를 일으키는 AI 코딩 에이전트를 위한 가장 저렴한 해결책
요약
AI 코딩 에이전트가 의도치 않은 코드 변경을 일으키는 문제를 방지하기 위해, 수행할 작업뿐만 아니라 '하지 말아야 할 사항'을 명시적으로 지시하는 방법론을 제안합니다. 모호한 지시 대신 구체적인 경계를 설정함으로써 에이전트의 결과물을 검증 가능하고 신뢰할 수 있게 만드는 것이 핵심입니다.
핵심 포인트
- 에이전트의 가장 위험한 실패는 에러가 아닌 조용한 코드 변경임
- 모델의 지능보다 명확한 작업 범위(Scope) 설정이 더 중요함
- '하지 말아야 할 것'을 목록화하여 모델의 즉흥적 행동을 차단해야 함
- 정교한 역할극 프롬프트보다 구체적인 제약 조건 명시가 더 효과적임
AI 코딩 에이전트(AI coding agent)의 가장 무서운 실패는 에러를 던지는 실패가 아닙니다. 그것은 에이전트가 실행되고, 얼핏 보기에 문제가 없어 보이며, 당신이 가졌던 문제와는 약간 다른 문제를 조용히 해결해 버리는 코드를 건네줄 때입니다. 명백한 실패는 몇 초 안에 잡아낼 수 있습니다. 하지만 이런 실패는 당신이 건드려 달라고 요청하지도 않은 무언가가 바뀌어 버린 3일 뒤, 운영 환경(production)에서 발견됩니다.
저는 계속해서 동일한 근본 원인을 목격하고 있으며, 이는 모델(model)과는 거의 관련이 없습니다. 그것은 바로 브리프(brief, 지시 사항)입니다.
"더 좋게 만들어줘"가 잘못되는 이유
당신이 에이전트에게 "이 파일을 정리해줘" 또는 "여기에 캐싱(caching)을 추가해줘"와 같은 느슨한 지시를 내릴 때, 당신은 실제로 경계(edges)가 어디인지 알려준 것이 아닙니다. 모델은 범위(scope)에 대한 자신의 추측으로 그 간극을 채웁니다. 보통 그 추측은 합리적입니다. 하지만 때로는 세 파일 떨어진 곳의 함수를 다시 작성하거나, 다른 무언가가 의존하고 있는 변수 이름을 바꾸거나, 혹은 구식으로 보인다는 이유로 당신의 로깅 라이브러리(logging library)를 "친절하게" 교체해 버리기도 합니다. 각각의 행위는 개별적으로는 방어 가능합니다. 하지만 이들이 모이면 당신은 이제 변경 사항이 당신의 머릿속에 있던 박스(box) 안에 머물렀는지 더 이상 신뢰할 수 없기 때문에, 코드 차이(diff)를 한 줄씩 감사(audit)해야만 합니다.
모델이 부주의했던 것이 아닙니다. 당신이 박스를 그려준 적이 없었을 뿐입니다.
습관: 변경하지 말아야 할 것을 말하기
해결책은 부끄러울 정도로 간단합니다. 수행하기를 원하는 작업과 함께, 반드시 건드리지 말아야 할 사항에 대한 짧고 명시적인 목록과 범위 내의 정확한 파일 또는 대상(targets)을 작성하세요. 두세 줄이면 충분합니다:
api/orders.ts의fetchOrders호출에 백오프(backoff)를 포함한 재시도(retry) 로직을 추가하세요.
함수 시그니처(function signature)를 변경하지 마세요, 다른 파일은 건드리지 마세요, 새로운 의존성(dependencies)을 추가하지 마세요.
3번의 시도 후에도 재시도가 실패하면 기존의OrderFetchError를 던지세요.
이것이 비결의 전부입니다. 당신은 모호한 요청을 경계가 있는 무언가로 바꾸었습니다. 이제 출력물은 검증 가능합니다. 박스 안에 머물렀는지 아니면 그렇지 않은지, 의심하며 모든 줄을 읽는 대신 한눈에 확인할 수 있습니다.
"하지 말아야 할 것(do not)" 라인들이 실제로 무엇을 하고 있는지 주목하십시오. 이 라인들이 존재하는 이유는 모델이 멍청해서가 아닙니다. 명시되지 않은 모든 가정은 모델이 즉흥적으로 행동할 수 있는 여지가 되는 곳이며, 즉흥적인 행동(improvisation)은 당신이 신뢰해야 하는 변경 사항에서 정확히 피해야 할 요소이기 때문입니다.
구체성이 영리함보다 낫다
특히 초기에는 영리한 프롬프트(prompt)를 작성하려는 편향이 존재합니다. 길고 정교한 지침, 역할극, "당신은 클린 코드(clean code)를 깊이 신경 쓰는 시니어 엔지니어입니다"와 같은 방식 말입니다. 하지만 이러한 방식의 대부분은 정확한 파일명과 건드리지 말아야 할 정확한 대상을 명시하는 지루한 한 줄보다 훨씬 효과가 떨어집니다.
이유는 간단합니다. 영리한 프롬프트는 모델이 올바른 결과물을 원하도록 유도하려고 노력합니다. 반면 구체적인 브리프(brief)는 잘못된 결과가 나올 여지를 제거합니다. 두 번째 방식이 더 신뢰할 수 있는 이유는 모델이 당신의 마음을 읽어야 하는 것에 의존하는 것이 아니라, 당신이 말하지 않았던 부분을 명확히 입 밖으로 내뱉었는지에 의존하기 때문입니다.
이것은 Claude를 포함한 모든 코딩 에이전트(coding agent)와 협업하는 능력을 키우는 가장 빠른 방법이기도 합니다. 실제로 전이되는 기술은 구문(syntax)이나 프롬프트 트릭을 암기하는 것이 아닙니다. 결과물을 몇 초 만에 대조하여 확인할 수 있을 만큼 충분히 타이트한 브리프를 작성하는 법을 배우는 것입니다. 일단 그것을 할 수 있게 되면, 모델은 슬롯머신이 아니라 당신이 지시하는 도구가 됩니다.
빠른 전후 비교
이전(Before):
결제 로직을 리팩터링(Refactor)해줘, 점점 지저분해지고 있어.
이후(After):
checkout/total.ts에서 할인 계산 로직을 순수 함수(pure function)인applyDiscount(cart, code)로 추출해줘.
getTotal의 공개 동작(public behavior)은 동일하게 유지해줘, 입력과 출력 모두 같아야 해.
세금(tax) 로직은 건드리지 말고, 파일의 나머지 부분도 포맷팅하지 마. 라이브러리도 추가하지 마.
만약code가 유효하지 않다면, 현재와 동일하게 변경 없이 장바구니 합계(cart total)를 반환해줘.
"이전" 방식은 모델이 당신의 결제 로직을 재설계하도록 유도합니다. "이후" 방식은 검토 가능한 깔끔한 변경 사항 하나만을 가져다주며 그 외에는 아무것도 하지 않습니다. 같은 모델, 같은 날이지만, 결과물에 대한 신뢰 수준은 완전히 다릅니다.
이것이 이끄는 곳
일단 "변경하지 말아야 할 것"이라는 습관이 자동화되면, 이후에 발생하는 수많은 고통이 사라집니다. 당신의 diff(차이점)는 줄어듭니다. 에이전트의 의도를 역공학 (reverse engineering) 하는 대신, 명시적인 사양 (spec)에 따라 작고 제한된 변경 사항을 확인하게 되므로 리뷰 속도가 빨라집니다. 그리고 에이전트가 처음부터 방황할 여지 자체를 없애버리기 때문에, 3일 뒤에 갑자기 터지는 조용한 문제들도 더 이상 겪지 않게 됩니다.
이는 작은 습관이지만 보상은 엄청나며, 대안(제한 없는 방식)으로 인해 고생해 본 적이 있다면 누구나 당연하다고 느낄 만한 일입니다. 만약 Claude를 사용하여 무언가를 만드는 법을 배우고 있다면, 이것은 가장 먼저 훈련해야 할 본능 중 하나입니다. 더 나은 프롬프트 (prompt)를 만드는 것이 아니라, 더 단단한 상자 (tighter box)를 만드는 것입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기