Intro 👋

다루지 않는 것들 ⛔

  • LangChain, RAG와 같은 LLM을 서비스 관점에서 바라봤을 때 유용한 내용들
  • 객관적인 지식 혹은 학술적인 내용들
  • 지금 시점 앞의 이야기, 약간이라도 뒤의 이야기들

다루고 싶은 내용들 ✅

  • LLM을 사용자 관점에서 바라봤을때 경험한 내용들
  • 주관적인 의견 그리고 직접 해보며 경험했던 내용들
  • 지금 시점에 유용하다고 느꼈던 것들

영감을 받은 것들 💭


Vibe Coding을 시작해본 계기 🆕

처음에는 반감으로 시작했습니다 🤬


‘XDD’ 뇌절과 비슷한 종류의 피로감

Image.png

  • 용어에 대한 반감은 뇌절에서 시작됩니다.
  • 주로 탁월한 아이디어에 뭔가를 더 붙이거나 지엽적으로 분류하여 편승하는 느낌으로 진행되는 것 같습니다
  • 한동안 ~DD로 끝나는 용어의 도배로 지지부진함과 피로감을 느꼈던 적이 많습니다.

더군다나 이런 파생 용어를 사용하시는 분들이 약간 더 상대방이 이 용어를 안다고 전제하고 이야기 하시는 경향이 많이 보였어서 조금 더 피곤함을 느꼈다고 생각했던 것 같습니다. “내가 알고 있는걸 모르면 트렌디 하지 못한 사람, 내가 모르고 있는걸 알면 오버엔지니어링 혹은 힙스터”


그런데 요즘 Hacker News, Geek News 등을 보면..

Image.png


컨텍스트에 대한 피로감

  • 이전에 클로드 코드 출시 전에 CLI를 클라이언트로 LLM을 붙여본 경험이 있었음
  • 그 때 직관과 상당히 어긋나는 부분은 ‘대화형 인터페이스’ 이면에 숨겨진 컨텍스트를 유지하는 무식한 방식

실제로 인터페이스를 붙여보시면 보이는 것들

Image.png

  • 하나의 대화에서 이전까지의 모든 대화 내용을 보내면서 컨텍스트를 유지해야 한다.
  • 즉 위의 이미지에서 점선의 길이가 의미하는것은 아래와 같다
    • 개발자 입장에서는 요청 페이로드의 크기
    • llm 벤더 입장에서는 입력 토큰의 크기💰
    • llm동작 원리상에서는 유지 할 수 있는 컨텍스트의 크기
    • 그리고 f(n) = f(n- 1) + n의 구조로 늘어난다

물론 실제로는 ‘에이전트’라고 불리는 서비스들이 서비스의 일환으로 컨텍스트를 압축해주지만, 정말 거의 대부분은 그 역시 llm을 기반으로 하기 때문에, 큰 프로젝트에서 사용하기에는 어느 순간 지나치게 비결정적인 면이 있고, 이부분은 지금도 그렇다고 생각합니다.

Image.png


그러다가 만나게 된 켄트백의 포스트, 그리고 세가지 통찰

  • 바이브코딩을 넘어 증강형 코딩
  • 놀랍게도 정말 또 뭔가 듣기 싫은 새로운 용어를 가져다 붙이셨지만, 통찰은 대단하다고 느꼈습니다. (저는 반골 기질이 있어 굳이 ‘증강형’ 코딩이라고 직접적으로 언급하진 않겠습니다)
  • 길지 않아 직접 읽어보셨으면 좋겠지만, 요약하자면 다음과 같습니다.

켄트백의 통찰 1 : TDD접근 방법

  • 바이브 코딩에서는 코드는 신경쓰지 않고 시스템 동작만 신경쓴다. 에러가 있으면 ‘이런 에러가 있다’고 얘기하고, 고쳐주길 기대한다.
  • 증강형 코딩에서는 코드를 신경쓴다. 코드의 복잡도, 테스트, 테스트 커버리지가 중요하다.
  • 증강형 코딩에서는 기존의 코딩과 마찬가지로 “Tidy Code That Works”, 즉 ‘작동하는 깔끔한 코드’를 중요시한다. 단지 예전만큼 타이핑을 많이 하지 않을 뿐이다.

