뒤로가기
AI 코딩 도구, 실무에서 진짜 쓸만한가

March 13, 2020

aiproductivityfrontend

작년 9월, 팀에 GitHub Copilot Business 라이선스가 들어왔다.

팀 리드가 슬랙에 "다들 써보고 2주 뒤에 후기 공유합시다"라고 올렸다. 첫 주에 팀원 6명 전원이 반응이 비슷했다. "와 이건 진짜 사기다." 자동완성이 내가 쓰려는 코드를 척척 맞추고, 함수 시그니처만 적으면 구현이 쭉 나오고, 주석 한 줄에 유틸 함수가 완성됐다. 우리는 이게 미래라고 생각했다. 그 흥분이 약 3주 정도 갔다.

현실은 데모 영상이 아니다#

Twitter(X)에 올라오는 AI 코딩 데모는 항상 깔끔하다. 빈 파일에서 시작해서 Todo 앱을 만들거나, 간단한 CRUD API를 뚝딱 찍어내거나, 알고리즘 문제를 풀어내는 영상들. 저런 걸 보면 "개발자 필요 없겠는데?"라는 생각이 드는 게 당연하다.

근데 실무는 빈 파일에서 시작하지 않는다. 이미 200개 넘는 컴포넌트가 있는 프로젝트에서 기존 디자인 시스템을 따르고, API 응답 구조에 맞추고, 에러 핸들링 컨벤션을 지키고, 비즈니스 로직의 히스토리를 이해해야 하는 게 실무다. AI한테 "결제 페이지에서 쿠폰 적용 시 배송비 할인과 상품 할인이 동시에 들어올 때의 우선순위 로직 짜줘"라고 하면 그럴듯한 코드가 나오긴 한다. 근데 그게 우리 서비스의 규칙과 맞는지는 전혀 다른 문제다.

AI가 진짜 잘하는 것들#

이건 인정해야 한다. 특정 영역에서 AI 코딩 도구는 시간을 확실히 줄여준다.

보일러플레이트 코드. React 컴포넌트 기본 구조, API 호출 함수, TypeScript 인터페이스 정의 같은 반복적인 코드. 2025년 11월에 어드민 대시보드의 테이블 컴포넌트를 8개 만들어야 하는 작업이 있었다. 각 테이블이 컬럼 정의, 정렬, 페이지네이션, 필터링을 포함해야 했는데, 첫 번째 테이블을 직접 짜고 나서 나머지 7개는 Copilot이 컨텍스트를 잡고 거의 다 완성해줬다. 원래 이틀은 걸렸을 작업을 반나절 만에 끝냈다.

정규표현식. 이건 누가 뭐래도 AI가 사람보다 낫다. 전화번호 포맷 검증, 이메일 유효성 체크, 특정 패턴의 문자열 파싱. 예전에는 regex101.com에서 30분씩 시행착오를 거쳤다면, 지금은 ChatGPT한테 "한국 휴대폰 번호 010-XXXX-XXXX 또는 01X-XXX-XXXX 형식, 하이픈 선택적"이라고 말하면 10초 만에 나온다.

typescript
// ChatGPT가 짜준 정규표현식 — 바로 적용 가능했던 경우
const phoneRegex = /^01[016789]-?\d{3,4}-?\d{4}$/;

테스트 코드 생성. 유틸 함수의 단위 테스트를 짤 때 특히 유용하다. 함수를 붙여넣고 "edge case 포함해서 테스트 짜줘"라고 하면 내가 생각 못 한 케이스까지 잡아준다. 0, undefined, 빈 배열, 음수 같은 경계값들. 올해 1월에 가격 계산 유틸 함수의 테스트를 Claude에게 시켰는데, 부동소수점 오차 케이스를 포함시킨 걸 보고 감탄했다. 그건 내가 놓쳤을 케이스였다.

