Claude가 생성한 코드가 작동은 하지만 어딘가 어색하게 느껴지는 이유 (그리고 해결 방법)
요약
Claude가 생성한 코드가 기존 코드베이스와 구조적으로 어긋나는 'AI 보조 드리프트' 현상의 원인을 분석하고, 이를 해결하여 유지보수성을 높이는 세 가지 실무 습관을 제안합니다.
핵심 포인트
- AI 보조 드리프트: 컨텍스트 결여로 인한 아키텍처적 불일치 발생
- 작업 전 브리프 작성: 무엇을 만들고 무엇을 유지할지 명시하여 제약 조건 설정
- 이해 확인 단계 추가: 코드 작성 전 Claude의 가정(assumptions)을 먼저 검토
- 맥락 공유의 중요성: 국소적 일관성을 넘어 전체 코드베이스와의 연결성 확보
기능을 배포합니다. 테스트는 통과합니다. PR(Pull Request)은 깔끔해 보입니다. 하지만 3일 후, 기능을 확장하려고 하면 무언가 어색하게 느껴집니다. 구조가 딱 맞지 않습니다. 특정 로직이 그 위치에 있는 것이 맞는지 확신이 서지 않습니다. 네이밍(Naming)을 다시 의심하기 시작합니다. 결국 결국 코드를 다시 작성하게 됩니다.
익숙한 상황인가요?
이것은 Claude와 함께 개발을 진행한 지 몇 달이 지난 개발자들이 겪는 가장 흔한 경험 중 하나입니다. 코드가 틀린 것은 아닙니다. 잘 실행됩니다. 하지만 미묘하게 이질적입니다. 당신의 코드처럼 느껴지지 않습니다.
왜 이런 일이 발생하는지, 그리고 실제로 무엇이 이를 해결할 수 있는지에 대해 이야기해보고자 합니다.
진짜 문제는 당신의 프롬프트가 아닙니다
본능적으로 더 나은 프롬프트(Prompt)를 찾게 됩니다. 더 구체적인 요구사항, 더 명확한 제약 조건 등을 말이죠. 그것도 도움이 되지만, 이는 증상만을 치료하는 것입니다.
근본적인 원인은 대개 다음과 같습니다: 출력물이 무엇과 연결되어야 하는지에 대한 명확한 그림을 그리기 전에 Claude에게 작업을 넘겨버린다는 점입니다.
Claude는 국소적으로 일관된(locally coherent) 코드를 생성하는 데 매우 뛰어난 능력을 갖추고 있습니다. 잘 형성된 요구사항이 주어지면, Claude는 문자 그대로의 문제를 해결하는 결과물을 만들어낼 것입니다. 문제는
저는 이것을 **AI 보조 드리프트 (AI-assisted drift)**라고 생각합니다. 전통적인 의미의 기술 부채 (technical debt)는 아니지만, 기존의 컨텍스트 (context)를 각 세션에 가져오지 않은 채 빠르게 움직일 때 축적되는 아키텍처적 불일치 (architectural incoherence)를 의미합니다.
실제로 도움이 되는 것들
Claude의 도움을 받아 작성한 코드의 유지보수성 (maintainability)을 실질적으로 개선해 준 세 가지 습관은 다음과 같습니다.
1. 각 세션 전에 한 단락 분량의 "브리프 (brief)" 작성하기
단 하나의 프롬프트 (prompt)를 입력하기 전에 다음 내용을 작성하세요: 무엇을 만들고 있는지, 그것이 연결되어야 할 기존 요소는 무엇인지, 그리고 명시적으로 변경하지 않을 것은 무엇인지.
이것이 번거로운 작업처럼 들릴 수 있습니다. 하지만 실제로는 그 반대입니다. 이는 같은 일을 두 번 반복하지 않게 해주는 작업입니다. 겉으로 드러난 요청만으로는 명확하지 않은 제약 조건 (constraints)을 글로 적어두면, Claude의 결과물이 코드베이스 (codebase) 옆에 따로 노는 것이 아니라 코드베이스 안으로 녹아들기 시작합니다.
매번 브리프 전체를 공유할 필요는 없습니다. 단지 그것을 적는 것만으로도 자신의 생각을 명확히 할 수 있으며, 이는 질문하는 방식을 변화시킵니다.
2. Claude에게 코드를 작성하기 전 이해한 내용을 요약해 달라고 요청하기
Claude에게 작업을 준 후 다음과 같이 물으세요: "무언가를 작성하기 전에, 당신이 이해한 작업 내용이 무엇인지, 그리고 어떤 가정 (assumptions)을 하고 있는지 말해줘."
이 작업이 속도를 늦출 것처럼 보일 수 있습니다. 하지만 그렇지 않습니다. 단 30초면 충분하며, 숨겨진 가정들이 200줄의 코드로 구현되어 버리기 전에 이를 표면화할 수 있습니다.
포착해야 할 가정들은 다음과 같은 것들입니다: "이 작업을 위해 새로운 모듈을 만들겠습니다" (당신은 새 모듈을 요청하지 않았습니다), 또는 "기존 데이터 클래스 (data class)가 없으므로 여기서는 딕셔너리 (dict)를 사용하겠습니다" (다른 파일에 이미 존재하지만, 당신이 붙여넣지 않았을 뿐입니다). 이러한 것들은 Claude에게는 그 순간 당연하게 느껴지는 작은 결정들이지만, 6번의 커밋 (commit)이 지난 후 당신에게 마찰을 일으키는 원인이 됩니다.
3. 모든 AI 출력물을 최종 결과물이 아닌 초안 (draft)으로 취급하기
가장 중요한 태도의 변화는 이것입니다: Claude의 출력물은 당신의 사고를 위한 시작점이지, 완성된 결과물이 아닙니다.
이것이 모든 것을 다시 작성해야 한다는 뜻은 아닙니다. 이는 당신이 신뢰하는 주니어 엔지니어의 PR (Pull Request)을 읽는 방식과 같아야 한다는 의미입니다. 즉, 대부분 맞을 것이라는 가정하에 읽되, 배포하기 전에 이를 완전히 이해해야 할 책임이 있다는 뜻입니다.
AI 보조 코드로 인해 문제를 겪는 개발자들은 AI를 너무 많이 사용하는 사람들이 아닙니다. 그들은 AI의 결과물을 비판적으로 검토하지 않고 그대로 수용하는 사람들입니다. 코드는 작동하고, 그들은 다음 단계로 넘어가며, 두 개의 기능이 더 지나고 나면 아무도 설명할 수 없는 무언가를 만들어 놓게 됩니다.
근본적인 문제: 맥락 없는 자신감
AI가 생성한 코드에는 상황을 악화시키는 미묘한 특성이 있습니다. 바로 기본적으로 매우 자신감 있어 보인다는 점입니다. 포맷팅은 깔끔하고, 네이밍 (Naming)은 합리적이며, 구조는 그럴싸합니다. 잘못된 가정을 하고 있을지도 모른다는 명백한 징후가 보이지 않습니다.
사람이 작성한 코드는 불확실성을 드러내는 경향이 있습니다. "이게 맞는지 모르겠다"라고 적힌 주석, 혼란을 드러내는 변수명, 혹은 무언가 미뤄졌음을 알리는 TODO 등이 그것입니다. AI의 출력물은 그렇지 않습니다. 근본적인 가정이 틀렸을 때조차 완성된 것처럼 보입니다.
이는 일반적인 디버깅 본능인 "맞아 보이면 아마 맞을 것이다"라는 생각이 제대로 적용되지 않음을 의미합니다. 단순히 시각적으로 훑어보는 것이 아니라, 출력물을 적극적으로 심문해야 합니다.
사소하지 않은 AI 출력물에서 확인해 볼 가치가 있는 구체적인 사항들은 다음과 같습니다:
- 상태(State)와 소유권(Ownership): 이 함수가 알아야 할 것보다 더 많은 외부 상태를 알고 있는가?
- 에러 핸들링 (Error handling): 존재한다고 가정했던 것이 없을 때 어떤 일이 발생하는가?
- 네이밍 컨벤션 (Naming conventions): 이것이 코드베이스의 나머지 패턴과 일치하는가, 아니면 스스로 만들어낸 것인가?
- 암시적 의존성 (Implicit dependencies): 이것을 다른 모듈로 옮겼을 때 무엇이 깨지는가?
이 중 어느 것도 Claude를 의심하라는 뜻이 아닙니다. 무언가 맞지 않을 때 이를 알아차릴 수 있을 만큼 당신의 시스템에 대해 충분히 명확한 그림을 가지고 있어야 한다는 뜻입니다.
더 깊이 파고들고 싶다면 활용할 수 있는 무료 리소스
저는 위에서 설명한 것과 같은 보이지 않는 혼란을 쌓지 않으면서 Claude와 함께 제품을 출시(ship)하고자 하는 개발자들을 위해 특별히 프롬프트 템플릿, 출시 체크리스트, 워크플로우 구조를 포함한 스타터 팩(starter pack)을 준비했습니다. 프롬프트 기술(prompt tricks)이 아닌, 유지보수성(maintainability)과 워크플로우 설계에 초점을 맞추었습니다.
이것은 무료이며 추가 판매(upsell)는 없습니다: Ship With Claude — Starter Pack
이 리소스는 인디 빌더(indie builders)와 초보 창업자를 대상으로 하지만, 혼자 작업하든 소규모 팀에서 작업하든 그 원칙은 동일하게 적용됩니다. 핵심 아이디어는 Claude 세션을 마쳤을 때, 시작할 때보다 코드베이스(codebase)를 더 잘 이해하고 있어야 한다는 것입니다. 그 반대가 되어서는 안 됩니다.
목표는 Claude를 덜 사용하는 것이 아닙니다. 여러분이 만들고 있는 것을 스스로 통제할 수 있는 방식으로 Claude를 사용하는 것입니다.
속도는 실제로 빠릅니다. 하지만 유지보수성과의 트레이드오프(tradeoff) 또한 실재합니다. 두 가지 중 하나를 선택해야 하는 것은 아니지만, 어떻게 작업할지에 대해 의도적(intentional)이어야 합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기