켄트백의 통찰 2 : AI의 치팅과 개발자의 개입

  • 비슷한 행동을 반복한다 (무한루프 등)
  • 내가 요청하지 않은 기능 구현. 그게 논리적인 다음 단계가 맞을지라도.
  • 테스트를 삭제하거나 비활성화는 등, AI가 치팅하는 걸로 느껴지는 그 외 모든 신호

참고로 제가 직전까지 겪었던 가장 자주 발생하는 치팅은 하드코딩이었습니다. 처리하기 까다로운 엣지케이스를 else { 하드코딩된 값 } 으로 치팅하는 경우가 많아서 욕이 늘었습니다.


켄트백의 통찰 3 : TDD를 주지시키기 위한 프롬프트

## 핵심 개발 원칙

- 항상 TDD 사이클을 따르세요: Red → Green → Refactor
- 가장 간단한 실패하는 테스트를 먼저 작성하세요
- 테스트가 통과하는 데 필요한 최소한의 코드를 구현하세요
- 테스트가 통과한 후에만 리팩토링하세요
- Beck의 "Tidy First" 접근법을 따라 구조적 변경과 행동적 변경을 분리하세요
- 개발 전반에 걸쳐 높은 코드 품질을 유지하세요

## TDD 방법론 가이드

- 작은 기능 증분을 정의하는 실패하는 테스트를 작성하는 것부터 시작하세요
- 행동을 설명하는 의미있는 테스트 이름을 사용하세요 (예: "shouldSumTwoPositiveNumbers")
- 테스트 실패를 명확하고 정보성 있게 만드세요
- 테스트가 통과하도록 하는 데 필요한 코드만 작성하세요 - 그 이상은 안 됩니다
- 테스트가 통과하면 리팩토링이 필요한지 검토하세요
- 새로운 기능을 위해 사이클을 반복하세요

## 예시 워크플로우

새로운 기능에 접근할 때:

1. 기능의 작은 부분에 대한 간단한 실패하는 테스트를 작성하세요
2. 통과하도록 하는 최소한의 것을 구현하세요
3. 테스트를 실행하여 통과하는지 확인하세요 (Green)
4. 필요한 구조적 변경을 하세요 (Tidy First), 각 변경 후 테스트를 실행하세요
5. 구조적 변경사항을 별도로 커밋하세요
6. 다음 작은 기능 증분을 위한 또 다른 테스트를 추가하세요
7. 기능이 완성될 때까지 반복하세요, 행동적 변경사항을 구조적 변경사항과 별도로 커밋하세요

이 과정을 정확히 따르고, 빠른 구현보다는 항상 깨끗하고 잘 테스트된 코드를 우선시하세요.

항상 한 번에 하나의 테스트를 작성하고, 실행하게 한 다음, 구조를 개선하세요. 매번 모든 테스트를 실행하세요 (장시간 실행되는 테스트는 제외).

바이브 코딩을 진행 과정과 결과물 그리고 시연 🫵

  • 위의 프롬프트는 그대로 사용했고, 프로젝트에 대한 개요등을 추가적으로 작성했습니다.
  • Claude Code를 이용했습니다.
  • 여기 : Github 에서 확인 하실 수 있습니다.
  • $$누구나 지금 당장 설치 가능$$ 평생 무로 $$ 가입 필요? 📵 즉시 설치 가능 brew만 있다면 🫵 바로 fink 유저 누구나 가능 하도록 brew에 배포해두었습니다.
brew tap SmallzooDev/fink
brew install fink

작업중 느낀점 🤪