익숙하지 않은 언어나 도구. 이게 개인적으로 가장 큰 이점이었다. 프론트엔드 개발자인 나한테 Dockerfile 작성, GitHub Actions 워크플로우 설정, 간단한 Python 스크립트 같은 건 매번 구글링의 연속이었다. 지금은 Cursor에서 컨텍스트를 주고 물어보면 프로젝트에 맞는 설정을 뱉어준다. 작년 12월에 CI 파이프라인에 Lighthouse 성능 체크를 추가하는 작업을 맡았는데, GitHub Actions yaml 파일을 처음부터 직접 짰으면 반나절은 걸렸을 거다. Claude Code한테 기존 워크플로우 파일을 보여주고 요구사항을 설명했더니 15분 만에 동작하는 워크플로우가 나왔다.

프로덕션에서 터진 AI 코드#

10월 말, 상품 목록 페이지의 무한 스크롤을 Copilot 자동완성에 많이 의존해서 짰다. IntersectionObserver 설정, 다음 페이지 fetch, 로딩 상태 관리까지 꽤 그럴듯하게 완성됐다. 코드 리뷰도 통과했다. 스테이징에서도 잘 돌았다.

프로덕션 배포 후 이틀 뒤에 슬랙 알림이 왔다. 특정 유저들에게서 페이지가 먹통이 된다는 CS.

원인을 추적해보니 이랬다. Copilot이 짜준 코드에서 cleanup 함수가 observer를 제대로 해제하지 않고 있었다. 컴포넌트가 언마운트되고 다시 마운트될 때 observer가 중복 등록됐다. 대부분의 유저는 페이지를 한 번 보고 나가니까 문제가 없었는데, 상품 상세 페이지를 갔다가 뒤로가기로 돌아오는 패턴을 반복하는 유저에게서 observer가 쌓이면서 API 호출이 폭발한 거다.

typescript
// Copilot이 짜준 코드 (문제 있는 버전)
useEffect(() => {
  const observer = new IntersectionObserver((entries) => {
    if (entries[0].isIntersecting && hasNextPage) {
      fetchNextPage();
    }
  });

  if (targetRef.current) {
    observer.observe(targetRef.current);
  }

  // cleanup이 빠져있었다
}, [hasNextPage, fetchNextPage]);
typescript
// 수정 후
useEffect(() => {
  const currentTarget = targetRef.current;
  const observer = new IntersectionObserver((entries) => {
    if (entries[0].isIntersecting && hasNextPage) {
      fetchNextPage();
    }
  });

  if (currentTarget) {
    observer.observe(currentTarget);
  }

  return () => {
    if (currentTarget) {
      observer.unobserve(currentTarget);
    }
    observer.disconnect();
  };
}, [hasNextPage, fetchNextPage]);

cleanup 함수 하나 빠진 거다. 근데 이게 AI 코드의 전형적인 문제점이다. 겉보기엔 완벽하고, 대부분의 케이스에서 동작하고, 코드 리뷰에서도 눈에 잘 안 띈다. 하지만 엣지 케이스에서 조용히 터진다. AI는 "보통은 이렇게 짜더라"는 패턴을 학습한 거지, "이 코드가 언마운트 후 다시 마운트될 때 어떤 상태가 되는지"를 추론한 게 아니다.

AI가 못하는 것들#

여러 파일에 걸친 맥락 이해. 우리 프로젝트에서 결제 플로우는 8개 파일에 걸쳐 있다. 장바구니 → 주소 입력 → 결제 수단 → 쿠폰 → 최종 확인 → PG 연동 → 결과 처리 → 주문 완료. 이 흐름 안에서 상태가 어떻게 전달되고 변환되는지를 AI는 이해하지 못한다. Cursor의 codebase 인덱싱 기능이 이 문제를 좀 줄여주긴 하지만, "쿠폰 적용 후 PG 연동 단계에서 금액이 원래로 돌아가는 버그"를 AI한테 디버깅 시키는 건 아직 불가능에 가깝다.

