AI가 스스로의 시스템을 이해하지 못하는 것에서 당신을 구원할 수 없는 이유
요약
AI 덕분에 소프트웨어 개발 속도는 매우 빨라졌지만, 그 과정에는 '시스템 전체를 이해하는 능력'이라는 함정이 숨어 있습니다. 필자는 특정 버그를 추적하며, AI가 코드를 생성하고 가설을 세우는 데 도움은 되지만, 실제 라이브 시스템의 요청/응답 사이클이나 복잡한 아키텍처의 이음매에서 발생하는 근본적인 문제를 스스로 디버깅하는 능력은 대체할 수 없음을 강조합니다.
핵심 포인트
- AI는 코딩 속도를 혁신적으로 높여주지만, 전체 시스템 이해가 필수적이다.
- 실제 버그는 엔드포인트 자체가 아닌 미들웨어 등 요청의 전 경로에서 발생했다.
- AI는 가설을 제시할 뿐, 실제 라이브 환경에서의 독립적인 검증은 개발자가 해야 한다.
시스템 설계는 대부분의 사람들이 깨닫지 못하는 것보다 더 중요하며, 우리 대부분은 그것을 매일 의식하지 않고 실천하고 있습니다.
AI 덕분에 소프트웨어 구축 속도는 그 어느 때보다 빨라졌습니다. AI는 몇 초 만에 프로젝트를 뼈대(scaffold)로 만들고, CRUD 계층을 생성하며, 이해하기 모호한 개념을 설명해주고, 아이디어를 몇 분 만에 작동하는 프로토타입으로 만들어줍니다. 지금 코딩을 배우고 있다면, 이것은 5년 전 개발자들이 가질 수 없었던 엄청난 이점입니다.
하지만 그 속도 속에 조용한 함정이 숨어 있습니다: AI는 당신이 그것이 구축한 것을 따라갈 수 있는 능력만큼만 유용합니다.
이번 주에 저는 그 교훈을 매우 구체적으로 깨닫게 해준 버그를 만났습니다.
찾으려 했던 곳에 있지 않았던 버그
저는 에스크로 플랫폼의 백엔드, 즉 핸들러(handlers), 서비스(services), 리포지토리(repositories), 미들웨어(middleware)로 구성된 계층형 아키텍처를 가진 Go API 작업을 하고 있었습니다. 하나의 엔드포인트가 계속해서 아무런 오류 본문 없이 단순히 400 Bad Request만 반환했습니다.
당연히 살펴봐야 할 곳은 그 엔드포인트 자체였습니다. 라우트(route)는 존재했고, 핸들러도 올바른 것처럼 보였으며, 서비스 로직도 괜찮아 보였습니다. 저는 증상이 나타난 바로 그 함수를 감히 인정하고 싶지 않을 만큼 오래 응시했습니다.
하지만 실제 문제는 전혀 다른 곳에 있었습니다.
알고 보니 이전에 테스트했던 오래된 액세스 토큰(access token)이 요청이 제 핸들러에 도달하기도 전에 조용히 검증에 실패하고 있었던 것입니다. 라우트 앞에 위치한 미들웨어가 이를 거절했고, 저에게 유용한 어떤 종류의 오류 메시지도 없이 조용히 처리했습니다.
수정할 부분은 엔드포인트가 아니었습니다. 시스템을 통과하는 요청의 전체 경로—미들웨어, 그리고 핸들러, 서비스, 리포지토리 순서로—를 이해하고, 각 경계마다 로그 라인을 추가하며 한 계층씩 추적해 나간 후에야 정확히 실행이 멈춘 지점을 찾을 수 있었습니다.
AI가 이것을 저 대신 해결할 수 없었던 이유
AI가 이것을 저 대신 해결할 수 없었던 이유
이 부분이 제가 깊이 생각해보고 싶은 부분입니다. 단순한 일화가 아니라 실제 교훈이라고 생각하기 때문입니다.
만약 제가 AI 비서에게 "왜 이 엔드포인트에서 400 에러가 반환되나요?"라고 물었다면, 보여준 코드를 바탕으로 추론할 수 있었고, 실제로 이 경우에는 정확하게 그랬습니다. 하지만 AI는 제가 제공한 것만을 가지고 추론할 뿐입니다. 제 실행 중인 서버의 라이브 뷰(live view), 실제 요청/응답 사이클(request/response cycle), 또는 데이터베이스 상태를 알지 못합니다. 저의 curl 명령을 직접 실행하고 무슨 일이 일어나는지 지켜볼 수도 없습니다.
패턴을 기반으로 가장 가능성이 높은 원인들을 제시할 수는 있지만, 그중 어떤 것이 제 특정 실행 시스템에서 실제로 참인지 독립적으로 검증할 수는 없습니다.
이 검증 단계 — 즉 실제 디버깅은 여전히 여러분 스스로가 조각들이 어떻게 맞물리는지에 대한 이해를 가지고 해야 합니다. AI는 가설을 더 빠르게 세우도록 도울 수 있습니다. 하지만 여러분 자신의 애플리케이션의 실제, 라이브 동작을 추적하는 것을 대체할 수는 없습니다.
이것은 작은 규모(400 에러 하나)에서도 사실이며, 시스템 설계 수준에서는 더욱 그렇습니다. AI는 그럴듯해 보이는 아키텍처 — 여기 서비스 계층(service layer), 저기 리포지토리(repository), 종이 위에서 깔끔해 보이는 미들웨어 체인(middleware chain) — 을 생성하는 데 탁월합니다. 하지만 그럴듯한 것과 여러분의 실제 시스템에 맞는 '정확한' 것은 다릅니다. 만약 아키텍처가 왜 그렇게 형태를 갖추었는지 이해하지 못한다면, 그것이 사용 사례에 미묘하게 잘못되었을 때 알아차리지 못할 것이고, AI가 개별적으로 생성한 조각들 사이의 이음매(seams)에서 무언가 고장 났을 때 디버깅하는 것은 확실히 할 수 없을 것입니다.
시스템 설계는 이미 여러분이 연습하고 있는 것입니다
제가 놓치고 있다고 생각하는 것이 있습니다. 시스템 설계는 나중에 습득하게 되는 별도의 고급 학문이 아닙니다. 만약 다음과 같은 질문들을 스스로에게 던져본 적이 있다면:
- "이 유효성 검사(validation)가 핸들러에 있어야 할까요, 아니면 서비스 계층에 있어야 할까요?"
- "만약 이 데이터베이스 호출이 중간에 실패하면 어떻게 될까요?"
- "이 컴포넌트가 저것에 대해 알 필요가 있을까요, 아니면 분리된 상태(decoupled)로 유지되어야 할까요?"
— 당신은 이미 시스템 설계(system design)를 하고 있었던 것입니다. 대부분의 개발자는 이를 매일, 작은 결정들 속에서 하며, 스스로 그것을 그렇게 명명하지는 않습니다. AI가 이러한 질문들에 대한 답변을 생성해 줄 수 있습니다. 하지만 특정 시스템에 어떤 답변이 다른 답변보다 더 나은지 그 이유를 이해하지 못한다면, AI의 답변이 틀렸거나, 일반적으로는 맞지만 당신의 경우엔 틀릴 때 그것을 실제로 포착할 준비가 되어 있지 않은 것입니다.
구체적인 예시: 계층적 유효성 검사 (Layered Validation)
이것을 덜 추상적으로 만들기 위해, 같은 프로젝트에서 가져온 실제 패턴을 소개합니다. 저는 세 가지 관련 리소스—딜(deal), 그 딜에 속하는 아티팩트(artifact), 그리고 그 아티팩트에 속하는 검증(verification)—를 가지고 있습니다.
초기에는 클라이언트가 URL로 deal A의 ID를 전달하면서도 deal B의 ID를 사용하여 아티팩트 ID를 요청하는 것을 막는 것이 아무것도 없었습니다. ID들은 독립적으로 해석되었고, 각 ID가 데이터베이스에 개별적으로 존재하기만 하면 요청은
- 제안된 패턴이 왜 작동하는지 묻는 것, 단순히 작동한다는 것을 받아들이는 것이 아닌
- 상황이 잘 돌아가고 있을 때조차도 요청이 통과하는 모든 레이어를 의도적으로 추적하여, 내 시스템의 형태를 실제로 알게 만드는 것
- 버그를 단순히 증상을 패치할 기회가 아니라 아키텍처를 더 잘 이해할 기회로 여기는 것
- 단순히 코드를 생성하고 그것이 완전하기를 바라는 것이 아니라, 실제 실패 사례를 추론하여 나만의 검증 로직을 작성하는 것
이 모든 것은 AI를 불신한다는 의미가 아닙니다. 이는 시스템 설계에 있어 AI의 유용성이 명확한 상한선(hard ceiling)이 있다는 것을 인식하는 것입니다. 즉, AI는 당신이 대화에 가져오는 정신적 모델(mental model)만큼만 좋을 수 있습니다. 만약 당신 자신이 자신의 시스템을 이해하지 못한다면, 미묘하게 잘못된 제안과 진정으로 좋은 제안을 구분할 수 없습니다. 단지
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기