제목부터 끌렸던 책이다. 한국어판 제목은 ‘바이브 코딩 너머 개발자 생존법’, 원제는’Beyond Vibe Coding: From Coder to Ai-Era Developer’. 최근에 개발자들을 만나면 빠지지 않는 주제가 AI와 관련된 이야기이고, 그 주제는 자연스럽게 성장과 미래로 연결된다. AI는 편한데 성장하고 있는지 모르겠다, 직접 짤 때보다 흥미가 느껴지는지 모르겠다 등 ‘Beyond Vibe Coding’라는 원제처럼 AI가 지닌 능력과 편리함 뒤에 우리가 어떤 방향으로 나아가야 할지 이야기를 자연스럽게 이어 나가게 되는 경우가 많았다.
초반부엔 바이브 코딩과 AI 보조 엔지니어링의 차이부터 말한다. 바이브 코딩이 자연어 중심의 대화를 통해 코딩을 이어 나가는 과정이라면, AI 보조 엔지니어링은 기존의 소프트웨어 개발 생명주기 전 과정을 그대로 사용하면서 적극적으로 AI를 활용하는 과정이라고 볼 수 있다. 그 과정에서 PRD나 작업 체크리스트 같은 문서를 활용하기도 하고, 기술 스택과 컴포넌트 구조를 명시하면서 내 의도대로 프로그래밍을 하는 과정으로, 다소 차이가 있겠다. 그런 관점에서 ‘의도 중심 프로그래밍’이라고 번역해 두었는데, 개발자가 최적의 경로를 AI가 찾을 수 있도록 조력하며 의도적으로 프로그래밍하는 과정이라고 느껴졌다.
그런 관점에서 아마 AI를 활용해 왔던 개발자라면 단순한 바이브 코딩과 명시적인 프롬프트 기반의 AI 보조 엔지니어링의 차이를 분명히 느껴왔을 것이다. 동료 디자이너가 Cursor나 Figma Make를 통해 화면 구현을 한다고 해도 분명 그 필드를 이해하고 있는 사람과 아닌 사람의 AI 활용 방식의 차이는 분명하다. 이건 개발자에 한정된 것이 아니라 반대로 개발자가 AI를 통해 디자인을 구현한다고 해도, 그 필드를 온전히 이해하고 있는 사람의 활용 방식을 ‘단순한 바이브’로 쫓기는 어렵다고 생각한다.
하지만 사실 이건 책에서도 언급하듯 완전히 배타적인 관계가 아니다. 두 방식을 결합해 사용할 수도 있고, PoC 단계에서는 바이브 코딩을, 이후에 고도화를 하게 된다면 그땐 좀 더 명시적인 AI 보조 엔지니어링을 통해 구현해 나가는 것이 가능하다.
두 번째 챕터에서는 프롬프트 작성에 대한 조언을 이어간다. 구체성 및 명확성, 반복적인 정제를 먼저 설명하고 있는데, 아마도 AI를 적극적으로 활용하는 사람이라면 자연스럽게 하고 있을 방식이기도 하다. 실제로 AI를 실무에 적용해 봤을 때 사용 언어나 환경, 결과 범위, 요구사항 및 제약 조건, 원하는 출력과 같이 명확하고 구체적으로 이야기를 해줘야 결과물이 좀 더 명확해지기 마련이었다. 반복적인 정제라 한다면 말 그대로 돌아온 결과물을 검토하고, 그 결과를 기반으로 추가적인 프롬프팅을 통해 좀 더 다듬는 과정이라고 볼 수 있는데, 경험상 이런 과정을 거쳐야 좀 더 온전한 결과를 얻어낼 수 있었고, 책에서도 설명을 통해 언급하고 있다.
프롬프트 방식에 대해서도 언급하고 있는데, 이제는 조금 익숙한 제로샷 및 원샷, 퓨샷 프롬프트와 더불어 사고의 연쇄(CoT) 프롬프트, 역할 프롬프트, 컨텍스트 프롬프트, 메타 프롬프트 등의 설명을 이어간다. 상황에 따라 걸맞은 프롬프트가 다를 수 있지만, 경험상 단계별로 생각하고 연쇄적으로 질문을 던지면서 최종 답변을 제공 받는 CoT 프롬프트를 가장 효과적으로 느끼고 있다. ReAct는 좀 더 최근의 에이전트와 가까운데, 책에서 언급되는 것처럼 ‘먼저 이 함수에 대한 테스트를 작성하고, 실행한 후 코드를 그에 맞게 조정하세요.’라는 프롬프트를 입력했다면, 테스트 작성이라는 ‘추론’ 단계를 보여준 후, 테스트 실행이라는 ‘행동’을 이어간다. 그리고 그 결과에 따라 코드 조정을 수행하는 과정을 설명하게 되는, 일종의 워크플로가 실행된다고 볼 수 있다.
이어 프롬프트를 모호하게 작성하거나, 한 번에 너무 많은 일을 시키는 과부하 프롬프트를 입력하거나, 일관성이 부족한 프롬프트를 입력하는 경우 안티 패턴에 가깝다고 언급하고 있다. AI를 꾸준히 활용하고 경험해 왔다면 경험해 본 바와 크게 다르지 않을 것 같다.
두 번째 파트에 들어서는 AI를 실무에 도입했을 때의 조언을 풀어내고 있다. AI 보조 워크플로 안티 패턴으로 언급된 게 ‘제자리걸음’이라는 명명한 패턴인데, 작업 방식은 아래와 같다.
작은 버그의 수정을 요청한다 → AI가 그럴싸한 변경 사항을 제안한다 → 이 수정으로 인해 다른 문제가 발생한다 → AI에 새로운 문제를 해결하라고 한다 → 이로 인해 두 가지 문제가 추가로 발생한다
이 과정이 계속 반복되는 걸 ‘제자리걸음’이라고 표현하는데, 실제 개인적으로 외주사로부터 전달받은 프로덕트의 코드 레벨을 제대로 숙지하지 못한 채 AI에게 요청했을 때 비슷한 경험이 있었다. 물론 몇 개월 전이라 지금보다 성능이 부족한 모델이었지만, 한정된 시간으로 애초에 그 코드 레벨을 온전히 파악하지 못했기에 진짜 문제가 뭔지 이해할 수 있는 사고 체계를 갖출 수가 없었다. 다른 사례로는 최근에 사내의 디자이너분이 Cursor를 이용해 바이브코딩을 하고 있는데, 어느 정도 뼈대를 갖춘 PoC라 하더라도 작은 버그가 존재하고, 그 버그를 코드 레벨에서 살펴보면 이건 하나의 프롬프트에서 나올 수 없는 버그라 생각될 정도로 꽤 많은 문제가 중첩되어 있었다. 마치 하나의 CSS 이슈를 명확히 해결하지 못해 override하고, 그마저도 쌓임 맥락을 제대로 파악하지 못해 !important로 해결하려는 방식이 생각날 정도로, 문제를 올바른 방식으로 개선하는 것이 아니라 현재의 문제를 해결하기 위해 다른 문제를 만들어내는 ‘제자리걸음’이 생기는 경우라고 볼 수 있었다.
물론 그런 안티 패턴에도 불구하고 AI가 나온 이후의 개발 방식은 완전히 새로운 관점에서 접근해야 한다고 느끼고 있다. AI 이전에는 해당 기술 스택이나 언어를 모르면 기능을 온전히 구현하기 어려웠다. Stack Overflow를 통해 많이 찾았다고 하지만, 한두 가지의 이슈를 해결하는 거지, 전반적인 개발을 순차적으로 이어 나갈 수 있는 것은 아니었다. AI 이후의 개발은 소프트웨어 개발 자체를 근본적으로 바꾸는 일이면서 동시에 사람의 개입을 최소화하는 방향으로 나아가고 있다는 점이 여러 가지 측면에서 피부에 와닿고 있다.
책에서 실용적인 AI 보조 워크플로 패턴으로 제안하는 방식은 다음과 같다.
- AI의 초안 작성: AI 모델이 초기 코드를 생성한 후, 개발자가 이를 정제하고 리팩터링 및 테스트합니다.
- AI와 페어 프로그래밍: 개발자와 AI가 끊임없이 대화하며 긴밀한 피드백과 빈번한 코드 리뷰, 그리고 최소한의 컨텍스트만을 주고받습니다.
- AI를 사용한 검증: 개발자가 초기 코드를 직접 작성한 후 AI를 활용해 코드의 검증, 테스트 및 개선 작업을 진행합니다.
더 정확히는 제안이라기보다, 저자가 개발 과정에서 AI를 효과적으로 사용하는 여러 팀의 사례를 정리해 보니 개인 워크플로와 팀 워크플로 모두에서 꾸준한 효과를 나타내는 패턴이었다고 한다. 사실 나도 Cursor와 Claude Code를 활용하면서 가장 효과적인 패턴은 저 방식이었다. 물론 아직 AI를 활용해 코드의 검증 및 테스트까지는 진행해 보진 못했지만, 일반적으로 각 AI 플랫폼마다 존재하는 ‘Plan Mode’를 사용해서 전반적인 계획을 먼저 수립하게 하고, 그 계획을 검토한 후 방향성을 잡은 후에 작업을 이어가게 한다. 물론 간단한 작업 같은 경우는 ‘Agent Mode’나 ‘Accept edits’ 같이 바로 작업을 이어가게 하는 경우도 있지만, 그런 경우에도 반드시 작업 후에 git diff를 통해 변경점을 확인하고 적용한다. 결국 키워드는 검토와 인지라고 생각한다. 검토를 통해 수정된 코드가 적합한지 판단하고, 그 과정에서 이 코드가 현재의 프로덕트에 적용되고 있음을 인지하는 것이 중요하다. 검토와 인지가 제대로 진행되지 않으면 그 이후의 코드 베이스를 온전히 파악할 수 없고, 그 과정이 쌓이면 전체 맥락을 읽어내기 어려워진다. 당장의 문제 해결은 AI의 코드 생성과 동시에 일종의 기술 부채가 되어 버릴 수도 있다.
AI의 초안 작성의 경우 아직 개인 단위로만 주로 사용해서 고려하지 못했지만, 책에서는 협업 기반의 다양한 방식을 권유하고 있다. 예컨대, 같은 기능을 하는 유틸리티 함수의 경우 미리 합의를 해두거나, 함수형 컴포넌트만 사용한다는, 혹은 Axios 대신 Fetch API만 사용한다는 팀 단위의 컨벤션을 미리 정의해놓는 방식이다. 이를 명확히 해두지 않으면 하나의 프로덕트에서 여러 방식의 코드가 생성될 가능성이 있기에 필요하다고 느꼈다.
챕터 4를 통해 각 경력별로 현시점에서 AI를 어떻게 활용해야 하는지에 대해 언급하고 있는데, 시니어, 중급, 주니어 개발자를 나누어 설명하고 있다. 개인적인 생각으로는 경력과 완전 무관하진 않겠지만, 동시에 어떤 면에선 크게 다르지 않다고 느끼기도 한다. 풀어 말하면 시니어, 중급, 주니어에 따라 각자의 역할이 다르긴 하지만, AI를 활용하는 시대에 들어서면서 가장 역할이 많이 변한 게 주니어 개발자라고 느끼고 있다. 기존의 주니어 개발자는 생각의 스코프가 크지 않아도 무관했다. 물론 주니어 레벨 이상의 스코프를 적용하고 생각을 확장해 나가는 사람도 있었을 테고 회사 차원에선 큰 도움이 되었겠지만, 명확한 디렉팅을 주고 있는 선임 개발자가 있었다면 기능 개발 중심의 사고만으로도 충분히 본인의 역할을 잘 수행한다고 볼 수 있었다.
하지만 현재 회사가 주니어 개발자에게 요구하는 건 기존의 없던 사고 능력이다. 표면적으로는 채용 공고를 통해 ‘AI 활용 능력’이라고 명시하지만, 그 단순한 워딩 안에 숨겨진 뜻은 생각의 스코프를 얼마나 넓힐 수 있는지 보고 싶다는 의미로 해석할 수도 있다. 기존의 기능 중심의 개발에서 지금은 AI와 페어 프로그래밍을 해야 하기도 하고, 그 과정에서 피드백을 주고받는 사고가 필요하다. 피드백을 명확하게 주고받기 위해서는 책에서 언급된 것처럼 데이터 구조, 알고리즘, 메모리 관리, 동시성과 같은 개념을 제대로 이해하고 있어야 하며, 현재 프로덕트에 걸맞은 아키텍처에 대한 이해 또한 있어야 한다. 그래야 AI의 응답에 대해 정확히 원하는 방향으로 나아갈 수 있는데, 사실 이건 기존의 중급 개발자가 지니고 있어야 하는 능력이기도 하다. 그런 맥락에서 주니어 개발자를 안 뽑는다는 말이 나오는 거라고 생각하는데, 더 정확히 말하면 주니어 스코프에 머무르는 주니어 개발자를 뽑지 않으려 하는 게 요즘 채용 추세가 아닐까 생각되기도 한다. (먹고 살기 힘들다)
덧붙여 생각해 보면, 혹자가 말하는 것처럼 개발자가 더 이상 예전처럼 학습하지 않아도 된다는 말에 동의하기는 어렵다. 오히려 이제 주니어 개발자는 단순히 주니어의 마인드가 아니라 사수의 마인드로 AI의 코드를 지켜봐야 한다. 그 말인즉슨, 나의 코드 리뷰 능력으로 AI가 생성된 코드를 판단해야 한다는 말이기도 하다. 물론 대화를 이어가며 코드를 검증할 수도 있지만, 내가 코드를 검증할 수 있는 사고를 스스로 빠르게 할 수 있다면 즉시 피드백을 적용하고 유지보수에 적합한 코드를 적용할 수 있기에 더 적은 시간에 더 많은 생산성을 취할 수 있다. 물론 학습을 덜 해도 된다는 맥락은 기존의 새로운 라이브러리, 혹은 프레임워크, 좀 더 크게는 새로운 언어로 작업을 하고자 할 때 존재하던 가파른 러닝 커브를 드라마틱하게 낮춰줬다는 의미라고는 볼 수 있는 것 같다. 결국은 꾸준히 학습하는 것이 AI와 공생할 수 있는 가장 좋은 방법이라고 생각하기에 꾸준히 새로운 기술을 학습하고, 책에서 언급된 것처럼 ‘메타 스킬’을 키우는 것이 좋다고 생각한다. (먹고 살기 힘들다 222)
챕터 6, 7은 실제로 AI를 각 영역에서 어떻게 활용할 수 있는지 예시를 보여주고 있다. 이 부분은 가볍게 훑게 되었는데, 우선 현재 활용하는 방식과 크게 다르지 않았고, 각 영역별로 나눠진 구성이다 보니 이후 해당 영역을 구성할 때 찾아서 읽어봐도 충분할 것 같다는 판단이었다. 그다음 챕터로는 보안, 신뢰성, 유지보수성에 관련된 내용이었다. 당연한 내용이기도 하지만, 하드코딩된 기밀 정보나 SQL 인젝션, XSS, 부적절한 인증 및 권한 부여 등 챙겨야 하는 부분을 AI가 챙기지 못한다면 좀 더 기민하게 확인하고 대응해야 한다고 언급한다.
이후 책의 후반부에서 ‘도구는 변해도 목표는 바뀌지 않습니다. 신뢰할 수 있고 효율적이며 혁신적인 소프트웨어를 구축하는 것입니다’라는 말이 인상적이었다. 요즘 드는 생각과 크게 다르지 않기에 그랬는데, 실제로 코딩을 떠나 AI를 통해 많은 결과물이 쉼 없이 쏟아지는 시대에 기술과 가장 멀리 있던 사람이 현재의 기술에 가장 드라마틱하게 놀라고 있는 시대라고 볼 수 있다. 예컨대 개발과 무관한 사람이 당연히 개발자보다도 더 놀랄 수밖에 없는 게, 기존엔 쉽게 접근할 수 없던 기술을 AI를 통해 허들을 넘어 본 경험을 가장 극적으로 할 수 있기 때문이라고 생각한다. 하지만 AI의 발전과 무관하게 개발 관점에서의 명확한 목표는 워딩 그대로 ‘신뢰할 수 있고 효율적이며 혁신적인 소프트웨어 구축’임은 변함없고, 그건 지금의 자연어 프롬프트로 온전히 구현하는 건 여전히 쉬운 일은 아니다. PoC 단계에서 사용하는 AI와 그 이상의 고도화된 어플리케이션 계층에서 사용하는 AI는 완전히 다른 방식의 접근이 필요하다는 것, 그리고 그 결과물이 다를 수 있다는 점을 경험해 보지 않으면 온전히 느끼기 어렵다. 실제로 PoC를 AI 기반으로 개발해 봤을 때 화면은 그럴듯하지만 코드 레벨에서의 재사용성이 떨어지고, 관심사의 분리가 제대로 되어 있지 않거나 응집도 측면이 무시된 걸 확인할 수 있기도 했다. 결국 기존에 개발한 PoC는 그 이상의 단계로 넘어가는 순간 유지보수성을 포함해 여러 가지 측면에서 아쉬운 프로덕트가 될 수 있는 한계가 현재까진 존재한다. 그런 측면을 고려하지 않고 AI 만능주의적인 관점은 조금 주의해야 하지 않을까 생각한다. AI를 떠나 인류가 진보하며 도구를 온전히 받아들이고 제대로 활용해 왔던 경우는 언제나 만능주의적 관점이 아닌 비판적 접근이 있어왔다는 사실을 다시금 떠올려볼 필요가 있다. 기술의 진보가 이처럼 빨랐던 적이 없었기 때문에 그저 기술에 취해 있지는 않은지 우리 스스로 잠시 돌아볼 필요는 있다.
마지막 챕터를 통해 AI 보조 엔지니어링의 미래에 대해 이야기하고 있다. 미래와 관련된 여러 가지 이야기가 있지만, 최근의 내 생각과 흡사한 부분은 생성형 도구의 결합 측면과 자연어 중심의, 혹은 자연어와 코드를 혼합한 하이브리드 언어에 대한 이야기였다. 실제로 전자는 여러 가지 측면에서 시도되고 있는데, 개별적인 생성형 도구가 서로 다양한 방식으로 결합되고 있다. 예컨대 Figma Make를 통해 시안을 생성하고 그걸 기반으로 코드를 생성해 주는 로우코드/노코드 플랫폼이 비개발자 사이에 사용되고 있고, 몇몇 플랫폼은 웹 배포까지 도와주기 때문에 기술적 허들을 완전히 무너뜨리고 있는 것과 흡사하다. 자연어와 코드를 혼합한 하이브리드 언어는 흥미로웠는데 책에서 접근한 방식은 다음과 같다.
// 주문에서 고객 이름 목록을 생성하되, 중복을 제거하고
// 알파벳순으로 정렬한 다음 출력합니다.
list<Customer> customers = orders -> map(order -> order.customerName)
-> unique()
-> sort()
-> print();
어떤 방향으로 나아가게 될까. 기술의 발전은 자연스레 학습에 대한 부담임을 부정할 순 없지만, 그럼에도 불구하고 이런저런 도구를 사용하고 미래를 상상해 보게 되는 건 어떤 호기심이나 흥미를 유발하기 때문에 가능한 일인 것 같다. 뭔가 자연스럽게 생기는 내적 호기심이 기술에 대한 새로운 접근과 상상을 불러일으킨다. 하이브리드 언어와 비슷한 맥락이면서 동시에 조금 다른 방향으로는 최근 논의되고 있는 SDD(Spec-Driven-Development)일 수도 있겠다. 물론 이건 자연어와 코드를 혼합한 방식은 아니지만, 자연어와 코드 사이에 AI가 명확하게 이해할 만한 명세서를 작성하고, 그 명세서를 기반으로 대화를 진행해 나가는 방식이라고 볼 수 있는데, 이 SDD 또한 어떤 방향으로 흘러갈지 궁금한 측면이 있다.
개인화된 사용자 경험에 관한 이야기도 흥미로웠다. 애초에 개인화는 이미 여러 플랫폼에서 다양한 방식으로 진행되고 있지만, 좀 더 심화적인 관점에서 사용자가 스크린 리더 기술을 사용하고 있다고 감지하고 판단할 수 있다면 접근성 측면에서 사용자에 맞춰 애플리케이션을 자동으로 전환하는, 책에서 언급하는 워딩 그대로 ‘적응적 소프트웨어’가 될 수 있겠다. 레이아웃을 재배치하고 사용자마다 다른 그리드를 맞춤형으로 볼 수 있다면 이커머스의 경험은 새로운 방향을 띄고 나아갈 수 있겠다는 생각 또한 들었다.
다시금 제목을 곱씹어 본다. 결국 ‘바이브 코딩 너머’에 존재하는 것은 화려한 기술의 향연이 아니라, 더 견고한 소프트웨어를 만들고자 하는 본질적인 관점이 아닐까 싶다. AI가 코드의 작성을 도울 수는 있어도, 그 코드가 향해야 할 방향과 품질을 결정하는 것은 여전히 개발자의 몫이다. 편리함이라는 달콤한 유혹 뒤에 숨겨진 기술 부채를 경계하고, 끊임없이 질문하며 검증하는 태도, 어쩌면 이 책이 말하는 ‘생존법’이라는 건, 도구가 바뀌어도 끝내 놓지 말아야 할 엔지니어로서의 집요함과 호기심 그 자체가 아닐까 싶다.