Race condition 디버깅. 올 1월에 실시간 재고 표시 기능에서 발생한 버그가 있었다. WebSocket으로 받은 재고 업데이트와 사용자의 장바구니 수량 변경이 동시에 일어날 때 UI가 깜빡이면서 잘못된 값을 보여주는 문제. 이걸 Claude한테 설명하면 "debounce를 써라" "optimistic update를 써라" 같은 일반적인 조언이 나온다. 근데 실제 문제는 WebSocket 메시지의 도착 순서가 보장되지 않는 환경에서 React 상태 업데이트의 batching 타이밍과 맞물려 발생하는 거였다. 이건 코드를 읽는 게 아니라 실행 흐름을 머릿속에서 시뮬레이션해야 찾을 수 있다.

비즈니스 로직의 "왜". 코드에 주석으로 // 2025년 3분기 프로모션 정책 변경으로 인한 예외 처리 라고 적혀 있어도, AI는 그 정책이 왜 바뀌었고 어떤 맥락에서 이 예외가 필요한지 알 수 없다. 우리 서비스에는 "이 조건에서는 배송비를 0원으로 해야 한다"는 규칙이 14개 있다. 기획 문서, PM과의 대화 히스토리, 과거 장애 보고서 안에 흩어져 있는 맥락이다. AI는 코드 패턴은 볼 수 있지만 조직의 기억은 볼 수 없다.

도구별 체감 비교#

6개월간 네 가지 도구를 돌아가면서 쓴 체감 정리다.

GitHub Copilot. 에디터 안에서의 자동완성이 핵심. 새 코드를 처음부터 짤 때보다 기존 패턴을 반복하는 작업에서 빛난다. 한 파일 안에서의 컨텍스트는 잘 잡는데, 프로젝트 전체를 보는 건 아니라서 가끔 엉뚱한 import를 추천한다. 체감 생산성 향상은 하루에 30분~1시간 정도. 무시할 수 없는 수준이다.

Cursor. 코드베이스 인덱싱이 Copilot과의 가장 큰 차이점. @codebase로 프로젝트 전체를 참조할 수 있어서 "이 프로젝트에서 에러 핸들링은 어떤 패턴으로 하고 있어?"라고 물으면 실제 코드를 기반으로 답해준다. Composer 기능으로 여러 파일을 동시에 수정하는 것도 가능한데, 큰 작업에서는 아직 믿고 쓰기엔 부족하다. 작은 수정 단위로 쪼개서 써야 안전하다.

Claude Code. CLI 기반이라 처음에는 낯설었는데, 익숙해지니까 가장 자주 쓰게 됐다. 긴 맥락을 유지하면서 대화하는 게 가능해서, 복잡한 리팩토링 계획을 세울 때 특히 좋았다. "이 컴포넌트를 이런 방향으로 바꾸려는데 영향 범위가 어디까지일까?" 같은 질문에 프로젝트 파일들을 직접 읽고 답해주는 게 유용했다. 다만 실행 결과를 실시간으로 확인하면서 반복하는 흐름이라 시간이 걸릴 때도 있다.

ChatGPT. 코드 에디터와 연결 없이 독립적으로 쓴다. 개념 설명, 설계 상담, 코드 리뷰 관점에서의 피드백 요청에 주로 쓴다. "이 아키텍처의 단점이 뭘까?" 같은 열린 질문에 강하다. 코드를 직접 적용하기보다는 방향을 잡을 때 대화 상대로 쓰는 느낌이다.

팀의 AI 사용 가이드라인#

