AI 코딩 도구의 폭발적인 발전으로 코드 자체를 작성하는 속도는 비교할 수 없을 만큼 빨라졌습니다.
이제 단순히 동작하는 코드를 만들어내는 것 자체의 희소 가치는 계속해서 떨어지고 있습니다.

그렇다면 AI 시대에 개발자의 진짜 경쟁력은 어디서 나올까요?

정답은 기술적 판단력과 TDD(테스트 주도 개발)에 있습니다.
AI가 만든 코드를 검증하고, 제어하며, 시스템의 품질을 유지하는 구체적인 실전 전략을 정리해 드립니다.

1. AI 코딩 시대, 개발자에게 필요한 ‘Taste(기술적 안목)’

소프트웨어 개발에서 “Taste(안목)”란 단지 문법 오류가 없는 코드가 아니라, 현재 비즈니스 맥락에 가장 적합한 “좋은 코드”를 선별해내는 능력입니다.

  • AI가 잘하는 것: 문법 오차 없는 코드 생성, 뻔한 패턴 반복, 단기적인 테스트 통과
  • AI가 못하는 것: 성능, 비용, 보안, 확장성 사이의 트레이드오프(Trade-off) 결정

성능을 높이면 코드가 복잡해지고, 유연성을 높이면 단순함이 줄어들며, 보안을 강화하면 UX가 불편해집니다.
비즈니스 목표와 사용자 요구사항을 종합적으로 고려해 최종 결정을 내리고 책임을 지는 것은 오직 맥락을 이해하는 개발자만의 영역입니다.

2. 켄트 백의 3단계 원칙과 ‘Small Steps’

소프트웨어 거장 켄트 백(Kent Beck)의 유명한 3단계 원칙은 AI 시대에 훨씬 더 중요해졌습니다.

  1. Make it work: 작고 안전한 범위에서 일단 동작하게 만든다.
  2. Make it right: 구조를 정돈하고 리팩터링한다.
  3. Make it fast: 확실한 병목이 확인되었을 때 최적화한다.

AI에게 한 번에 복잡한 대형 기능을 요청하면 코드 복잡성이 폭발하여 디버깅이 불가능해집니다.
작고 안전한 단계(Small, Safe Steps)로 나누어 지시해야 합니다.

  • ❌ 잘못된 프롬프트: “입력값 검증, DB 저장, 이메일 발송, 실패 시 로그 생성을 한 번에 만들어줘.”
  • ⭕ 올바른 프롬프트:
    • 1단계: “사용자 입력을 받는 함수 작성 (테스트 코드 포함)”
    • 2단계: “입력값을 검증하는 가드 로직 추가”
    • 3단계: “유효하지 않은 입력 발생 시 예외 처리 추가”

3. AI가 궤도를 이탈하는 3가지 경고 신호

AI에게 구현을 맡겼을 때 다음 3가지 현상이 발생하면 즉시 개발자가 개입해야 합니다.

  1. 무한 루프(Loops): 동일한 오류를 다른 방식으로 계속 시도하며 복잡한 로직의 늪에 빠질 때
  2. 과도한 기능 추가: 지시하지 않은 파일이나 비즈니스 영역까지 넘겨짚어 수정할 때
  3. 치팅 징후(Cheating): 테스트를 통과시키기 위해 테스트 코드를 삭제, skip, 혹은 조건을 완화할 때 (가장 위험!)

4. AI의 ‘비결정성’을 제어하는 TDD 스펙

전통적인 프로그래밍은 결정적(Deterministic)이어서 동일한 입력에 항상 동일한 결과가 나옵니다.
하지만 AI는 비결정적(Non-deterministic)이므로 같은 질문을 해도 매번 다른 코드를 생성합니다.

따라서 자연어 프롬프트보다 Input과 Output이 명확히 정의된 테스트 코드가 AI에게 가장 정확한 요구사항 명세서(Specification) 역할을 합니다.

[개발자의 테스트 작성] ➔ [AI의 코드 생성] ➔ [테스트 자동 실행] ➔ [검증 완료]

5. Claude Code 환경에서 TDD 사이클 강제하기 (실전 설정)

AI 코딩 도구가 테스트 없이 구현 코드부터 한 번에 생성하지 못하도록 개발 환경을 구축할 수 있습니다.

① 파일 수정 시 자동 테스트 실행 Hook (.claude/settings.json)

JSON

{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit:*.ts|Edit:*.tsx|Write:*.ts|Write:*.tsx",
"hooks": [
{
"type": "command",
"command": "npm test -- --findRelatedTests $CLAUDE_FILE_PATH --passWithNoTests",
"timeout": 60
}
]
}
]
}
}

② 프로젝트 기본 TDD 규칙 명시 (CLAUDE.md)

Markdown

