AI가 우리 대신 코드를 작성할 수 있게 되었다 — 그렇다면 우리에게 남은 역할은 무엇인가?
요약
AI가 코드를 작성하는 시대에 인간 개발자의 역할 변화를 다룹니다. AI는 개별 함수와 유닛 테스트를 잘 작성하지만, 비즈니스 로직의 의도와 복잡한 흐름을 이해하는 데 한계가 있음을 지적합니다.
핵심 포인트
- AI는 코드 작성 능력은 뛰어나지만 비즈니스 컨텍스트를 이해하지 못함
- 단순 코드 커버리지를 넘어 비즈니스 의도를 반영한 테스트 설계가 중요함
- 인간 개발자의 핵심 역할은 비즈니스 플로우와 요구사항의 맥락을 연결하는 것
AI가 우리 대신 코드를 작성할 수 있게 되었다 — 그렇다면 우리에게 남은 역할은 무엇인가?
매일 더 자주 들리는 문장이 있습니다: "요즘 누가 AI 도움 없이 코딩을 하나요?"
답은 — 거의 없다는 것입니다.
GitHub Copilot, Cursor, Claude, ChatGPT부터 프로젝트 전체를 스스로 작성할 수 있는 에이전트 (agent)에 이르기까지 — 우리는 서로 다른 레벨 (level)에서 AI를 사용하고 있습니다:
| Level | 특징 | 예시 |
|---|---|---|
| 🎵 Vibe Coding | 원하는 것을 입력하고 수락(accept)만 하면 됨 | "로그인 페이지 만들어줘" → Tab, Tab, Tab |
| ... |
그렇다면 질문은 이겁니다 — AI가 이 모든 것을 할 수 있다면, 인간인 우리에게 남은 것은 무엇일까요?
유닛 테스트 (Unit Test) — 가장 명확한 사례
AI가 작성한 유닛 테스트 (unit test)를 살펴보겠습니다:
// 🤖 AI-generated test
func TestCalculateDiscount(t *testing.T) {
tests := []struct {
...
겉보기에는 — 깔끔하고, 테이블 주도 (table-driven) 방식이며, Go 컨벤션 (convention)을 잘 따르고 있습니다.
하지만 물어보겠습니다 — 이 테스트가 비즈니스 (business)에 대해 무엇을 말해주고 있나요?
- "100바트 결제 시 10% 할인" — 왜 하필 100인가요? 어디서 온 규칙인가요?
- "1000바트 도달 시 20% 할인" — 만약 고객이 멤버십 회원이라 5%를 더 받는다면 어떻게 되나요?
input: 0, expected: 0— 이 테스트는 엣지 케이스 (edge case)를 커버하나요, 아니면 단순히 코드 라인만 커버하나요?
AI는 함수 (function)에 따라 정확하게 테스트를 수행합니다 — 하지만 그것은 실제 비즈니스가 무엇인지 알지 못합니다.
AI는 비즈니스 컨텍스트 (Business Context)를 모른다 — 그리고 영원히 모를 것이다
이커머스 (e-commerce) 시스템을 상상해 보세요:
고객 상품 구매 → 시스템 재고 차감 → 할인 계산 → 배송비 계산 → 영수증 발행
AI는 각 함수 (function)를 개별적으로 테스트할 수 있습니다:
- ✅
TestDeductStock— "재고 1개 차감" - ✅
TestCalculateDiscount— "10% 할인" - ✅
TestCalculateShipping— "배송비 50바트"
하지만 AI가 모르는 것:
"고객이 주문을 눌렀을 때 재고가 딱 0이 된다면 — 시스템은 고객이 결제할 수 있도록 15분 동안 재고를 예약(reserve)해야 한다. 결제하지 않으면 재고를 복구해야 하며, 상점에도 알림(notification)을 보내야 한다."
이것이 바로 비즈니스 플로우 (business flow) 입니다 — 이것은 단일 함수의 유닛 테스트 (unit test)가 아니라, 함수들을 하나로 연결하는 이야기이며, 이것이 어떻게 이루어져야 하는지를 아는 것은 오직 인간뿐입니다.
요구사항 (requirement) 전체를 컨텍스트 윈도우 (context window)에 집어넣는다 해도 — AI는 오늘은 이야기를 올바르게 연결할 수 있을지 모릅니다. 하지만 3개월 뒤에는:
- 새로운 조건: "회원 대상 5% 추가 할인"
- 엣지 케이스 (edge case): "예약 판매 상품 — 재고 차감 금지"
- 버그 리포트 (bug report): "고객이 중복 할인을 받음 — 10% + 5%"
AI는 "왜 이 코드가 작성되었는지"에 대한 컨텍스트 (context)가 없습니다 — AI는 코드만 볼 뿐, 그 의도 (intention)는 보지 못합니다2
토큰 (Token) — 보이지 않는 비용
사람들이 잘 이야기하지 않는 또 다른 문제: 토큰 비용 (Token cost)
# AI 제안 — "모든 테스트를 파라미터화된 테스트 (parameterized test)로 리팩터링 (refactor) 하세요"
# 더 나은 테스트를 얻기 위해 AI는 다음을 읽어야 합니다:
# 1. 테스트할 함수 (200 lines)
...
그리고 이것은 단지 테스트 리팩터링 (test refactor)일 뿐입니다 — 코드 리뷰 (code review), PR 설명 (PR description), 문서 생성 (document generation)은 아직 계산에 넣지도 않았습니다.
쟁점은 "비싸다"가 아니라 — "얻는 것에 비해 가치가 있는가?"입니다.
- AI가 작성한 테스트: 함수를 모두 커버 (cover)함 → ✅ 가치 있음
- AI가 작성한 테스트: 비즈니스 흐름 (business flow)을 커버하지 못함 → ❌ 가치 없음
그렇다면 인간은 무엇을 해야 하는가?
1. 비즈니스 컨텍스트 (Business Context)를 보유하는 사람
당신만이 다음을 알고 있습니다:
- "왜 이 기능이 만들어졌는가" (단순히 "어떻게 작동하는가"가 아님)
- "요구사항 (requirement)의 범위는 어디까지인가" (AI는 범위를 넘어서 작성하는 경향이 있음)
- "무엇을 변경할 수 있고, 무엇을 변경할 수 없는가"
AI = 코드 작성자, 당신 = 개발자의 모습을 한 프로덕트 오너 (Product Owner)
2. 단순히 Accept를 누르는 것이 아니라 Diff를 읽는 것
바이브 코딩 (Vibe coding)4는 즐겁습니다 — 하지만 프로젝트가 커지면:
실제 문제:
- AI가 알리지 않고 의존성 (dependency)을 추가함
- AI가 함수를 리팩터링 (refactor)하면서 중요한 비즈니스 로직 (business logic)을 삭제함
...
저의 개인적인 규칙: 모든 AI 제안 (proposal) = 한 번의 PR 리뷰 — 모든 파일을 git diff로 확인하며, 스스로에게 질문하세요. "이 코드가 여전히 비즈니스 요구사항 (business requirement)을 반영하고 있는가?"
3. 비즈니스 우선 (Business-First) 방식으로 테스트 작성하기
AI에게 "이 함수에 대한 테스트를 작성해줘"라고 묻는 대신, 다음과 같이 물어보세요:
"요구사항은 다음과 같습니다: '500바트 이상 구매 고객은 무료 배송이지만, 회원은 300바트 이상 시 무료 배송이며, 예약 판매 (pre-order) 상품은 다른 프로모션과 결합할 수 없다' — 기존 코드를 보지 않고 이 요구사항을 커버하는 테스트를 작성해줘."
이렇게 하면 AI는 함수 시그니처 (function signature)가 아니라 **비즈니스 요구사항 (business requirement)**으로부터 테스트를 작성하게 됩니다. 그러면 당신은 코드가 실제 비즈니스에 따라 올바르게 작동하는지 증명하는 테스트를 얻게 될 것입니다.
4. AI를 파일럿 (Pilot)이 아닌 네비게이터 (Navigator)로 사용하기
❌ 파일럿 모드 (Pilot Mode): AI가 운전 → 당신은 구경만 함
"user management를 위한 API 생성"
→ AI가 전부 수행 → 당신은 merge 버튼만 클릭
...
네비게이터 모드 (Navigator mode)는 토큰을 더 적게 사용하고, 오류가 적으며, 당신이 여전히 코드의 소유권을 가집니다.5
요약
| AI가 잘하는 것 | 인간이 해야 하는 것 |
|---|---|
| 보일러플레이트 (Boilerplate) 작성 | 비즈니스 컨텍스트 (Business context) 유지 |
| ... | ... |
질문은 "AI가 개발자를 대체할 것인가"가 아닙니다. 질문은 다음과 같습니다:
"AI를 사용하는 개발자가 사용하지 않는 개발자를 대체할 것이며 — 비즈니스를 이해하는 개발자가 그 둘 모두를 대체할 것이다"
각주
-
테이블 기반 테스트 (Table-driven test): Go 언어의 표준 패턴 — 테스트 케이스를 struct의 slice로 선언한 뒤
t.Run()으로 루프를 돌림 — 읽기 쉽고 테스트 케이스 추가가 용이하며, 테스트 코드를 복사-붙여넣기 할 필요가 없음 ↩ -
코드 ≠ 의도 (Code ≠ Intent): 코드는 "무엇(what)"이며 — 요구사항(requirement), 설계 문서(design doc), 커밋 메시지(commit message)는 "왜(why)"입니다 — AI는 what은 보지만 why는 보지 못합니다. 이것이 인간이 가치 있는 간극입니다 ↩
-
AI는 범위를 벗어나 작성하는 것을 좋아함: AI는 종종 edge case 처리, 유효성 검사(validation), 에러 메시지 등을 추가하여 "도움"을 주려 합니다 — 이는 diff 상으로는 좋아 보이지만, 실제로는 작업의 범위(scope)를 확장하고 있는 것입니다 — 즉, 불필요하게 버그가 발생할 수 있는 표면적(surface area)을 넓히는 것과 같습니다 ↩
-
바이브 코딩 (Vibe Coding): Andrej Karpathy가 "프롬프트 입력 → 수락(accept) → diff 확인 안 함" 식의 코딩 방식을 일컫는 용어 — 프로토타입 제작에는 즐겁고 생산적이지만, 프로덕션(production) 환경에서는 리스크가 매우 높습니다 ↩
-
네비게이터 vs 파일럿 (Navigator vs Pilot): 항공 분야에서의 비유 — 파일럿은 최종 결정권을 가지며, 네비게이터는 정보를 제공합니다 — 코드의 맥락에서: 당신은 main에 merge되는 코드에 책임을 져야 하므로 파일럿입니다 ↩
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기