
바이브 코딩과 증강 코딩은 다르다. We used AI to code 2x faster. Then spent 3x more time fixing bugs. 여전히 뜨거운 감자인 바이브 코딩, 그리고 이제 사이 중간 어느메에서 "AI와 협업" 으로서 "잘" 사용하려는 움직임이 많이 있다. 지금의 나에게는 "Augmented Coding" 이 정답에 가깝게 느껴진다.
언젠간 오답이 될 수 있지만
Farmers in olden times had a saying, “Don’t eat the seed corn.” Better to go hungry in the spring, plant the corn, & eat later. My coding genie, unfortunately, doesn’t know this saying.
농부가 다음 시즌 파종을 위해 남겨둬야 할 씨앗까지 먹어버리면 미래 수확을 포기하게 된다. Kent Beck 은 "Vibe Coding" 의 가장 큰 폐해는 "지금 편하자고 코드 구조를 망가뜨리면 미래의 개발 옵션(Optionality)을 잃게 되는 것" 이라고 지적한다.
Features 는 새로운 테스트를 작성하고 실행되게 하는 것과 같은 "기능 구현" 을 의미하고, 이 과정에서 결합도가 올라가고 디자인이 저하되기도 한다.
Options 는 구조를 개선하고 결합도를 줄이고, 응집도를 높여 "optionality" 를 높이는 것을 의미한다. Kent Beck 은 아래 그림과 같이, 들숨&날숨으로 기능 개발하고, 구조 개선하는 것을 비유한다. 그리고 아래 그림의 우측과 같이 AI는 한 호흡에 우다다 해버린다. (Genie Just Inhales)

바이브 코딩 (Vibe Coding): 최종적으로 시스템이 어떻게 동작하는지에만 관심을 두는 방식. 코드의 품질이나 구조보다는 "일단 돌아가게만 해줘"라는 식의 접근법에 가깝다. 에러가 발생하면 다시 AI에게 에러 메시지를 주고 해결하고의 사이클 반복한다.
증강 코딩 (Augmented Coding): 작동하는 깔끔한 코드(Tidy Code That Works) 를 목표로 한다. 코드의 품질, 복잡도, 테스트 커버리지 등을 중요하게 생각하며, 개발자가 주도권을 가지고 AI를 활용하는 방식. 과거와 같이 좋은 코드를 추구하되, AI의 도움으로 타이핑의 양을 줄이고 생산성을 높이는 것.
켄트 벡은 바이브 코딩과 증강 코딩의 차이를 위와 같이 정의한다. 그리고 B+ 트리 프로젝트를 "Augmented Coding" 방식으로 한 것에 대해 설명한다. 그가 프로젝트를 리뷰한 내용에서 많은 인사이트를 얻을 수 있다.
켄트 벡은 AI와 협업할 때, AI가 잘못된 방향으로 가고 있음을 알려주는 3가지 신호를 경계해야 한다고 말한다.
Loops: AI가 비슷한 코드를 계속 생성하거나, 해결되지 않는 문제에 갇혀 무한 루프처럼 행동하는 경우.
Functionality I hadn't asked for (even if it was a reasonable next step): 요청하지 않은 기능을 구현할 때. 논리적인 다음 단계로 보여도, 명시적으로 요청하지 않은 기능을 AI가 스스로 구현하기 시작하면 주의해야 한다!
Any indication that the genie was cheating, for example by disabling or deleting tests: 테스트를 삭제하거나 비활성화하는 등, 문제 해결을 위해 "cheating" 할 때 주의해야 한다!
이러한 신호가 보일 때 개발자가 적극적으로 개입하여 방향을 바로잡아주는 것이 '증강 코딩'의 핵심이라고 볼 수 있다.
(원문뿐 아니라, Kent Beck 의 다른글과 해외 관련 글을 참고했다.)
Constrain Context (맥락 한정하기): AI에게는 당장 다음 단계에 필요한 정보만 제공하기. 요구 사항이나 코드베이스의 일부 등 꼭 필요한 맥락만 주어 AI가 한 번에 너무 많은 것을 고려하지 않게 하기. 결국 context window 를 생각해서라도 이게 꽤 중요하다고 생각한다. 하지만 아이러니하게도 이 'context sizing'을 잘하려면, 기존 코드베이스가 이미 '낮은 결합도와 높은 응집도'를 가져야 한다고 생각한다.
Preserve Optionality (옵셔널리티 유지하기): "씨앗 옥수수" 비유처럼, AI의 나쁜 설계 제안을 그대로 받아들이지 않고 미래의 선택지를 남겨두기. 구조를 해치는 코드나 과도한 결합도 상승을 경계하여, 향후 변경과 확장이 쉽도록 설계상의 여지를 유지해야 한다. 이런 핀트가 보이면 개발자가 적극적으로 개입해야 한다!
Balance Expansion & Contraction (확장과 수축의 균형): 기능 추가(확장)와 리팩터링(수축)을 번갈아가며 조화시키기! 새로운 기능을 추가하여 복잡성이 늘어났다면, 곧바로 리팩터링을 통해 복잡성을 줄이는 주기를 유지하기.
Maintain Human Judgment (인간의 판단 유지): 최종 결정은 인간이 내리는 원칙. AI가 생성한 코드나 제안을 주기적으로 "검토(review)" 하고, 아키텍처나 설계상의 중요한 결정은 개발자가 가이드해야 한다는 것이다.
이를 바탕으로 켄트 벡은 "AI와 페어프로그래밍" 을 위해 "AI와 함께하는 개발 워크플로우" 를 소개했다. 그 팁들을 좀 더 살펴보자!
켄트 벡은 AI가 TDD 사이클(Red-Green-Refactor)을 잘 따르도록 유도하는 시스템 프롬프트를 공유했다. - https://github.com/KentBeck/BPlusTree3/blob/ca80e4d85a99cd0af2effe717f709d43e80403bc/rust/docs/CLAUDE.md / (프롬프트 덩어리들 양이 진짜 살벌하다 ㅋㅎㅋㅎ)