# CLAUDE.md
## 테스트 규칙
- 새로운 기능을 구현하기 전에 반드시 실패하는 테스트를 먼저 작성할 것.
- 테스트가 실패하는 것을 확인한 후에만 구현 코드를 작성할 것.
- 모든 테스트가 통과한 후에만 커밋 가능.
- 테스트 삭제, skip, 주석 처리, expect 조건 완화 절대 금지.

③ TDD 단계별 슬래시 커맨드 커스텀

🔴 Red 단계 (.claude/commands/tdd-red.md)

Markdown

# TDD Red Phase
다음 기능에 대한 **실패하는 테스트만** 작성해주세요: $ARGUMENTS
## 규칙
1. 구현 코드는 절대 작성하지 않습니다.
2. 테스트 파일만 생성 또는 수정합니다.
3. 테스트가 실패하는 원인을 명확히 설명합니다.

🟢 Green 단계 (.claude/commands/tdd-green.md)

Markdown

# TDD Green Phase
가장 최근에 작성한 실패하는 테스트를 통과시키는 **최소한의 코드**를 작성해주세요.
## 규칙
1. 테스트를 통과시키는 가장 단순한 로직만 작성합니다 (하드코딩 허용).
2. 미래를 위한 추상화 코드를 금지합니다.

🔵 Refactor 단계 (.claude/commands/tdd-refactor.md)

Markdown

# TDD Refactor Phase
테스트 통과 상태를 유지하며 코드를 리팩터링해주세요.
## 규칙
1. 새로운 기능을 추가하거나 테스트를 수정하지 않습니다.
2. 가독성 향상 및 중복 제거에만 집중합니다.

실제 사용예시: /tdd-red 이메일 중복 체크 함수 ➔ /tdd-green ➔ /tdd-refactor

6. AI로 인한 회귀(Regression) 현상 자동 차단 전략

AI가 기존의 잘 동작하던 코드를 훼손하지 못하도록 자동화 안전망을 설치해야 합니다.

① Pre-commit 커밋 전 자동 테스트 Hook

JSON

{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "INPUT=$(cat); CMD=$(echo \"$INPUT\" | jq -r '.tool_input.command // empty'); if echo \"$CMD\" | grep -qE 'git commit'; then npm test; fi",
"timeout": 180
}
]
}
]
}
}

② 테스트 Skip 편법 방지 셸 스크립트 (.claude/hooks/detect-test-skip.sh)

Bash

#!/bin/bash
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(test|spec)\.(ts|tsx|js|jsx)$')
for FILE in $STAGED_FILES; do
if git diff --cached "$FILE" | grep -E '^\+.*(\.skip|\.only|xtest|xit)'; then
echo "[ERROR] $FILE 에서 테스트 skip/only 가 감지되었습니다."
echo "테스트를 우회하지 말고 원인을 해결해 주세요."
exit 1
fi
done

③ 신규 코드의 테스트 존재 여부 자동 검증 (.claude/hooks/check-test-exists.sh)

Bash

#!/bin/bash
STAGED_SRC=$(git diff --cached --name-only --diff-filter=A | grep -E '^src/.*\.(ts|tsx|js|jsx)$' | grep -vE '\.(test|spec)\.')
for SRC_FILE in $STAGED_SRC; do
BASE_NAME=$(basename "$SRC_FILE" | sed 's/\.[^.]*$//')
DIR_NAME=$(dirname "$SRC_FILE")
TEST_FILE_1="${DIR_NAME}/${BASE_NAME}.test.ts"
TEST_FILE_2="${DIR_NAME}/${BASE_NAME}.spec.ts"
TEST_FILE_3="${DIR_NAME}/__tests__/${BASE_NAME}.test.ts"
if [[ ! -f "$TEST_FILE_1" && ! -f "$TEST_FILE_2" && ! -f "$TEST_FILE_3" ]]; then
echo "[ERROR] $SRC_FILE 에 대응하는 테스트 파일이 존재하지 않습니다."
echo "TDD 원칙에 따라 테스트 코드를 먼저 작성해 주세요."
exit 1
fi
done

7. 마치며: AI 시대, TDD의 가치는 더 커졌다

AI 시대로 접어들면서 TDD의 가치가 퇴색된 것이 아니라 오히려 필수불가결한 엔진 제어 장치가 되었습니다.

AI가 빠르게 생성해 내는 수많은 코드들 사이에서 “이 변경사항이 정말 안전한가?”라는 질문에 확실히 답할 수 있는 유일한 수단은 잘 짜인 테스트 스위트뿐입니다.

AI를 단순한 대체재가 아닌 생산성을 극대화하는 파트너로 삼기 위해, 오늘부터 프로젝트에 TDD와 감시 Hook 설정을 도입해 보세요.

Posted in

댓글 남기기

봉로그에서 더 알아보기

지금 구독하여 계속 읽고 전체 아카이브에 액세스하세요.

계속 읽기