같은 앱을 두 번 만들었습니다—직접 만든 방식과 AI를 사용한 방식 비교
요약
작성자는 같은 앱을 직접 개발한 버전과 AI가 코드를 작성하게 한 버전을 비교했습니다. AI 버전이 더 깔끔하고 기능적으로 우수했지만, 작성자는 오히려 자신이 직접 만든 '버전 원'에 대해 더 큰 신뢰를 느꼈습니다. 이 경험은 코드의 품질이나 속도가 아닌, 개발 과정에서 얻는 깊은 이해와 지식(지도)이 진정한 '신뢰'임을 보여줍니다.
핵심 포인트
- AI가 생성한 코드는 기술적으로 우수하지만, 개발자가 가진 내부적인 '지식 지도'를 대체할 수 없다.
- 진정한 신뢰는 코드의 정확성 자체가 아니라, 시스템의 취약점과 작동 원리를 깊이 이해하는 데서 온다.
- 코딩 과정에서 겪는 고민(멈춤)들이 쌓여 만들어지는 것이 개발자의 핵심적인 지적 자산이다.
몇 달 전 바보 같은 작은 실험을 했습니다. 저는 똑같은 앱을 두 번 만들었습니다.
첫 번째는 느린 방식, 즉 제가 예전에 모든 것을 만들던 방식으로 직접 코딩했습니다. 대부분 타이핑했고, 막힐 때만 AI를 찾았습니다. 이 작업은 거의 일주일의 저녁 시간을 필요로 했습니다.
그리고 한 달 후, 지루함 반, 호기심 반으로 전체 프로젝트를 버리고 처음부터 다시 구축했습니다. 기능과 사양은 동일합니다. 다만 이번에는 AI가 코드를 작성하도록 맡겼습니다. 제가 원하는 바를 설명했고, 그것이 결과물을 내놓았고, 저는 방향을 잡아주었습니다. 이 작업은 오후 시간을 넘기지 않았습니다.
두 번째 버전이 더 좋습니다. 코드가 더 깔끔하고, 거친 부분이 적으며, 명명 규칙도 더 일관성이 있습니다. 심지어 첫 번째 버전에서는 통과하지 못했던 몇 가지 엣지 케이스(edge-case) 테스트까지 통과했습니다. 대시보드에 표시될 모든 수치에서 AI 버전이 승리했고, 그 차이는 결코 작지 않았습니다.
그리고 저는 그것을 덜 신뢰하게 되었습니다. 조금 덜가 아니라, 훨씬 덜 신뢰하게 되었습니다.
그 간극이야말로 제가 계속 곱씹어 온 전부입니다. 왜냐하면 그런 간극은 존재해서는 안 되는 것이기 때문입니다. 더 나은 코드는 더 많은 신뢰를 얻어야 하는데, 그렇지 않았습니다. 제 경험은 정반대였습니다.
속도와 신뢰는 무관하지 않았습니다. 역의 상관관계에 있었습니다.
저는 신뢰가 품질을 따라갈 것이라고 가정했습니다. 더 좋은 코드를 작성하면 당연히 더 신뢰하게 될 것이라고 생각했죠. AI 버전은 실제로 더 높은 품질입니다. 그런데 왜 저는 직접 만든 버전을 쉽게 열어보지만, AI로 만든 버전은 매번 약간 주저하게 되는 걸까요?
제가 빠르게 만들수록, 그것이 어디서 고장 날지 알게 되는 정도가 적었습니다. 이 두 가지는 잘못된 방향으로 함께 움직였고, 한 번 보고 나니 저는 그 것을 잊을 수 없었습니다. 이는 신뢰가 애초에 코드의 속성이 아니었음을 의미합니다. 그것은 다른 무언가의 속성이었고, 빠르고 편리한 버전이 저에게 말해주지 않은 방식으로 건너뛴 것이었습니다.
'신뢰'가 실제로 무엇이었는지 밝혀진 것
제가 첫 번째 버전을 직접 만들었을 때, 저는 리포(repo)에 포함되지 못한 무언가를 얻게 되었습니다. 바로 지도였습니다.
어떤 부분이 핵심을 담당하는 부분(load-bearing)인지, 어떤 부분이 임시방편적인지(duct tape)를 알고 있었습니다. 목록이 이미 정렬되어 있다고 조용히 가정하는 하나의 함수도 알고 있었습니다. 만약 동일한 요청이 두 번 들어올 경우, 끔찍한 일이 발생하는 정확한 지점도 알고 있었습니다. 아무도 그것을 문서화하지 않았습니다. 그건 제 머릿속에 존재했고, 저는 알아차리지 못한 채 그것을 구축해 왔습니다. 결정 하나하나가 쌓여서, 이 모든 라인들이 저를 잠시 멈추게 했기 때문입니다. 여기에서 승인(Ack)할까, 아니면 저장 후에 할까? 이 입력을 신뢰할까, 아니면 검증할까? 이게 두 번 호출되면 어떻게 될까? 매번의 멈춤은 마치 '무덤이 파묻힌 곳'을 표시하는 정신적 지도 위에 작은 못 자국을 남겼습니다.
그 지도가 바로 '신뢰(trust)'입니다. "코드가 정확하다"는 것이 아닙니다—저는 어느 버전에 대해서도 그것을 실제로 증명할 수 없습니다. 신뢰란 "여기서 코드가 깨지는 곳을 안다"는 것입니다. 저는 버전 원(version one)에 대한 그 지도를 가지고 있었습니다. 하지만 버전 투(version two)에는 없었고, AI가 아무리 깔끔한 코드를 제공해도 저에게 줄 수는 없는 것이었습니다.
타이핑 자체가 핵심이 아니었다. 지도가 나온 곳이었다.
저를 실제로 불안하게 만든 부분은 바로 이것입니다.
오랫동안 저는 손으로 코드를 작성하는 가치가 그 코드 자체에 있다고 생각했습니다. 기술(craft). 결과물(output)에 말입니다. 그렇지 않았습니다. AI가 제 손보다 더 나은 코드를 작성합니다—버전 투는 이 논쟁을 종결지었습니다. 타이핑은 하나의 _부산물(side effect)_이었습니다. 타이핑이 비밀리에 만들어낸 것은 바로 지도였습니다. 모든 키 입력은 작은 결정이었고, 제가 실제로 축적하고 있던 것은 그 '결정'들이었습니다.
저는 코드를 제조한다고 생각했습니다. 저는 그것이 어디서 깨지는지에 대한 지식을 제조하고 있었고, 코드는 부수적인 결과물(byproduct)일 뿐이었습니다. AI는 저에게 그 부산물을 공짜로 건네주면서, 제가 실제로 필요했던 것을 조용히 가져갔습니다.
그것을 증명하는 단 하나의 라인
제가 정확한 라인을 가리킬 수 있도록 구체적으로 말씀드리겠습니다.
두 버전 모두 요청을 기록(acknowledge)하고 나서 행(row)을 영속화(persist)하는 쓰기 경로(write path)가 있습니다. 버전 원에서는 제가 그 라인을 작성했던 것을 기억합니다. 멈칫거렸던 것도 기억합니다. 순서 때문에 마음 한구석이 싸늘해져서, 승인(ack)을 저장 아래로 옮겼던 것도 기억합니다.
그 차가운 느낌에는 원인이 있습니다. 몇 년 전 저는 정확히 그런 버그를 배포한 적이 있습니다. 클라이언트에게 아무것도 저장하기 전에 "받았다"고 알리는 쓰기 경로(write path)였습니다. 코드는 깨끗했고, 관용적이었으며 (idiomatic), 테스트되었고, 성공적이었습니다 (green). 그러던 어느 평범한 날 재시도(retry)가 잘못된 순간에 발생했습니다: "받았다"는 메시지는 나갔지만, 저장은 이루어지지 않았고, 돈을 내는 고객은 로그 기록 어디에도 그들이 존재했다는 흔적 없이 자신의 계정에 잠겼습니다. Ack before persist. 저는 아직도 그 전화 통화가 느껴집니다.
그래서 제가 버전 1에서 이 줄을 직접 타이핑했을 때, 상처(scar)가 작동했고, 저는 버그가 발생하기 전에 그것을 고쳤습니다.
버전 2에서는 AI가 같은 줄—ack before persist—를 자신감 있고 깨끗하게 작성했고, 저는 그 위를 그냥 지나갔습니다. 한 달 만에 제가 더 멍청해져서가 아닙니다. 제가 직접 타이핑하지 않았기 때문입니다. 결정이 저를 거치지 않았기에, 상처는 작동할 기회조차 얻지 못했습니다.
그 순간 깨달았습니다. 타이핑은 단지 지도를 만드는 것이 아니었습니다. 그것은 _체크포인트(checkpoint)_였습니다. 모든 줄이 통과하던 관문이었고, 그곳에서 제 상처들 각각이 진입에 대한 투표권을 얻곤 했습니다. 타이핑을 자동화하면 단순히 지도만 잃는 것이 아닙니다. 제가 판단력을 사용하던 유일한 장소, 즉 매 줄마다 자동으로, 그리고 무료로 자문받던 곳 자체를 제거하는 것입니다.
명확히 하자면 — 이것은 "손으로 작성하기"가 아니다
저는 여러분에게 모든 것을 타이핑하며 되돌아가라고 말하는 것이 아닙니다. 저는 버전 2를 배포했고, 버전 1을 배포한 것이 아닙니다. AI 코드가 더 좋고, 저는 결코 그 앱을 다시 수작업으로 만들지 않을 것입니다. 타이핑 자체가 가치 있어서는 안 됩니다.
실제 함정은 이것입니다: 마치 키 입력(keystrokes)이 신성한 것처럼, 느려지고 더 많이 타이핑하는 것이 해결책이라고 생각하는 것입니다. 그렇지 않았습니다. 문제는 AI가 코드를 작성한다는 것이 아닙니다. 문제는 우리가 코드를 얻고 지도가 그에 붙어 있다고 가정했다는 점입니다—마치 지난 20년 동안 항상 그랬던 것처럼 말이죠. 왜냐하면 지난 20년 동안 지도를 만드는 작업 없이는 코드를 얻을 수 없었기 때문입니다.
예전에는 지도가 무료였다. 원하든 원하지 않든 키스트로크와 함께 기본으로 제공되었다. 이제는 분리되었고, 대부분의 사람들은 그 지도를 돈을 내지 않고 코드와 함께 배포하며 그 속도를 순수한 승리로 간주한다.
그래서 나는 지금 의도적으로 지도를 따로 구매한다
일이 바뀌었다. 더 이상 타이핑만으로는 지도를 얻을 수 없기 때문에, AI가 코드를 작성한 후에 내가 의도적으로 그것을 구매한다:
나는 마치 낯선 사람이 쓴 것처럼 diff를 읽는다. 나에게 데모에서 잘 보이게 하려고 애쓰지만, 새벽 2시에 무슨 일이 벌어지는지는 전혀 신경 쓰지 않는 낯선 사람처럼. 왜냐하면 그게 바로 작성한 방식이기 때문이다. 여기서 감탄은 적이다. 더 깔끔해 보일수록 내가 읽기는 더 어렵다.
모든 파일에 대해 나는 "이건 ___ 할 때 깨진다"고 스스로에게 말한다. 특히 소리 내어 말한다. 만약 문장을 완성할 수 없다면, 그것은 통과가 아니라 구멍이다. 그리고 그 구멍은 아직 내가 이해하지 못한 부분이다. '보기 좋다'는 지도가 아니다. 지도의 부재일 뿐이다.
나는 작게 배포한다. 플래그 뒤에, 카나리(canary)에게, 내부 사용자 한 명에게만. 그래야 내가 놓친 지도 부분이 저렴하게 채워지기 때문이다. 진짜 고객 앞에서 새벽 2시에 비싸게 채우는 대신 말이다.
이 모든 것은 타이핑과는 무관하다. 이것은 예전에 타이핑이 나를 위해 해주던 일인데, 우연이 아니라 의도적으로 하는 것이다. diff를 그냥 받아들이는 것보다 느리다. 하지만 버전 원을 작업하며 보냈던 시간의 아주 작은 일부일 뿐이다. 그리고 이것은 AI가 진정으로 줄 수 없는 한 가지, 즉 그 문제가 어디서 발생하는지 아는 것을 나에게 가져다준다.
내가 이렇게 구축하는 정확한 이유
한 단계 위로 올라가도 문제는 똑같다.
코드를 작성하는 에이전트(agent)는 빠르고, 깔끔하며, 지도 없이 아름다운 결과물을 만들어낸다. 그리고 지도가 없는 것보다 더 나쁜 것은—자신의 작업에 서명한다는 것이다. diff를 작성한 주체에게는 의심할 만한 흉터도 없고 아무것도 없다. 그것은 버전 원의 자신감과 버전 두의 능률을 갖추었지만, 얻어낸 주의력은 전혀 없는 상태다. 가장 위험한 조합이다: 유창하고, 빠르며, 자기 자신을 완전히 불신할 수 없는 상태.
그래서 저는 코드를 작성하는 주체가 그 코드를 축복하는 주체가 되지 않도록 했습니다. 차이점(diff)을 빠르게, 깔끔하게, 지도 없이 생성하는 저자가 있습니다. 그리고 이 저자가 건너뛰는 지도를 구축하는 것이 전적으로 임무인 별도의 회의론자(skeptic)가 있습니다: 낯선 사람처럼 diff를 읽고, '이건 _일 때 깨지네', 무너지게 만들려고 시도합니다. 그리고 병합 버튼(merge button) 앞에 있는 인간이 호출권을 가지고 실제 상처들을 계속 수집합니다. 저자, 회의론자, 인간. 회의론자는 타이핑된 것이 _좌석_으로 바뀐 것입니다. 마치 모든 줄이 통과했던 검문소처럼, 저자가 빨라지면서 사라지지 않도록 그 자체로 재구축되었습니다. 이것이 바로 xenition 전체의 형태입니다.
저는 계속해서 그것(AI)이 코드를 작성하도록 내버려 둘 것입니다. 타이핑 자체가 목적은 아니었습니다. 버전 2가 그것을 확실히 증명했습니다. 하지만 저는 지도가 키스트로크와 함께 공짜로 온다고 착각하는 것을 멈췄습니다. 왜냐하면 더 이상 그렇지 않기 때문입니다. 코드는 빨라졌지만, 신뢰는 따라오지 않았습니다. 그래서 이제 저는 신뢰를 그 자체의 항목으로 의도적으로 비용을 지불합니다. 왜냐하면 그것이 작업의 부수 효과가 아니게 되었기 때문입니다.
저는 같은 앱을 두 번 만들었습니다. 빠르게 배포하는 버전은 제가 출시할 버전이고, 느리게 만든 버전은 빠르면서 놓치고 간 것들을 저에게 가르쳐 준 버전입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기