현업 개발자가 바이브 코딩을 써본 솔직한 후기

게시일: 2026년 2월 6일 · 20분 읽기

나는 지난 6개월간 거의 매일 Cursor, Claude Code, GitHub Copilot을 사용했다. 진지한 마음으로, 진정으로 내 업무에 도움이 되는지 검증하려는 목적으로. 이 글은 그 경험에 대한 정직한 기록이다.

결론부터 말하면: 도움이 된다. 하지만 마케팅이 약속하는 만큼은 아니다. 그리고 특정 상황에서는 오히려 시간을 낭비하게 된다.

첫 만남: Cursor with TypeScript

지난 가을, 회사에서 기존 React 프로젝트를 TypeScript로 마이그레이션하기로 했다. 규모는 꽤 컸다. 500개 이상의 컴포넌트. 그때 나는 생각했다. "이게 Cursor의 진짜 쓸모를 보여줄 프로젝트다."

내 프롬프트는 이랬다:

이 React 컴포넌트를 TypeScript로 변환해줘. Props의 타입을 정의하고, 컴포넌트의 상태 관리도 타입을 지정해. 기존 기능은 유지해야 해.

결과는? 생각보다 훨씬 좋았다. Cursor는 컴포넌트를 분석해서 자동으로 Props 타입을 생성했다.

// 이전 (JavaScript)
const UserCard = ({ user, onDelete, onUpdate }) => {
  return (
    <div>
      <h2>{user.name}</h2>
      <button onClick={() => onDelete(user.id)}>Delete</button>
    </div>
  );
};

// Cursor의 결과
interface User {
  id: string;
  name: string;
}

interface UserCardProps {
  user: User;
  onDelete: (id: string) => void;
  onUpdate: (user: User) => void;
}

const UserCard: React.FC<UserCardProps> = ({ user, onDelete, onUpdate }) => {
  return (
    <div>
      <h2>{user.name}</h2>
      <button onClick={() => onDelete(user.id)}>Delete</button>
    </div>
  );
};
      

이 작업은 정말 빨랐다. 손으로 했다면 1개월이 걸렸을 것이다. Cursor와 함께는 2주일이면 됐다. 그리고 결과의 질도 나쁘지 않았다.

그때 나는 생각했다. "오, 이거 진짜 좋네."

흥분이 식은 순간: Claude Code with 복잡한 로직

좋은 경험 후, 나는 자신감이 생겼다. 더 복잡한 작업에 Claude Code를 시도해봤다. 우리 팀의 데이터 처리 라이브러리를 리팩토링하는 작업이었다.

요구사항은 이랬다:

사용자 데이터의 여러 소스(API, CSV, 데이터베이스)를 통합해서 하나의 형식으로 변환하는 라이브러리. 중복 제거, 데이터 유효성 검사, 필드 매핑이 필요해. 그리고 대규모 데이터(10만 개 이상의 레코드)를 1초 안에 처리해야 해.

나는 Cursor에 요청했다. 생성된 코드는 겉으로는 좋아 보였다:

class DataIntegrator {
  async transformData(sources) {
    const unified = [];

    for (const source of sources) {
      const data = await source.fetch();
      const validated = this.validate(data);
      const mapped = this.mapFields(validated);
      unified.push(...mapped);
    }

    return this.deduplicateAndSort(unified);
  }

  deduplicateAndSort(data) {
    const unique = new Map();
    data.forEach(item => {
      unique.set(item.id, item);
    });
    return Array.from(unique.values());
  }
}
      

이 코드는 작동한다. 하지만 성능은? 최악이었다. 10만 개 레코드 처리에 5초가 걸렸다. 요구사항은 1초였다.

문제는:

내 프롬프트에 이 조건들을 명시했어야 했다. 하지만 AI는 "일반적으로 작동하는 코드"를 생성했을 뿐이다.

결국 나는 직접 다시 작성했다. 스트림 기반 처리, 배치 동시 실행, 인덱싱. 3시간이 걸렸다. 그 시간을 AI로 절약하지 못했다. 오히려 AI 코드를 분석하고 버리는 시간을 낭비했다.