더 작은 기능에 대한 개발 요구, 더 구체적인 요구사항일수록 잘 동작한다

“큰 문제를 작은 문제 여럿으로"와 같은 격언은 아직도 통용되고, 저 이야기가 처음 나온 즈음 이상으로 더 의미있는 구문이 된 것 같습니다.

  • 아래 이야기될 내용과 중복될 내용이 많아 아래에서 조금 더 이야기 하겠습니다.

프로젝트의 구조와 설계, 기술 스택등은 개발자가 알고 시작하는게 좋다

“클로드야 Rust가 좋아? 아니면 Go가 좋아?”, “클로드야 ddd가 좋아 아니면 ddd안하는게 좋아?”, 와 같은 질문은 의미가 없는 것 같습니다. 항상 A는 이런면에서 좋으며, B는 이런면에서 좋다고 답변받을 뿐이니까요

  • 저는 원래 써보고 싶었던 ratatui라는 tui 라이브러리가 이미 있었습니다, 하지만 그걸 영리하게 찾아오지는 않습니다.
  • 구조도 마찬가지입니다 저는 아래와 같은 구조를 원했습니다. 뭔가 cli로 요즘 유행하는 gemini code나, claude code와 같은 것들과 파이프라이닝을 해보고 싶었거든요

Image.png

결론적으로 적당한 뭔가 라이브러리로 tui를 그려줘, 각 계층을 기능 단위로 나눠서 리팩토링해줘 와 같은 것들은 높은 확률로 실패합니다 . 제가 직접 인터페이스를 빼고 몇가지 구현을 한 뒤에 그걸 이용해서 리팩토링을 요구하면 잘 동작합니다 즉 사전질문 > 개발자의 선택 > 선택을 통한 구체적인 요구사항이 훨씬 효율적입니다.

컨텍스트 유지 보다 중요한 것은 작은 단위의 빠른 컨텍스트 복구이며, 프롬프트(CLAUDE.md를 포함한)와 단위 테스트 코드들은 이것을 달성하는데 엄청 큰 역할을 한다.

  • 일단 AI가 치팅을 하거나 이상한 짓을 시작하는 시점은 생각보다 빠르게 옵니다.
  • 그리고 대부분의 경우 위에 언급한 두가지를 포함해서 사용자가 모호한 요청, 혹은 코드베이스적으로 너무 광범위한 컨텍스트를 요구하거나 판단이 필요한 요청을 제시했을 가능성이 높은 것 같습니다.
  • 그러한 경우 빠르게 checkout을 통한 green phase로의 전환, claude.md혹은 프롬프트를 통한 최소한의 컨텍스트를 제외한 모든 컨텍스트를 clear이 효과적이었습니다.

필요한 경우

  1. 테스트를 직접 작성해주거나

  2. 인터페이스 혹은 상위 계층을 직접 정의하거나

  3. 정의한 인터페이스 사용 예시 코드까지를 작성해두고 컴파일 에러를 유발시키거나

하면 더 치팅을 방지 할 수 있었습니다.

Screenshot 2025-07-14 at 3.47.53 PM.png

TL; DR 🤓

  1. 작은 작업 단위, 명확한 요구사항, 테스트코드와 같은 것들은 컨텍스트를 작게 만들어 준다.
  2. 작은 컨텍스트를 유지 할 수 있다면 실무와 같은 큰 코드베이스에서도 llm agent를 이용한 개발이 가능하다.
  3. 그리고 위의 두가지를 달성하기 위해서는 적절한 개발자의 개입과 프롬프트를 이용한 빠른 컨텍스트 복구가 매우 중요하다.
  4. 그런 당신을 위한 프롬프트 관리앱 fink ($$누구나 지금 당장 설치 가능$$ 평생 무로 $$ 가입 필요? 📵 즉시 설치 가능 brew만 있다면 🫵 바로 fink 유저 누구나 가능)

감사합니다! 🙇‍♂️

Github 들어가서 fink 별좀요..