🤖 바이브코딩 대실패
최근 두 편의 글을 작성했다. 쿼리 개수 측정 라이브러리 개발기를 정리한 글로, 1편과 2편으로 이어지는 시리즈 글이다.
- API 요청 당 쿼리 개수를 알고 싶어 라이브러리까지 만든 이야기 — 라이브러리 제작
- API 요청 당 쿼리 개수를 알고 싶어 라이브러리까지 만든 이야기 — 호환성의 늪에서 헤엄치기
이 라이브러리를 한참 개발하던 시기가 1~3월 사이였는데, 이 때가 마침 ‘바이브코딩’ 이라는 용어가 만들어지는 시점이었다.
바이브 코딩은 AI와 협업하여 자연어로 코드를 작성하는 새로운 개발 방식입니다. 2025년 초, OpenAI의 공동 창립자이자 전 테슬라 AI 책임자인 안드레이 카파시(Andrej Karpathy)가 이 개념을 처음 제안했으며, 이후 AI 커뮤니티와 에듀테크 분야에서 빠르게 주목을 받았습니다.
대단한 개념은 아니고, 그냥 LLM 에게 만들고 싶은 기능을 자연어로 설명하면 LLM 이 해당하는 기능을 수행할 수 있는 코드를 작성해주는 것이다. (대단하다고 봐야하려나?)
동일한 시기에 나도 LLM 에게 여러가지 질문을 하며 라이브러리를 개발하고 있었다. 아예 무지한 영역에 대해 설명을 부탁하기도 하고, 옅은 지식 조각을 짜맞춘 내 추론이 맞는지 질문하기도 했다. 때로는 직접 코드를 만들어달라고 부탁하기도 했다. 거의 매일 퇴근 후 한 두시간씩, 한 달 정도는 그렇게 바이브코딩을 시도했던거 같다.
한 달 후 결과는 어땠을까? 안타깝게도 바이브코딩은 라이브러리 코드를 단 한 줄도 개선하지 못한 체, 내 머리 속을 더 어지럽히는 결과만 낳았다. (이 때 정말 많이 화가 났었다.)
실질적으로 라이브러리를 개선하고 완성시키는 데에는 마지막 일주일 정도가 소요되었다. 직접 공식문서를 참고해서 기능을 완성하는데 이틀, 완성된 코드를 보기 좋게 정리하는데 하루, 그리고 나머지 기간은 테스트와 배포에 소요되었다.
이 일주일 동안 바이브코딩에 대한 생각을 정말 많이 했다. ‘왜 사람들은 바이브코딩에 열광하는 걸까?’, ‘바이브코딩이 정말 유의미한 걸까?’, ‘도대체 어떤 상황에 유용한거지?’ 등등…
이 시기에 MCP(Model Context Protocol)와 RAG(Retrieval-Augmented Generation)를 접하게 되었는데, 두 개념과 바이브코딩을 접합시켜 생각을 정리하면서 최종적인 결론을 내릴 수 있었다.
“바이브코딩은 객체지향 프로그래밍과 어울리지 않는다.”
🤖 MCP(Model Context Protocol)
바이브코딩과 객체지향 프로그래밍 대해 이야기 하기 앞서 MCP 와 RAG 에 대해 간단히 정리해야겠다.
MCP 는 이름 그대로 통신규약이다. 애플리케이션이 LLM 에 컨텍스트를 제공하는 방법을 표준화했다. 요즘은 아래 그림을 많이 활용하여 설명하는 것 같다.
모든 규약을 이해할 필요는 없고, 당장 통신 규약을 정의해야할 정도(통일해야 할 정도)로 여러 애플리케이션에서 너도나도 LLM 에게 컨텍스트 제공을 위해 힘쓰고 있다는 점만 알면 되겠다.
🤖 RAG(Retrieval-Augmented Generation)
RAG 는 LLM 이 기본적으로 소지하고 있는 데이터 소스 외에도, 독자적인 데이터베이스를 구축하고 이를 토대로 ‘검색’하여 답변을 더욱 정확하고 풍성하게 만들 수 있도록 돕는 개념이다. 할루시네이션 방지에도 도움이 되고, 적시성 문제도 해결이 된다. Advanced-RAG, Modular-RAG 등 여러가지 발전 형태가 존재하는데 핵심은 결국 동일하다.
“LLM 에게 더 많은, 더 풍부한 컨텍스트를 제공해서 더 높은 완성도의 답변을 얻자.”
구현 방식은 여러가지가 있겠지만, 기본적인 구조를 설명하면 아래와 같다.
- LLM 에게 질문을 던진다.
- Text2Vector, Text2Cypher 등과 같은 변환기를 통해 질문을 DB 조회용 언어로 변경한다.
- DB 에서 데이터를 조회한다.
- 조회 결과를 기반으로 응답을 생성한다.
- 사용자에게 응답을 반환한다.
실제로 요즘 팀 내에서 GraphDB 기반 RAG 를 활용한 여러가지 실험을 진행하던 중 흥미로운 결과를 얻게 되었다.
본래 키워드 검색(text-matching)을 기반으로 응답을 생성하는 RAG 활용 모델과 유사도 비교(embedding-vector)를 기반으로 응답을 생성하는 RAG 활용 모델을 각기 나누어 실험중이었는데, 두 RAG 를 합쳐서 하나의 모델로 만들어보니 답변의 완성도가 획기적으로 높아졌다.
완성도가 높아진 원리는 키워드 검색과 유사도 비교가 더해진 덕분에 LLM 에게 전달되는 컨텍스트량이 다각도(다차원)으로 풍부해졌고, 이에 따라 LLM 이 더 높은 수준으로 사용자의 질문을 해석하여 답변을 생성할 수 있기 때문인 것으로 결론지었다. (이외에도 여러가지 요소가 결론에 힘을 더해줬지만, 글이 산으로 가므로 생략.)
🤖 바이브코딩과 객체지향 프로그래밍
다시 바이브코딩과 객체지향 프로그래밍으로 돌아와서…
바이브코딩은 결국 ‘LLM 에게 질문을 던지고 결과물을 얻는 행위’ 다. 그리고 앞서 이야기 했듯 LLM 는 주어진 컨텍스트가 풍부하면 풍부할수록 더욱 높은 수준의 답변을 제공한다. 반대로 이야기하면 컨텍스트가 부족하면 부족할수록 형편없는 답변을 제공한다는 것이다. 그래서 너도나도 LLM 에게 데이터소스를 제공하려다가 MCP 가 등장했고, 우리 팀도 RAG 를 활용한 실험에서 컨텍스트가 풍부해야한다는 결론을 얻었다.
그에 반해 객체지향 프로그래밍은 어떤가? 흔히 SOLID 라고 불리는 다섯가지 원칙을 떠올려보자.
- SRP(Single responsibility principle)
- OCP(Open/closed principle)
- LSP(Liskov substitution principle)
- ISP(Interface segregation principle)
- DIP(Dependency inversion principle)
이 다섯가지 원칙은 모두 ‘나중에 봤을 때 더 이로운 코드를 작성’ 하는 것을 목표로 한다. 거기서 특히 SRP(Single responsibility principle) 원칙은 컨텍스트를 가능하면 작게 쪼개어 나눌 것을 강조한다. 인간의 인지 능력에는 한계가 있기 때문에, 컨텍스트를 작게 쪼개어 나누어 좁은 영역에만 집중할 수 있도록 돕는 코드를 작성하라는 것이다.
컨텍스트가 풍부해야 완성도가 높아지는 바이브코딩과 컨텍스트를 작게 쪼개어 나누어 좁은 영역에만 집중할 수 있도록 돕는 객체지향 프로그래밍은 완전히 정반대의 패러다임을 가지는 것을 알 수 있다.
LLM(claude) 가 Spring Data JPA(Hibernate)의 트랜잭션 동작 특성을 이해하고 올바르게 답변하는지 실험해본 결과다.
어느정도 트랜잭션 동작 특성을 이해하고 있다면 위 답변이 오답이라는 걸 알 수 있다.
실제로는 registerMember
메서드에서 진행된 트랜잭션이 이미 commit mark 를 찍은 후라
handleMemberRegisteredEvent
에서 진행되는 트랜잭션에서는 데이터 변경이 일어나지 않는다.
데이터 변경을 일으키고 싶다면 추가 트랜잭션을 개방(@Transactional(propagation = Propagation.REQUIRES_NEW)
)해야 한다.
Spring, Java, Kotlin, Hibernate 등의 객체지향 프레임워크 진영에서 LLM 에게 컨텍스트를 제공하는 자체적인 RAG 를 준비하지 않는 이상 계속해서 사용자의 질문 기반으로만 컨텍스트를 유추하고, 잘못된 답변을 내놓을 수 밖에 없을 것이다.
🤖 상상의 나래를 펼치자면
객체지향과 패러다임이 충돌하기 때문에 어울리지 않을 뿐, 스크립트 중심의 언어에서는 바이브코딩이 강력한 건 사실이다. 특히나 한 파일에 모든 컨텍스트를 담는 상황에서는 바이브코딩이 정말 잘 어울린다. 때문에 100% 바이브코딩을 배척할 순 없다. 분명히 활용할 줄 알아야 한다.
언젠가 Java, Kotlin, C# 등의 객체지향 프로그래밍 언어 관리 진영과 Spring, Django 같은 서버 프레임워크 진영에서도 RAG 에 활용 가능하도록 MCP 에 맞춘 데이터 소스를 제공한다면 바이브코딩으로 충분히 기능 구현이 가능할 수도 있지 않을까 상상해보곤한다. 물론 유기적으로 얽힌 방대한 양의 컨텍스트를 모두 받아들이고 답변을 생성하려면 어마무시한 크기의 메모리가 필요할 것 같지만, 또 어디선가 천재 엔지니어가 나타나서 최적화 해주겠지.
그런 날이 오기 전까지는 객체지향 프로그래머에게 더 많은 기회와 도전이 주어질 것이라 생각한다. 바이브코딩이 계속되면서 수 없이 많은 유지보수하기 힘든 코드들이 쏟아져 나올 것이고, 이를 유지보수하고 개선할 수 있는 엔지니어가 필요할테니까. 그러러면 더욱 더 기초적인 부분에 대한 지식과 이해가 필요하겠다.
객체지향 프로그래머라면, 적어도 당분간은 브라우저 탭에 LLM UI 페이지보단 공식 문서 페이지를 더 많이 열어두자.
댓글남기기