올 2월에 팀에서 AI 도구 사용 원칙을 정했다. 형식적인 규칙이 아니라, 몇 달간 쓰면서 자연스럽게 합의된 것들이다.

  1. AI가 생성한 코드는 반드시 한 줄씩 이해하고 커밋한다. "Copilot이 짠 건데 잘 모르겠어요"는 코드 리뷰에서 받아들여지지 않는다.
  2. 비즈니스 로직에는 AI를 보조로만 쓴다. 금액 계산, 권한 처리, 개인정보 관련 코드는 AI 출력물을 초안으로 쓸 수는 있지만, 로직의 정확성은 기획 문서와 대조해서 사람이 검증한다.
  3. 테스트 코드 생성은 적극 권장한다. 테스트 커버리지를 올리는 데 AI가 효과적이니까, 단위 테스트 작성에 AI를 쓰는 건 장려한다. 다만 생성된 테스트가 실제로 의미 있는 케이스를 검증하는지는 확인해야 한다.
  4. PR 리뷰에서 AI 사용 여부를 밝힌다. 강제는 아니고 권장이다. "이 부분은 Cursor Composer로 생성 후 수정했습니다" 같은 코멘트를 달면 리뷰어가 어디를 더 꼼꼼히 봐야 하는지 판단할 수 있다.

이게 거창한 정책이 아니라 그냥 "AI 코드 때문에 장애 났던 경험"에서 나온 실용적인 합의다.

"AI가 내 직업을 대체하나?"#

이 질문을 안 해본 개발자가 있을까. 나도 Copilot을 처음 쓴 날 밤에 이 생각을 했다. 내가 3년간 쌓은 게 Tab 키 한 번으로 대체되는 건가.

6개월 뒤의 답은 이렇다. AI는 타이핑을 대체하지, 판단을 대체하지 않는다.

내가 하루에 하는 일을 나눠보면 코드를 치는 시간은 전체의 30%도 안 된다. 나머지는 기획 문서 읽기, PM이랑 엣지 케이스 논의하기, 코드 리뷰하기, 장애 대응하기, 아키텍처 결정하기, 동료한테 맥락 설명하기. AI가 빠르게 해주는 건 그 30% 중에서도 일부분이다.

불안은 이해한다. 나도 여전히 가끔 느낀다. 근데 그 불안의 방향이 좀 바뀌었다. "AI 때문에 직업을 잃을까?"에서 "AI를 잘 못 쓰면 뒤처질까?"로. 솔직하게, 같은 작업을 AI 도움 없이 두 배 시간 들여서 하는 개발자와 AI를 적절히 활용해서 절반 시간에 끝내는 개발자가 있다면, 시간이 지나면서 차이가 벌어질 거다.

그래서 요즘 생각은 이런 쪽에 가깝다. AI 도구를 쓰는 능력 자체가 하나의 스킬이 되고 있다. 좋은 프롬프트를 쓰는 것, AI 출력물에서 문제를 빠르게 발견하는 것, AI에게 맡길 일과 직접 할 일을 나누는 판단. 이런 게 1~2년 안에 개발자 채용 기준에 들어갈 수도 있다고 생각한다.

결국 도구는 도구다#

몇 달 전에 읽은 트윗이 있다. 누군가가 "AI is like an intern with infinite stamina and no judgment"이라고 적었다. 끝없이 일하는 인턴인데 판단력이 없다. 꽤 정확한 비유라고 느꼈다.

인턴한테 일을 잘 시키려면 명확한 지시, 작은 단위의 태스크, 그리고 결과물 검토가 필요하다. AI도 똑같다. "이거 만들어줘"라고 던지면 결과물의 질이 들쭉날쭉하다. "이 함수의 input은 이거고, output은 이거고, 이런 엣지 케이스가 있고, 우리 프로젝트에서는 에러를 이렇게 처리해"라고 주면 쓸만한 코드가 나온다.

나는 AI 코딩 도구를 매일 쓴다. 안 쓰던 때로 돌아가고 싶지 않다. 그런데 AI가 짠 코드를 내가 이해할 수 없으면 그건 내 코드가 아니다. 이 한 줄이 6개월간 AI 도구를 쓰면서 내가 내린 결론 같은 건데, 사실 결론이라기보다는 매일 반복되는 판단에 가깝다. 오늘도 Copilot이 제안한 코드에서 Tab을 누를지 Esc를 누를지 0.5초간 생각한다. 그 0.5초가 아마 당분간은 사람의 몫으로 남아 있을 거다.