AI 페어 프로그래밍 한 달, 세 가지 도구를 써봤다 (I Tried Pair Programming With Three Different AI Tools For a Month)
한 개발자가 Cursor, GitHub Copilot, Claude Code를 한 달간 실제 개발 업무에 투입해 비교했다. 코드 생성 속도가 아니라 '작업 후 손이 얼마나 더 가는가'를 기준으로 삼은 결과, 승자는 하나가 아니었다.

I Tried Pair Programming With Three Different AI Tools For a Month
AI coding tools can write a function in seconds. The harder question is whether that function...
개요 #
AI 코딩 도구는 함수 하나쯤 몇 초 만에 써낸다. 문제는 그 함수가 내 코드베이스에 들어가도 되는 물건이냐다. 기존 아키텍처를 따르는가, 엣지 케이스를 처리하는가, 테스트는 여전히 통과하는가. 그리고 세 파일 건너에서 뭔가 깨졌을 때, AI가 또 다른 패치를 찍어내는 대신 진짜 원인을 찾아줄 수 있는가.
개발자 Elsie Rainee가 이 질문에 답하려고 한 달을 썼다. Cursor, GitHub Copilot, Claude Code를 페어 프로그래밍 상대로 놓고 코드 작성, 디버깅, 리팩터링, 테스트 작성, 여러 파일에 걸친 변경까지 실무에 가까운 과제를 돌렸다.
기준은 "어느 도구가 코드를 더 많이 뽑아내는가"가 아니었다. 작업이 끝난 뒤 사람이 뒤처리할 일을 얼마나 덜 만드는가였다.
결론부터: 절대 승자는 없었다 #
세 도구 모두 실제 개발 과제에 물려본 뒤 그가 내린 답은 "하나를 고를 수 없다"였다. 각자 잘하는 구간이 달랐기 때문이다.
- Cursor — AI 중심 에디터 안에서 대화하며 코딩할 때, 그리고 여러 파일을 동시에 손볼 때 가장 강했다.
- GitHub Copilot — 자동완성, 보일러플레이트, 작은 함수 같은 일상 코딩에서 가장 편했다.
- Claude Code — 큰 코드베이스를 파악해야 하거나, 파일을 넘나드는 디버깅, 터미널에서 여러 단계를 이어가는 작업에서 제일 앞섰다.
한 달을 통틀어 가장 큰 차이는 코드를 뽑아내는 속도가 아니었다. 코드를 만들기 전에 얼마나 쓸모 있는 맥락을 확보하느냐였다.
무엇을 테스트했나 #
흔한 AI 코딩 비교는 이런 식이다.
"투두 앱 만들어줘."
이런 프롬프트로는 실무에서 쓸 만한지 알 길이 없다. 그래서 그는 기존 프로젝트 안에서 실제로 벌어지는 일과 닮은 과제를 골랐다.
과제 1 — 빠진 함수 채우기 #
기존 코드를 주고 미구현 함수를 채우게 했다.
async function getUserById(id) {
// implementation needed
}요구사항은 단순했다. 유저를 가져오고, 실패 응답을 처리하고, 반환 데이터를 검증하고, 예측 가능한 결과를 돌려줄 것. 여기서 확인하려던 건 하나다.
AI가 자기 스타일을 발명하지 않고 프로젝트의 기존 코딩 스타일을 따라가는가?
셋 다 동작하는 출발점은 만들어냈다. 차이는 그다음 정리 단계에서 나왔다.
Copilot은 첫 구현을 빠르게 찍어내는 데 강했다. Cursor는 관련 파일을 참조해 주변 코드에 맞춰 함수를 다듬기 편했다. Claude Code는 손대기 전에 "비슷한 함수가 다른 곳에서 어떻게 구현돼 있는지 먼저 보라"고 시킬 때 특히 쓸모 있었다.
기존 애플리케이션에서는 이 구분이 중요하다. 백지에서 코드를 쓰는 건 쉽다. 기존 코드베이스에 어울리는 코드를 쓰는 게 어렵다.
진짜 시험대는 디버깅이었다 #
차이가 가장 크게 벌어진 곳은 코드 생성이 아니라 디버깅이었다. 그는 해법을 지어내게 하는 대신 실제로 터진 에러를 던졌다.
TypeError: Cannot read properties of undefined
at UserList.jsx:42
여기서 "이 에러 고쳐줘"라고 묻지 않았다. 관련 컴포넌트, API 함수, 데이터 구조를 함께 주고 근본 원인을 짚어보라고 했다. 결과물의 질이 확연히 달라졌다.
GitHub Copilot #
지금 편집 중인 코드 근처에 문제가 있을 때 좋았다. null 체크가 빠졌거나 변수를 명백히 잘못 쓴 경우라면 빠르게 수정안을 내놨다. 한계는 원인이 다른 곳에 있을 때 드러났다. 파일과 맥락을 직접 더 넣어줘야 하는 상황이 종종 생겼다.
Cursor #
관련 코드가 이미 프로젝트 안에 있으면 이런 상황을 더 잘 다뤘다. 컴포넌트와 API 호출, 관련 타입을 훑어보고 데이터 모양이 어디서부터 기대와 어긋나는지 설명하라고 시킬 수 있었다. 자동완성이라기보다 옆에서 같이 봐주는 두 번째 눈에 가까운 감각이었다.
Claude Code #
디버깅이 여러 파일을 가로지를 때 특히 유용했다. 에러가 터진 줄만 보는 게 아니라 데이터 흐름 전체를 추적하게 시킬 수 있었다. 실무 버그는 애플리케이션이 죽는 자리에 있지 않은 경우가 많다. 크래시는 대개 마지막 증상일 뿐이다.
리팩터링 — 시간을 아끼기도, 만들기도 한다 #
동작은 하지만 유지보수가 힘들어진 코드를 주고 동작을 바꾸지 말고 개선하라고 했다.
function calculateTotal(items) {
let total = 0;
for (let i = 0; i < items.length; i++) {
if (items[i].active) {
total += items[i].price * items[i].quantity;
}
}
return total;
}단순한 리팩터링이야 쉽다. 그런데 실무 리팩터링에는 늘 제약이 붙는다.
- API를 바꾸지 말 것
- 기존 동작을 보존할 것
- 현재 데이터 구조를 유지할 것
- 의존성을 새로 추가하지 말 것
- 테스트 커버리지를 지킬 것
- 프로젝트의 기존 컨벤션을 따를 것
여기서부터 도구별 성향이 갈렸다. Copilot은 작은 범위의 리팩터링 제안에 뛰어났다. Cursor는 영향받는 파일을 훑어가며 넓은 범위를 손볼 때 나았다. Claude Code는 그 함수가 저장소 전반에서 어떻게 쓰이는지부터 파악해야 하는 리팩터링에서 제 몫을 했다.
핵심은 diff를 읽는 것 #
그가 이 실험에서 규칙으로 삼은 것 하나.
AI가 만든 대규모 리팩터링은 diff를 읽기 전에 절대 받아들이지 않는다.
깔끔해 보이는 구현이 곧 안전한 구현은 아니다. AI는 중복을 없애면서 동작을 슬쩍 바꿔놓기도 하고, 다른 부분과의 관계 때문에 일부러 그렇게 써둔 코드를 "개선"해버리기도 한다.
AI로 테스트 작성하기 #
테스트는 셋 다 시간을 아껴준 영역이었다. 기존 함수를 주고 정상 입력, 빈 입력, 잘못된 입력, 누락된 값, API 실패, 경계 조건까지 커버하는 단위 테스트를 요청하면 첫 결과물은 대체로 쓸 만했다.
문제도 분명했다. AI는 눈앞의 구현을 보고 테스트를 쓴다. 그러면 "애플리케이션이 무엇을 해야 하는가"를 검증하는 테스트가 아니라 "지금 코드가 무엇을 하는가"를 박제하는 테스트가 나온다. 구현에 기본값이 잘못 들어가 있으면, 생성된 테스트가 그 잘못된 동작을 정답으로 굳혀버린다.
그래서 그는 요청을 바꿨다.
"이 함수의 테스트를 써줘."
대신 이렇게 물었다.
"아래 설명한 기대 동작을 기준으로 테스트를 작성해. 엣지 케이스와 실패 시나리오를 포함하고, 현재 구현이 옳다고 가정하지 마."
이 작은 변경만으로 훨씬 쓸모 있는 테스트가 나왔다.
여러 파일 변경에서 판이 갈렸다 #
함수 하나씩 시키는 걸 그만두고 기능 단위를 통째로 던지자 세 도구의 차이가 확실해졌다.
기존 유저 목록에 페이지네이션을 추가해. 현재 API 응답 형식은 유지하고, 로딩·에러 상태를 넣고, API 요청을 수정하고, 기존 필터는 그대로 두고, 새 동작에 대한 테스트도 추가해.
이 한 문장을 처리하려면 AI가 알아야 할 게 이만큼이다.
- API 요청이 어디서 일어나는가
- 유저 목록이 어디서 렌더링되는가
- 상태를 현재 어떻게 관리하는가
- 필터가 어떻게 동작하는가
- 테스트가 어디에 있는가
- 어떤 파일을 수정해야 하는가
- 기존 API가 요청한 동작을 지원하는가
실제 소프트웨어 개발에 훨씬 가까운 상황이다.
Cursor는 에디터 안에 머무르며 변경을 대화식으로 이끌고 싶을 때 잘 작동했다. 제안된 수정을 살펴보고 진행하면서 구현을 조정할 수 있었다.
GitHub Copilot은 여전히 유용했지만, 변경 규모가 커질수록 방향을 더 많이 잡아줘야 했다. 무엇을 해야 할지 이미 아는 상태에서 구현을 거들 때 탁월했다.
Claude Code는 구현에 앞서 저장소 수준의 조사가 필요한 과제에 잘 맞았다. 첫 단계가 코드를 쓰는 게 아니라 어디를 고쳐야 하는지 알아내는 것인 큰 변경에서 값어치를 했다.
어느 도구가 손을 가장 덜 타게 했나 #
생성된 코드 줄 수보다 측정하기 까다로웠지만, 그는 더 실용적인 지표를 보기 시작했다. AI가 끝낸 뒤 내가 해야 할 일이 얼마나 남는가.
- 잘못된 가정 고치기
- 불필요한 코드 걷어내기
- API 바로잡기
- 변수명 수정
- 빠진 에러 처리 추가
- 테스트 다시 쓰기
- 회귀 버그 잡기
- 불필요한 변경 되돌리기
이 관점이 생산성에 대한 생각을 바꿨다. 1분에 200줄을 뽑는 도구가, 쓸 만한 80줄을 내놓는 도구보다 반드시 빠르지는 않다. 앞의 결과물을 고치느라 30분을 더 써야 한다면 말이다. 중요한 건 생성된 코드가 아니라 쓸모 있는 코드였다.
과제별 정리 #
| 작업 | 적합한 도구 | 이유 |
|---|---|---|
| 인라인 자동완성 | GitHub Copilot | 타이핑 중 빠른 제안 |
| 작은 함수 | GitHub Copilot | 마찰이 적고 생성이 빠름 |
| 대화식 리팩터링 | Cursor | 에디터 기반 워크플로가 강함 |
| 여러 파일 편집 | Cursor | 변경을 유도·검토하기 편함 |
| 단순 에러 디버깅 | GitHub Copilot | 맥락 기반 즉각 제안 |
| 파일 넘나드는 디버깅 | Claude Code | 저장소 수준 조사에 적합 |
| 낯선 저장소 파악 | Claude Code | 프로젝트 구조 추적에 유용 |
| 단위 테스트 작성 | 셋 다 | 사람 검토를 전제로 한 좋은 출발점 |
| 대규모 구현 과제 | Cursor / Claude Code | 다단계 작업에 적합 |
| 최종 코드 리뷰 | 사람 개발자 | AI가 최종 결정권자여선 안 됨 |
AI 페어 프로그래밍이 실제로 바꾼 것 #
가장 큰 생산성 향상은 "프로그래밍을 안 하게 됐다"가 아니었다. 다르게 프로그래밍하게 됐다.
AI를 본격적으로 쓰기 전에는 문서 검색, 문법 확인, 반복 코드 작성, 테스트 보일러플레이트, 낯선 함수 추적, 첫 버전 만들기에 시간이 많이 들어갔다. AI가 이 마찰을 상당히 줄였다.
대신 다른 종류의 일이 중요해졌다. 생성된 코드 검토, 가정 확인, 엣지 케이스 테스트, diff 읽기, 더 나은 프롬프트 쓰기, 큰 과제를 작은 요구사항으로 쪼개기. AI는 엔지니어링 작업을 없애지 않았다. 시간이 쓰이는 자리를 옮겼을 뿐이다.
한 달간 조심하게 된 것들 #
1. AI는 가정한다 #
요구사항이 명확하지 않으면 도구가 빈칸을 스스로 채운다. 프로젝트에 맞지 않는 API 패턴, 라이브러리, 명명 규칙, 아키텍처가 그렇게 들어온다.
2. 동작하는 코드가 좋은 코드는 아니다 #
컴파일되고 기본 테스트를 통과해도 불필요하게 복잡할 수 있다.
3. 테스트는 거짓 안심을 준다 #
생성된 테스트 스위트가 곧 좋은 커버리지는 아니다.
4. 큰 변경에는 중간 체크포인트가 필요하다 #
기능 전체를 프롬프트 하나로 요청하는 것보다 단계를 나눌 때 결과가 좋았다.
5. Git이 더 중요해졌다 #
AI가 변경을 더 많이 만들수록 커밋과 diff를 검토하는 일이 필수가 됐다. 무엇이 왜 바뀌었는지 정확히 알아야 했다.
가장 잘 통한 워크플로 #
의외로 단순했다.
- 기존 코드를 설명하게 한다 — 관련 파일을 주고 손대기 전에 현재 동작부터 설명하게 한다.
- 요구사항을 정의한다 — 무엇이 바뀌어야 하고 무엇이 그대로여야 하는지 정확히 말한다.
- 계획을 먼저 받는다 — 큰 과제라면 코드를 쓰기 전에 어떤 파일을 고칠지 짚게 한다.
- 작게 쪼개 구현한다 — 거대한 변경을 의심 없이 받아들이지 않는다.
- diff를 읽는다 — 의미 있는 수정은 전부 확인한다.
- 테스트를 돌린다 — 그럴듯해 보인다고 완성된 코드로 취급하지 않는다.
- AI에게 자기 답을 반박시킨다 — 다음 프롬프트가 유용했다.
"이 구현에서 엣지 케이스, 회귀, 불필요한 복잡도, 틀렸을 수 있는 가정을 검토해."
놓쳤던 문제가 여기서 자주 드러났다.
그래서 어느 도구를 고를 것인가 #
지금 새 프로젝트를 시작한다면 벤치마크 점수나 기능 목록만 보고 고르지는 않겠다는 게 그의 답이다. 기준은 자기 워크플로다.
- 일상 코딩과 자동완성 → GitHub Copilot
- 에디터 중심의 대화식 작업 → Cursor
- 저장소 수준 디버깅·조사, 터미널 기반의 큰 작업 → Claude Code
단서가 하나 붙는다. 어느 쪽에도 최종 결정권을 넘기지 않겠다는 것. AI는 구현을 제안할 수 있지만, 그 구현이 맞는지 판단하는 건 여전히 사람이다. AI를 페어 프로그래머로 쓰는 것과 코드 생성기로 쓰는 것의 차이가 여기에 있다.
마무리 #
세 도구로 한 달을 보낸 뒤 그가 얻은 결론은 자극적이진 않지만 실용적이다. AI는 프로그래밍을 사라지게 하지 않는다. 프로그래밍의 특정 부분을 극적으로 빠르게 만들 뿐이다.
Copilot은 코드를 쓰는 동안 빠른 도움이 필요할 때 탁월했고, Cursor는 대화식 편집과 여러 파일이 얽힌 작업에서 더 유용해졌다. Claude Code는 저장소를 조사하거나 문제를 추적하거나 터미널에서 큰 과제를 밀고 나갈 때 돋보였다.
진짜 생산성은 AI 생성과 평범한 엔지니어링 규율을 합칠 때 나왔다. 여전히 코드를 읽고, diff를 검토하고, 테스트를 돌리고, 실패를 디버깅하고, 아키텍처를 결정하는 건 사람의 몫이다.
가장 좋은 AI 페어 프로그래머는 코드를 가장 많이 쓰는 도구가 아니다. 엔지니어링 문제를 푸는 데 더 많은 시간을, 반복 구현과 싸우는 데 더 적은 시간을 쓰게 해주는 도구다.
이 글은 위 출처를 바탕으로 한국 독자를 위해 재작성한 기사입니다. 원문의 사실과 수치에 근거하며, 별도의 견해를 포함하지 않습니다.

Photo by