바이브 코딩(Vibe Coding)은 만들고 싶은 기능을 AI에게 말로 전달하고, 생성된 코드를 세세하게 읽기보다는 실행 결과를 보면서 수정하도록 맡기는 개발 스타일이다. Andrej Karpathy가 2025년에 소개한 용어로, OpenSSF의 용어집에서는 사람이 생성한 코드를 검토하는 개발과는 구분하고 있다.
예를 들어 '로그인 화면을 만들어줘'라고 요청하여 표시된 화면을 보고, 신경 쓰이는 부분이나 오류를 수정하도록 하는 것이다. 아이디어를 빠르게 형태화하기에는 편리하지만, 눈앞에서 잘 작동한다고 해서 표면적으로 드러나지 않은 조건까지 충족하는지는 알 수 없다.
만들어진 코드를 실제 기능에 사용하려면 좀 더 깊이 파고들어 확인하고 싶다. 예상되는 입력에 대해 요구사항대로 결과가 나오는지 확인하는 것이다. 작은 할인 계산 함수를 예로 들어, AI가 작성한 코드에 이 검증 과정을 추가해 보자.
쇼핑몰 사이트에서 회원 등급에 따라 가격을 할인하는 기능을 AI에게 맡겼다고 가정하자. 계산 자체는 단순하지만, 할인율 외에도 지켜야 할 조건이 있다.
- 일반 회원은 10% 할인한다.
- VIP 회원은 20% 할인한다.
- 할인 후 가격은 0원 미만이 되지 않아야 한다.
이 요청에 대해 돌아올 법한 코드를 예시로 준비했다.
type MemberType = "normal" | "vip";
function calculatePrice(price: number, memberType: MemberType): number {
const discountRate = memberType === "vip" ? 0.2 : 0.1;
...
10,000원을 넣으면 일반 회원은 9,000원, VIP 회원은 8,000원이 된다. 이 두 가지만 보면 요청한 기능이 된 것처럼 보인다.
console.log(calculatePrice(10_000, "normal")); // 9000
console.log(calculatePrice(10_000, "vip")); // 8000
하지만 세 번째 조건은 아직 확인하지 않았다. 음의 가격을 넣어도 결과가 0원을 밑돌지 않는지 시험해 본다.
console.log(calculatePrice(-10_000, "vip")); // -8000
결과는 -8,000원이다. 할인율은 맞지만, 가격의 하한을 처리하는 로직이 빠져 있었다. TypeScript에서는 음수도 number 타입이기 때문에, 타입 체크만으로는 이 요구사항 위반을 발견할 수 없다.
빠진 조건이 파악되었으니, 수정 후에도 같은 문제가 발생하지 않도록 확인할 수 있게 해두자. 앞서의 요구사항을 '입력과 기대하는 결과'의 쌍으로 만들면 간단한 테스트가 된다. 이 정도 함수의 경우라면 외부 라이브러리나 테스트 프레임워크를 추가할 필요는 없다.
다음 코드를 앞서의 함수와 같은 파일에 이어서 작성한다. 계산 결과가 기대값과 다르면 에러를 발생시키고, 일치하면 PASS를 표시한다.
function check(name: string, actual: number, expected: number): void {
if (!Object.is(actual, expected)) {
throw new Error(
...
첫 번째 구현에서는 마지막 '음수 입력'에서 실패한다. 이 예시에서는 음의 결과를 0원으로 보정하는 것으로 하고, 앞서의 calculatePrice 함수를 다음 코드로 대체한다.
function calculatePrice(price: number, memberType: MemberType): number {
const discountRate = memberType === "vip" ? 0.2 : 0.1;
const discountedPrice = price * (1 - discountRate);
...
같은 테스트를 다시 실행하면 네 가지 입력에 대해 기대했던 결과가 나온다. 확인하고 싶은 조건을 코드로 만들어 두면, 나중에 함수를 변경했을 때도 같은 기준으로 비교할 수 있다.
하지만 이 네 건만으로 모든 상황을 확인할 수 있었던 것은 아니다. 일반 가격을 사용한 두 건만으로는 처음의 잘못된 코드도 통과했기 때문이다. 테스트를 만들기 전에 요구사항을 재검토하고 싶은 것이 바로 이 이유다.
이 예시에서는 유한한 숫자가 입력된다고 가정하고, 음의 결과는 0원으로 보정했다. 실제 결제 기능이라면, 음의 입력을 에러로 거부할지, 소수점 이하 금액을 어떻게 처리할지도 결정해야 할 필요가 있다.
무엇을 테스트해야 할지 막막할 때는 AI에게 리뷰를 요청하는 것도 가능하다. 앞선 예시라면 '음수나 0원 등, 놓치고 있는 입력 조건이 없는지 봐'와 같이 질문하는 형태다. 다만, AI의 지적에도 확인은 필요하다. LLM을 사용한 코드 리뷰 실증 연구에서는 리뷰 지원의 가능성과 함께, 오탐(false positive)이나 결과에 대한 신뢰성에 관한 과제도 보고되고 있다.
확인해야 할 범위 역시 계산 결과만으로는 충분하지 않다. Fu 등의 연구는 공개 GitHub 프로젝트에서 AI 도구가 생성했다고 식별된 코드 조각을 분석하여 보안상의 취약점을 보고했다. 특정 데이터와 분석 방법으로 얻은 결과를 모든 AI 생성 코드의 결함률로 간주할 수는 없다. 이러한 문제점도 있기 때문에, 동작 테스트에 더해 보안 확인도 진행하고 싶다.
그래서 실제 프로젝트에서는 여러 검사를 조합한다. 컴파일러를 이용해 타입을 확인하고, 린터(linter)나 정적 분석으로 감지할 수 있는 문제를 찾는다. 동작은 테스트로 확인하고, 변경이 기존 기능에 영향을 미치는지 여부는 회귀 테스트(regression test)로 조사한다. AI 리뷰에서 나온 의견도 이러한 검사 결과나 요구사항과 대조하여 판단하고 싶다.
이러한 확인 과정들을 매번 모두 사람이 수작업으로 수행할 필요는 없다. AI 코딩 에이전트(agent)는 제품이나 설정에 따라 파일 읽기/편집이나 명령어 실행도 할 수 있다. Codex의 공식 가이드와 개발 환경 관련 자료에서도 코드 수정이나 테스트/린터/타입 체크 실행 방법이 설명되어 있다.
앞서 언급한 할인 기능을 다시 요청한다면, 구현뿐만 아니라 확인할 입력값이나 수정 후 재검증까지 요청에 포함할 수 있다.
EC 사이트의 할인 가격을 계산하는 기능을 만들어줘.
요구사항:
- 일반 회원은 10% 할인
...
이처럼 요청하면, 코드를 실행하고 실패한 조건을 고치고 재확인하는 단계까지 맡길 수 있다. Anthropic의 에이전트 개발 가이드에서도 테스트와 같은 검증 가능한 기준을 제공하고 결과를 보면서 반복하는 방법을 권장한다. 보고를 받으면, 무엇을 실행했는지, 실행하지 못한 검사는 없는지 확인해 보는 것이 좋다.
첫 번째 할인 코드는 일반 가격 두 개를 전달했을 때 올바르게 작동했다. 음수 입력을 시도해보고서야 빠져있던 요구사항을 발견했다. Vibe coding으로 만든 기능을 실제로 사용할 때도, 이런 식으로 확인할 조건을 하나하나 구체화할 수 있다. AI에게 코드를 작성하게 한 후에도, 어떤 조건을 확인했는지까지 보고서 받아 사용 여부를 결정하고 싶다.
- OpenSSF Glossary — Vibe coding — 바이브 코딩의 의미와 사람에 의한 코드 리뷰와의 구분
- OpenAI Help Center — OpenAI Codex CLI: Getting Started — 에이전트에 의한 코드 읽기/편집/명령어 실행
- OpenAI — Addendum to o3 and o4-mini System Card: Codex — 테스트/린터/타입 체크를 실행할 수 있는 환경
- Fu et al. — Security Weaknesses of Copilot-Generated Code in GitHub Projects — 실제 프로젝트에서 식별된 AI 생성 코드의 보안 분석
- Rethinking Code Review Workflows with LLM Assistance: An Empirical Study — LLM을 통한 코드 리뷰 워크플로우 재고: 실증 연구
- Anthropic — Claude Code: Best practices for agentic coding — 테스트를 사용한 검증과 반복
※ 본문 중 5점의 이미지는 생성형 AI로 작성됨.