그때 배운 교훈: AI는 "평범한" 코드는 완벽하지만, "최적화된" 코드는 못 만든다.

Copilot Chat: 도움이 되는 상황과 안 되는 상황

GitHub Copilot Chat은 다르다. IDE 안에서 직접 대화할 수 있어서, 더 빠르고 편하다. 나는 여러 가지를 시도했다:

잘 된 경우: 버그 디버깅

복잡한 정규식에서 원하지 않는 동작이 있었다. 나는 Copilot Chat에 물었다:

이 정규식이 특정 경우에 틀린 결과를 줘. 예를 들어서 "user@example.com"은 맞게 매칭되는데 "user+tag@example.com"은 안 돼. 왜일까?

Copilot은 즉시 답했다:

당신의 정규식 /^[a-z]+@[a-z.]+$/는 '+' 문자를 허용하지 않습니다. 이메일 주소 표준에 따르면 + 문자는 로컬 부분에서 허용됩니다.

완벽한 진단이었다. 그리고 수정한 정규식도 제안했다. 이런 경우 Copilot은 정말 훌륭하다. 왜냐하면 버그의 원인을 설명하는 것은 AI가 잘하기 때문이다.

덜 된 경우: 새로운 기능 설계

나는 "새로운 캐싱 레이어를 설계해줄래?"라고 물었다. 요구사항은:

생성된 코드는 작동했지만, 설계 관점에서는 미흡했다:

// 문제: 동시성 처리가 없음
// 다중 요청이 동시에 같은 캐시 키를 접근할 때 race condition 발생 가능
class Cache {
  constructor(maxSize, ttl) {
    this.data = new Map();
    this.timestamps = new Map();
    this.accessTimes = new Map();
    this.maxSize = maxSize;
    this.ttl = ttl;
  }

  get(key) {
    if (!this.data.has(key)) return null;
    if (Date.now() - this.timestamps.get(key) > this.ttl) {
      this.delete(key);
      return null;
    }
    this.accessTimes.set(key, Date.now());
    return this.data.get(key);
  }
}
      

이 코드는 단일 스레드에서는 문제없다. 하지만 Node.js의 비동기 특성상, 동시 요청에서는 문제가 생길 수 있다. AI는 이런 미묘한 점을 놓쳤다.

새로운 설계나 아키텍처가 필요한 경우, Copilot은 "평범한" 솔루션을 제시한다. 혁신적이거나 최적화된 솔루션은 아니다.

실제 프로젝트에서의 활용: 3가지 사례

사례 1: REST API 마이그레이션 (성공)

우리는 Express.js에서 Fastify로 마이그레이션했다. 50개의 엔드포인트가 있었다.

프롬프트: "Express 라우터를 Fastify로 변환해줄래?"

Cursor가 생성한 코드:

// Express
app.get('/users/:id', async (req, res) => {
  const user = await db.findUser(req.params.id);
  res.json(user);
});

// Fastify로 변환 (Cursor)
fastify.get('/users/:id', async (request, reply) => {
  const user = await db.findUser(request.params.id);
  reply.send(user);
});
      

완벽했다. 모든 50개 엔드포인트가 자동으로 변환되고, 테스트도 통과했다. 예상 시간 1주일 → 실제 시간 2일. 이건 큰 성공이었다.

왜 성공했을까? 패턴이 정해져 있었기 때문이다. Express와 Fastify의 API 차이는 단순하고 명확하다.

사례 2: 복잡한 상태 관리 로직 (부분 성공)

Redux 스토어의 복잡한 리듀서를 Zustand로 변환했다.

처음 60%는 AI가 잘 변환했다. 하지만 나머지 40%는 문제가 있었다:

결국 손수정한 부분이 40%. AI를 믹서기로, 손으로 조정하는 방식으로 진행했다. 예상 시간 3일 → 실제 시간 2.5일. 조금 도움이 됐지만, 완전 자동화는 아니었다.

사례 3: 성능 최적화 (실패)

우리 대시보드의 메인 페이지가 느렸다. 로딩에 3초가 걸렸다.