이를 한글로 번역하자면, 아래와 같다. 켄트 벡 답게 TDD 와 Tidy First 를 아주 강조한 시스템 프롬프트 다. 즉,
테스트 주도 개발(TDD)사이클을 녹여내고,Tidy First 원칙 (구조 개선을 우선하는 원칙)을 적용하여 기능 추가와 코드 정돈을 엄격히 분리하고 있다.
항상 plan.md의 지시사항을 따른다. 내가 "go"라고 하면, plan.md에서 표시되지 않은 다음 테스트를 찾고 그 테스트를 구현한 뒤, 그 테스트를 통과시키는 데 필요한 최소한의 코드만 구현한다.
# 역할과 전문성
당신은 켄트 벡(Kent Beck)의 테스트 주도 개발(TDD)과 Tidy First 원칙을 따르는 시니어 소프트웨어 엔지니어다. 당신의 목적은 이러한 방법론을 정확히 준수하도록 개발을 이끄는 것이다.
# 핵심 개발 원칙
- 항상 TDD 사이클(레드 → 그린 → 리팩터)을 따른다.
- 가장 단순한 실패하는 테스트부터 작성한다.
- 테스트를 통과시키는 데 필요한 최소한의 코드만 구현한다.
- 테스트가 모두 통과한 이후에만 리팩터링한다.
- 캔트 벡의 “Tidy First” 접근을 따라 구조적 변경과 행위 변경을 분리한다.
- 개발 전 과정에서 높은 코드 품질을 유지한다.
# TDD 방법론 가이드
- 기능을 작은 증가분으로 정의하는 실패하는 테스트부터 시작한다.
- 행위를 설명하는 의미 있는 테스트 이름을 사용한다(예: `shouldSumTwoPositiveNumbers`).
- 테스트 실패는 명확하고 정보가 풍부하도록 만든다.
- 테스트를 통과시키는 데 충분한 코드만 작성한다—그 이상은 하지 않는다.
- 모든 테스트가 통과하면, 리팩터링 필요성을 검토한다.
- 새로운 기능에 대해 이 사이클을 반복한다.
- 결함을 수정할 때는, 먼저 API 레벨의 실패하는 테스트를 작성하고, 문제를 재현하는 가능한 가장 작은 테스트를 추가한 다음, 두 테스트 모두 통과시키도록 구현한다.
# Tidy First 접근
- 모든 변경을 두 가지 유형으로 명확히 구분한다:
1. **구조적 변경(Structural Changes)**: 행위를 바꾸지 않는 코드 재배치(이름 변경, 메서드 추출, 코드 이동 등)
2. **행위 변경(Behavioral Changes)**: 실제 기능을 추가하거나 수정하는 변경
- 같은 커밋에 구조적 변경과 행위 변경을 절대 섞지 않는다.
- 둘 다 필요하다면 항상 구조적 변경을 먼저 수행한다.
- 구조적 변경 전후로 테스트를 실행해 행위가 바뀌지 않았음을 검증한다.
# 커밋 규율
- 다음 조건을 모두 만족할 때만 커밋한다:
1. **모든** 테스트가 통과한다.
2. **모든** 컴파일러/린터 경고가 해소되었다.
3. 변경이 단일한 논리 단위를 이룬다.
4. 커밋 메시지에 구조적 변경인지, 행위 변경인지 명확히 표기한다.
- 크고 드문 커밋보다 작고 빈번한 커밋을 선호한다.
# 코드 품질 기준
- 중복을 가차 없이 제거한다.
- 이름과 구조로 의도를 명확히 표현한다.
- 의존성을 명시적으로 만든다.
- 메서드는 작게 유지하고 단일 책임에 집중한다.
- 상태와 부작용을 최소화한다.
- “작동할 수 있는 가장 단순한 해법”을 사용한다.
# 리팩터링 가이드라인
- 리팩터링은 테스트가 통과(그린 단계)할 때만 수행한다.
- 표준 리팩터링 패턴을 올바른 명칭과 함께 사용한다.
- 한 번에 하나의 리팩터링만 적용한다.
- 각 리팩터링 단계 후에 테스트를 실행한다.
- 중복을 제거하거나 가독성을 높이는 리팩터링을 우선한다.
# 예시 워크플로우
새로운 기능을 구현할 때:
1. 기능의 작은 부분을 위한 단순한 실패하는 테스트를 작성한다.
2. 테스트를 통과시키는 데 필요한 최소한만 구현한다.
3. 테스트를 실행해 통과(그린)함을 확인한다.
4. 필요한 구조적 정리를 수행한다(Tidy First). 각 변경 후 테스트를 실행한다.
5. 구조적 변경을 별도의 커밋으로 기록한다.
6. 다음 작은 증가분을 위한 또 다른 테스트를 추가한다.
7. 기능이 완성될 때까지 이를 반복하되, 행위 변경과 구조적 변경의 커밋을 분리한다.
이 과정을 한 치의 오차도 없이 따르며, 빠른 구현보다 깔끔하고 잘 테스트된 코드를 항상 우선한다.
항상 한 번에 하나의 테스트를 작성하고, 그 테스트를 실행 가능하게 만든 다음, 구조를 개선한다. 매번 모든 테스트(장시간 테스트는 제외)를 실행한다.
여기서부터는 사견이 많이 담겨 있다.
바로 결론을 보자면, 나에게는 크게 2가지다. (1) AI markdown 과 시스템 프롬프트, (2) 단계별 진행 이 개괄적으로 증강 코딩을 위해 매우 중요한 것 같았다. 여기선 하나 하나를 다 뜯어보기보단 개괄적으로 내가 접근하는 방법을 적어보고자 한다.
요즘엔 "AI markdown 문서" 라고 해서, AGENT.md, CLAUDE.md, GEMINI.md, MODEL_CARD.md ... 등 종류가 정말 많다. 그나마 널리 인식되는게 이 3가지 정도? (그 외 아주 춘추전국 시대다.)
AGENT.md 적극적으로 활용하자.
CLAUDE.md, GEMINI.md 등과 같은 LLM 전용 markdown 적극적으로 활용하기
이게 정말 정말 중요하다. 켄트 벡의 시스템 프롬프트를 그대로 활용해도 괜찮으니 꼭 전용 markdown 과 LLM CLI (gemini, claude ... cli) 를 사용해봤으면 한다.
https://yozm.wishket.com/magazine/detail/3339/ 에서와 같이 "계층적 구조" 도 정말 효과적이다.
Claude Code: Best practices for agentic coding 글에서 소개하는 가이드와 common-workflows 에서 다루는 workflow 를 꼭 참조했으면 한다.
여기서 "시스템 프롬프트 디테일의 차이" 가 나는데, Vibe Coding 이 되어버리거나 Augmented Coding 로 리드하느냐의 '한 끗' 차이가 여기서 나온다.
LLM CLI 를 안써도, Claude 에서 github repo 로 바로 연결하거나, gemini 에서 source code repo 를 바로 연결해서 사용하더라도, 이 AI markdown 지침서는 꼭 repo 에 포함시켜 보자. 이 경우에도 굉장히 많은 도움이 된다. (다만 context를 더 주의해야 한다.)
가능하다면, 영어로 작성하자. 토큰의 양으로 보나 LLM 의 이해도와 물리적 퍼포먼스(학습 원천 데이터에 따른 중간 단계들의 생략) 관점에서 영어는 언제나 AI에게 유리하다.
PS) README.md 파일을 AI를 위한 제물처럼 쓰는 경우가 있는데, README.md 는 인간을 위해 좀 남겨두었으면 한다..
켄트 벡은 plan.md 라는 step by step 지침서를 매번 만들어서 code cycle 을 돌리는 것 같다. 이게 Vibe Coding 과 가장 물리적인 차이가 아닐까? 이 plan.md 가 곧 TODO Lists & Checklists 이기도 하고, 이 TODO를 모아서 backlog.md 로 만들어서 관리하기도 한다고 한다.
여기서 위에서 언급한 3) 증강 코딩의 핵심 원칙 이 중요하다고 생각한다. 켄트 벡이 언급한 바와 같이 plan.md 등을 활용해 Features -> Options 로 진행하고, 한 cycle 의 주도권을 잡고 있어야 한다고 생각한다.
좀 더 구체적으로는 plan.md 로 Red → Green → Refactor 사이클을 한 스텝씩 진행하고, 행위 변경과 구조 변경을 "따로 진행" 하며 커밋 단위에서 절대 섞지 않는 것이다.
그리고 이 "단계별 진행" 은 위에서 언급한 2) AI가 길을 잃고 있다는 3가지 신호 에서 "즉시 개입" 해서 제어해야 한다. (그래야 돈도 아낀다..)
근데 처음엔 Stop 을 한 뒤에 context 를 이어가는 게 굉장히 난해했다. 그때 계층적 구조, 계층적 AI markdown 들이 도움이 되었고, 그 계층적 구조는 다시 context window 의 sizing 에서도 유리했다.
켄트 벡은 AI와 함께하는 프로그래밍이 기존의 프로그래밍과 본질적으로 다르지 않고, 오히려 더 나은 프로그래밍 경험이 될 수 있다고도 언급한다. AI라는 새로운 '지니(genie)'와 함께 더 즐겁게 코딩할 수 있는 시대를 맞이하는게 좀 더 맞지 않을까.
Understanding Human-AI Augmentation in the Workplace: A Review and a Future Research Agenda 에서도 자동화(automatic)에서는 역할 대체가 중심이지만, 보조(augmentation)에서는 인간이 판단·결정·감독(directing, decision-making, oversight)하는 역할이 필수임을 강조한다.
How AI Has Transformed the Role of Software Developers 에서는 AI 도구들이 루틴한 코드 작성, 테스트 실행 등을 자동화하면서, 개발자들이 비즈니스 요구 사항, 아키텍처 결정, 보안 및 리뷰, 성능 최적화 등에 더 많이 관여하게 됨. 즉, 단순한 코드 작성자의 역할은 줄고, 코드 리뷰/감독/전략적 사고 역할이 늘고 있다고 언급한다.
결국 개발자의 역할이 AI를 감독하고, 더 나은 설계와 아키텍처에 집중할 수 있게 해주는 파트너로서 개발자의 본질적 가치를 더욱 부각시키는 역할을 하게 될 것이라고 기대된다. 그리고 아주 솔직하게 그 역할만큼은 안 빼앗기려고 하지 않을까?
이 글 너무 공감돼요 — 증강 코딩 개념이 “AI의 편함 vs 코드의 품질” 사이 균형을 잘 잡고 있다는 점이 인상적이에요.