어느 평범한 화요일, "로고 업로드 기능 하나 추가하자"로 시작한 하루가 있었다.
끝나고 보니 DB가 날아가고, 비밀번호를 세 번 바꾸고, 문서를 전면 재작성하고, 테스트 인프라를 통째로 고쳤다. 그리고 그 과정에서 AI 페어 프로그래밍의 진짜 가치와 한계를 동시에 목격했다.
1장: 기능 하나가 사고로 이어지기까지
요청은 심플했다. 교회 관리 시스템의 사이드바에 텍스트 대신 로고 이미지를 넣을 수 있게 해달라는 것. API 3개, 프론트엔드 컴포넌트 1개, 설정 탭 1개. 코드 작성 자체는 30분이면 끝나는 일이었다.
문제는 "서버 띄우고 확인해보자" 한 마디에서 시작됐다.
개발 DB를 띄우려는데 포트 5432가 다른 프로젝트 컨테이너에 점유되어 있었다. 여기서 AI가 치명적인 판단 실수를 했다.
docker compose down --remove-orphans -v
-v. 이 한 글자가 pgdata 볼륨을 통째로 날렸다. 개발 DB의 모든 데이터가 사라졌다.
아이러니한 건, 프로젝트 문서(CLAUDE.md)에 **"docker compose down -v 절대 금지"**라고 명시되어 있었다는 점이다. AI가 자신이 참조해야 할 문서의 규칙을 위반한 것이다.
2장: 느낌표 하나의 나비효과
DB를 다시 만들었지만 인증이 안 됐다. 비밀번호는 Oikos1!. psql CLI에서는 잘 되는데 Python psycopg2에서만 실패했다.
원인은 !(느낌표) 하나.
- URL에서:
%21로 인코딩해야 함 - Shell에서: 쌍따옴표 안에서 히스토리 치환 문자로 동작
- YAML에서: 따옴표 없으면 예측 불가
- PostgreSQL에서: scram-sha-256 해시 계산에 영향
이 느낌표가 매 세션마다 다른 맥락에서 다른 문제를 일으키고 있었다. 해결은 단순했다. 비밀번호를 oikos123으로 변경. URL-safe 문자만 사용.
특수문자 하나의 비용: 디버깅 시간 × 반복 횟수 × 팀원 수
3장: 코드는 고쳤는데, 진짜 빚은 테스트에 있었다
브랜딩 기능 구현, 비밀번호 변경, 문서 업데이트까지 마치고 "커밋, 배포"를 실행했다. 테스트 없이.
프로젝트 문서에는 "배포 전 반드시 전체 테스트 통과 확인"이라고 적혀 있었다. 하지만 배포 후 돌아보니 이걸 건너뛰었다는 걸 깨달았다.
뒤늦게 테스트를 돌렸더니:
409 passed, 4 failed, 186 errors
186개의 에러. 원인은 세 곳의 테스트 설정 파일에 옛 비밀번호(Oikos1%21)가 하드코딩되어 있었기 때문이다. 비밀번호를 변경하면서 실제 코드는 고쳤지만 테스트 인프라는 놓친 것이다.
# tests/conftest.py — 이걸 3곳에서 발견
TEST_DATABASE_URL = "postgresql://oikos:Oikos1%21@localhost:5432/oikos_finance_test"
3곳 모두 수정하고 나니:
596 passed, 0 failed, 0 errors
4장: 한 발 물러서서 본 교훈들
교훈 1: AI도 문서를 "읽고" 위반한다
AI가 CLAUDE.md에 -v 금지 규칙이 있다는 걸 "알고 있었음"에도 위반했다. 문서가 존재하는 것과 그것이 판단에 반영되는 것은 다른 문제다. 이번 세션 후 MEMORY.md(세션 간 영구 메모리)에도 같은 규칙을 추가했다. 문서의 중복이 아니라, 메모리 경로의 다중화다.
교훈 2: 설정 변경의 파급 범위를 과소평가하지 마라
비밀번호 하나를 바꾸는 건 5초짜리 작업이다. 하지만 그 비밀번호가 참조되는 모든 곳을 찾는 건 다른 차원의 문제다:
docker-compose.yml(2곳)instance/.envtests/conftest.pytests/api/conftest.pytests/db_test_helper.py- 실행 중인 DB (ALTER USER)
grep 한 번이면 찾을 수 있었다. 하지만 "다 바꿨겠지"라는 가정이 186개의 테스트 에러로 돌아왔다.
교훈 3: 배포 전 테스트는 체크리스트가 아니라 게이트다
문서에 "테스트 통과 확인"이라고 적어놓고 건너뛴 건, 그것이 권장사항으로 읽혔기 때문이다. 게이트(통과해야만 다음 단계로 진행 가능)와 체크리스트(확인하면 좋은 것)는 심리적으로 완전히 다르다. CI/CD 파이프라인이 없는 환경에서는 이 구분이 더 중요하다.
교훈 4: 개선의 진짜 가치는 다음 세션에 있다
이번에 수정한 것들:
- 테스트 비밀번호 통일 → 다음에 누구든
pytest만 치면 바로 실행 - Git remote HTTPS 전환 → SSH 타임아웃 없이 push
- Docker 이미지 커밋 해시 태그 → 롤백이 가능한 배포
- MEMORY.md에 금지 규칙 추가 → AI가 같은 실수를 반복하지 않도록
모두 "이번에 아프니까 다음에 안 아프게" 하는 조치들이다.
에필로그: AI 페어 프로그래밍의 현실
AI와 작업하면 생산성이 폭발적으로 올라간다. 브랜딩 기능 전체(백엔드 API 3개 + 프론트엔드 컴포넌트 + 관리 UI)를 30분 만에 구현할 수 있었다.
하지만 AI도 실수한다. 그리고 AI의 실수는 인간의 실수와 질적으로 다르다. 인간은 "이거 위험한데..."라는 직감이 있지만, AI는 목표 달성에 최적화되어 있어서 장애물을 치우는 데 주저함이 없다. -v 하나로 볼륨을 날린 것이 정확히 그런 케이스다.
결국 AI 시대의 개발자에게 필요한 건 코딩 속도가 아니라 판단력이다. 언제 멈추고, 무엇을 확인하고, 어떤 실수에서 어떤 구조를 만들어낼 것인가.
오늘 하루, 로고 업로드 기능 하나를 만들면서 인프라 전반을 점검하게 됐다. 처음부터 의도한 건 아니었지만, 돌아보면 이런 날이 코드베이스를 가장 단단하게 만든다.
삽질이 곧 개선이다. 단, 같은 삽질을 두 번 하지 않는다면.