나는 Copilot에 물었다: "이 페이지를 최적화해줄래? 가능하면 1초 이내로."

Copilot의 제안:

AI는 일반적인 최적화 기법만 제시했다. 우리의 실제 병목은:

이런 구체적인 문제는 AI가 찾아내지 못했다. 결국 나는 프로파일러를 직접 들고 분석했다. 이 경우 AI는 전혀 도움이 안 됐다.

패턴 찾기: 언제 AI가 도움이 될까?

여러 프로젝트를 진행하면서 패턴이 보였다:

상황 AI 효율 이유
보일러플레이트 변환 90% 패턴이 정해져 있음
표준 기능 구현 75% 많은 예제 데이터가 있음
버그 분석 80% 설명하는 것을 잘함
코드 리뷰 70% 관례를 알고 있음
성능 최적화 30% 컨텍스트가 필요
새로운 설계 40% 창의성이 필요
보안 강화 50% 엣지 케이스가 많음
복잡한 알고리즘 35% 깊이 있는 이해가 필요

비용 분석

실제로 시간을 얼마나 절약했을까?

Cursor (월 $20): 월 평균 30시간 절약. 비용 효율이 좋다. 주로 보일러플레이트와 리팩토링에서 시간을 절약했다.

GitHub Copilot Chat (월 $10): 월 평균 10시간 절약. 사실 더 많이 썼지만, 실제로 생산성을 높인 경우는 적었다.

Claude Pro (월 $20): 월 평균 15시간 절약. Cursor보다는 덜하지만 특정 분야에서 좋다. 특히 설명과 분석에서 우수하다.

합계: 월 55시간 절약. 내 월 업무 시간 160시간의 34%다.

하지만 더 중요한 것은, "절약한 시간이 정말 생산성 향상으로 이어졌는가?"라는 질문이다. 답은 "부분적"이다. 일부는 다른 작업에 충당했지만, 일부는 그냥 쉬었다. 또는 AI 코드를 검증하는 데 시간을 썼다.

신입과 베테랑의 차이

흥미롭게도, AI 도구의 효율은 경력에 따라 다르다.

우리 팀의 신입(2년차)은 AI를 사용한 후 생산성이 2배 올랐다. 왜일까? 신입에게는 AI가 "선생님" 역할을 했기 때문이다. "이렇게 하면 되나요?"라는 질문에 AI가 빠르게 답했다.

하지만 나는? 생산성이 1.3배 올랐다. 왜냐하면 나는 대개 이미 방법을 알고 있었기 때문이다. AI는 내가 "알고 있는 것"을 빠르게 구현해주는 도구일 뿐이었다.

흥미로운 점은, 복잡한 문제에서는 역으로 신입이 AI에 속는 경우가 있다는 것이다. "AI가 이렇게 했으니까 맞겠지"라고 생각하고, 실제로 검증하지 않는다. 나는 항상 의심한다.

6개월 사용 후 최종 평가

마이너스:

플러스:

결론: 좋은 도구다. 하지만 "개발자를 대체하는" 정도는 아니다. 오히려 "좋은 개발자를 더 좋게 만드는" 도구다. 그런데 나쁜 개발자는... 더 나쁘게 만들 수도 있다.

앞으로의 계획

나는 계속 이 도구들을 쓸 것이다. 하지만 더 선택적으로 쓸 것이다.

그리고 팀 전체에 하는 권고사항도 생겼다: "AI가 생성한 코드는 2배로 엄격하게 리뷰하세요. 특히 성능과 보안 부분을."

개발하면서 배운 것 중 하나는, 새로운 도구가 나올 때마다 그것을 수용하되 의심해야 한다는 것이다. 그것이 정말 도움이 되는지 검증하고, 어디서 한계가 있는지 알아야 한다.

바이브 코딩도 그렇다. 좋은 도구지만, 만능은 아니다. 그리고 잘 써야 한다.

iL
ian.lab

실무 개발자입니다. 현장에서 겪은 문제와 해결 과정을 기록합니다. 오류 제보는 연락처로 보내주세요.