첫 커밋에 화면 코드가 한 줄도 없었습니다
- 공유 링크 만들기
- X
- 이메일
- 기타 앱
개발자로 밥벌이를 시작한 지 서른 해가 되는 해를 얼마 앞두고 있습니다. 그동안 남들이 만든 설계문서를 받아 개발하는 일을 몇 번 했는지는 세어 확인한 적은 없습니다.
지난주에도 그런 일을 하나 추가했습니다. 기획과 화면정의와 DB 구조와 목업까지 전부 만들어진 상태로 넘어온 프로젝트였습니다. 음성 콘텐츠 구독 서비스라는 것까지만 적겠습니다. 발주처가 있는 일이라 서비스 이름도 저장소도 공개하지 않고, 소스와 파일 경로도 인용하지 않습니다.
명세가 다 나와 있는 일은 굉장히 편한 축입니다. 무엇을 만들지 정하는 회의가 없고 화면이 몇 개인지도 이미 계획되어 있습니다. 이번에도 문서 여섯 종에 목업이 스물일곱 장이었으니 개발만 하면 되는 상태로 보였습니다.
열어 보니 사람이 검토한 문서가 아니었습니다. AI 로 작업한 지 2년째라 이제는 문서를 보면 누가 작성했는지 대체로 알아봅니다. 표기에 흔적이 남습니다. 「(핵심)」 같은 괄호 라벨이 문서 세 종에 하나씩 똑같이 붙어 있고, 세 쪽 분량인 기획 문서 하나에 엠대시가 다섯 번 나옵니다. 문장을 화살표로 이어 붙인 표기는 문서 전체에 마흔 번이 넘습니다. 사람이 그때그때 고른 표기라면 이렇게 균질하지 않습니다. 어느 도구였는지까지는 모르겠고 이 글에서 중요하지도 않습니다. 검토를 시작하자마자 확인된 것은 그쪽이 아니라 아무도 이 문서를 검토하지 않았다는 것이었습니다.
명세 파일 여섯 종의 타임스탬프가 9월 4일 오전 6시 56분으로 전부 같습니다. 한 번에 받았다는 뜻입니다. 첫 커밋이 9월 5일 오후 2시 39분, 마지막 커밋이 9월 7일 오후 6시 8분이고 그 사이에 커밋 76건이 들어갔습니다. 앞의 이틀은 주말이라 오전에 개인 일과가 있었고 마지막 날은 평일이라 저녁에야 손을 댔으니, 실제로 붙어 있던 시간은 이틀보다 짧습니다.
제가 하려는 건 이틀 만에 관리자 페이지와 앱과 인프라와 e2e 테스트까지 나왔다는 이야기가 아닙니다. 제가 지금 다시 확인하는 것은 그 이틀의 첫 커밋입니다.

첫 커밋 82개 파일에 화면 코드는 README 두 장뿐이었습니다
첫 커밋에 파일 82개가 들어갔습니다. 그중 화면을 구현한 코드는 하나도 없습니다. 관리자 웹 폴더와 앱 폴더에 README 한 장씩, 두 장이 전부입니다.
나머지는 셋이 채우고 있습니다. 하나는 하네스 파일 21개입니다. 에이전트 정의 5개, 스킬 10개, 워크플로우 1개, 스펙 문서 1개, 세션 상태 파일 2개입니다. 다른 하나는 전달받은 명세 그 자체로, 문서 6종과 UI 목업 HTML 27종입니다. 마지막이 데이터베이스인데 마이그레이션 12개와 RLS 정책 1개가 들어갔고, 여기에 Edge Function 2개가 붙었습니다. 공용 인증과 관리자 사용자 처리입니다.
하네스라고 쓴 건 에이전트에게 줄 역할과 절차를 파일로 적어 둔 것입니다. 누가 어느 영역을 맡는지, 무엇을 근거로 답해야 하는지, 어디까지 손을 대도 되는지를 문서로 정해 두고 작업을 시작합니다. 코드가 아니라서 저장소에서는 그냥 텍스트 파일 스물한 개로 보입니다.
에이전트 다섯은 설계문서 담당, 데이터 모델 담당, 관리자 웹 담당, Flutter 앱 담당, 검수 담당입니다. 스킬 열 개는 작업 종류별로 나뉘어 있습니다. 화면 수용기준을 어떤 형식으로 적는지, 마이그레이션을 어떤 순서로 올리는지, RLS 정책을 어떻게 쓰는지, 목업을 실제 화면으로 옮길 때 무엇을 지키는지, 오디오를 어떤 경로로 내보내는지, 검수를 어떤 절차로 도는지가 각각 한 장씩입니다.
화면 코드가 없는 첫 커밋이 이상하게 보일 수도 있습니다. 보통은 프로젝트를 열면 프레임워크부터 깔고 화면 한 장을 띄워 놓고 시작합니다. 그래야 돌아가는 걸 보면서 붙여 나갈 수 있으니까요. 이번에는 그 순서 대신 명세와 하네스와 스키마가 먼저 들어갔고 화면은 다음 날부터 붙었습니다.
이 21개를 언제 만들었는지는 커밋으로 가릴 수 없습니다. 전부 첫 커밋에 한꺼번에 들어와 있기 때문입니다. 확실한 건 명세를 받은 9월 4일 오전과 첫 커밋 사이 서른두 시간 안에 만들어졌다는 것, 그리고 화면 코드가 한 줄도 없는 시점에 이미 저장소 안에 있었다는 것입니다. 그 서른두 시간 안에서 제가 무엇을 먼저 하고 무엇을 나중에 했는지는 기억으로만 적을 수 있어서 여기서는 적지 않겠습니다.
명세가 틀려 있을 것을 전제한 역할이 하네스에 있었습니다
설계문서 담당 에이전트의 작업 원칙을 다시 읽어 봤습니다. 첫 커밋 시점의 내용이고 나중에 덧붙인 것이 아닙니다.
문서에 없는 것을 지어내지 않고, 없으면 문서에 없다고 답한다. 문서 사이에 모순이 보이면 즉시 보고하고 어느 쪽이 맞는지 임의로 고르지 않는다. 미확정 항목에 값을 채우지 않고, 그 항목에 기대는 작업이 있으면 진행 전에 막는다. 답할 때는 화면번호와 목업 파일명을 근거로 대서 구현자가 원본을 직접 확인할 수 있게 한다. 설계문서 원본은 어떤 경우에도 수정하지 않고 편집 권한을 작업 폴더로 한정한다.
첫 항목에 이유가 한 줄 붙어 있습니다.
추정한 값을 사실처럼 넘기면 그 추정이 다음 세션의 기준이 되어 버립니다.
이 한 줄은 AI 가 거짓말을 한다는 이야기가 아닙니다. 추정을 추정이라고 표시해 두지 않는다는 이야기입니다.
AI 는 명세를 의심하지 않습니다. 적힌 대로 만듭니다. 빈칸이 있으면 그럴듯한 값으로 채우는데, 문제는 채운 다음입니다. 화면 하나를 만들면서 채운 추정이 그 화면을 참조하는 다음 화면의 근거가 됩니다. 세션이 끊겼다가 다시 붙으면 그 추정은 이미 코드 안에 들어가 있으니 확정된 사실처럼 읽힙니다. 되돌리려면 어디서부터가 추정이었는지를 사람이 찾아야 하는데, 그 값에는 표시가 남지 않습니다. 그래서 나중에 발견하면 고치는 대상이 값 하나가 아니라 그 값을 전제로 쌓인 코드 전부가 됩니다.
이번 명세에도 그렇게 채워질 항목이 여럿 있었습니다. 오디오를 어디에 두고 어떤 형식으로 내보내는지가 문서에 없었는데, 묻지 않고 만들면 무난한 형식 하나가 정해지고 업로드와 재생과 보안 처리가 전부 그 위에 얹힙니다. 나중에 실물 형식이 다르다는 게 확인되면 고칠 곳이 한 군데가 아닙니다.
의심하는 역할을 코드보다 먼저 정의해 둔 셈입니다. 정확히는 의심이 아니라 정지입니다. 모르는 것을 만나면 채우지 말고 멈추라는 지시고, 멈춘 항목을 사람에게 올리라는 지시입니다.
마지막 줄은 성격이 조금 다릅니다. 설계문서 원본을 건드리지 않는다는 건 편의를 포기하는 조항입니다. 문서에서 틀린 것을 찾았으면 그 부분을 고쳐 놓는 것이 당장은 편합니다. 대신 그렇게 하면 발주처가 준 원본과 대조할 기준이 없어집니다. 무엇을 받았고 무엇을 우리가 바꿨는지가 섞이면 나중에 회신이 왔을 때 어느 쪽이 원래 문장이었는지 알 수 없게 됩니다. 그래서 원본은 두고 작업 폴더에서만 손대게 했습니다.
다섯 줄이 전부 같은 실패를 막습니다. 모르는 것을 모르는 채로 남겨 두지 못하는 것입니다. 사람이 하면 이건 확인해 봐야 알겠다는 말이 자연스럽게 나오는데, 지시를 받은 쪽은 답을 내놓는 게 일이라 빈칸을 만나면 답을 만듭니다. 그래서 답하지 않아도 되는 경우를 미리 적어 준 것입니다.
같은 파일에 이미 잡아 둔 모순이 한 건 적혀 있습니다. 화면정의서의 두 항목이 기존 화면을 재사용하는 걸 전제하고 쓰였는데, 전면 재구축이 결정되면서 그 전제가 사라진 상태였습니다. 첫 커밋 시점에 명세의 모순 하나가 이미 문서에 적혀 있었다는 뜻입니다.
설계문서가 「앱」이라고 부른 것은 이미 돌아가는 웹이었습니다
명세를 훑으면서 걸리는 것을 따로 모았습니다. 이 분석이 언제 끝났는지는 애매합니다. 문서의 마지막 수정 시각이 구현 기간과 겹치기 때문입니다. 시작이 착수 전이었다는 것까지만 말할 수 있습니다.
모인 항목은 열다섯 건입니다. 운영 쪽 이슈가 여덟 건이고 설계 자체의 결함이 일곱 건인데, 그중 셋은 그대로 운영에 나갔으면 되돌릴 수 없는 것이었습니다.
열다섯 건은 성격이 두 갈래입니다. 여덟 건은 지금 돌아가고 있는 서비스를 새 구조로 옮길 때 생기는 것들입니다. 기존 사용자를 어떻게 이관하는지, 결제 이력을 어디까지 가져오는지 같은 것이라 문서가 틀렸다기보다 문서가 다루지 않은 항목입니다. 나머지 일곱 건이 설계 자체의 문제입니다. 문서가 다루고 있고, 다룬 내용을 그대로 만들면 안 되는 것들입니다.
제일 먼저 걸린 건 단어 하나였습니다. 설계문서가 기존 서비스를 계속 「앱」이라고 부르는데, 그 앱의 기술 스택은 미확정으로 남아 있었습니다. 실물을 열어 봤습니다. 네이티브 앱이 아니라 이미 운영 중인 웹 서비스였고 PWA 로 감싸져 있었습니다.
단어 하나가 어긋난 것뿐인데 네 군데에 영향을 미쳤습니다. 재구축을 어떤 방식으로 하느냐, 오디오 보안을 어디서 거느냐, 기존 사용자를 어떻게 옮기느냐, 콘텐츠 분류를 새 구조에 어떻게 맞추느냐가 전부 이 답에 따라 갈립니다. 문서를 쓴 사람에게 「앱」은 개발 용어가 아니라 사용자가 쓰는 화면을 가리키는 일상어였습니다. 문서 안에서는 아무 문제가 없는 말입니다. 그 문서를 받아서 만드는 쪽에서만 문제가 됩니다.
미확정이라고 적혀 있는 항목은 그래도 눈에 띕니다. 더 위험한 것은 확정된 것처럼 읽히는 일상어입니다. 「앱」은 문서 안에서 미확정 표시가 붙어 있지도 않았습니다. 읽는 사람이 개발자면 자동으로 기술 스택으로 읽고, 쓴 사람은 그런 뜻으로 쓴 적이 없습니다. 양쪽 다 자기 뜻으로는 아무 문제가 없는 문장이라 아무도 묻지 않습니다.
미확정으로 남아 있던 항목 여섯 개가 이 분석에서 답이 나왔는데, 전부 실물을 열어서 확인한 것입니다. 오디오 파일이 어떤 형식인지, 전체가 어느 정도 용량인지, 기존 서비스가 실제로 무엇으로 돌아가고 있는지, 서버와 DB 가 따로 있는지, 이어듣기 위치를 어디에 저장하고 있는지입니다. AI 에게 물어서 나온 답이 하나도 없습니다. 물어볼 근거가 문서인데 문서에 없는 것들이었으니까요.
결제매핑 테이블에 기간 컬럼이 없었습니다
되돌릴 수 없다고 본 셋 중 하나가 방금 적은 「앱」입니다. 나머지 둘을 적어 두겠습니다.
결제와 콘텐츠를 잇는 테이블에 들어 있는 건 콘텐츠와 사용자와 결제일 셋뿐이었습니다. 언제까지 들을 수 있는지를 적는 컬럼이 없습니다. 만료 판단은 콘텐츠 쪽에 붙은 종료일 하나로만 합니다.
여기까지만 보면 그냥 단순한 설계입니다. 실제로 화면을 만들고 결제를 붙이면 정상으로 돌아갑니다. 문제는 운영을 시작한 다음에 나옵니다.
한 사람이 사정이 있어서 청취 기간을 조금 늘려 달라고 합니다. 늘리려면 콘텐츠의 종료일을 미뤄야 하고, 미루는 순간 그 콘텐츠를 결제한 사람 전원의 기간이 같이 늘어납니다. 한 명을 위한 조정이 항상 전체 조정이 됩니다.
이런 건 개발 중에는 잘 안 보입니다. 테스트 데이터는 보통 한 명이고, 한 명일 때는 전체 연장과 개별 연장이 같은 결과를 냅니다. 사람이 여럿 붙고 그중 한 명만 다르게 처리해야 하는 날에 처음 갈라집니다. 운영 몇 달 뒤일 수도 있습니다.
설계문서에는 이 종료일이 관리자가 의도적으로 청취 기간을 연장하는 용도라고 적혀 있었습니다. 적힌 용도가 불가능한 게 아니라, 그 용도로 쓰면 늘 전체가 딸려 옵니다.
되돌릴 수 없다고 본 이유는 스키마를 나중에 못 고쳐서가 아닙니다. 컬럼은 언제든 추가할 수 있습니다. 다만 그때는 결제가 이미 쌓여 있고, 과거 결제 건의 기간을 무엇으로 채울지 정할 근거가 없습니다. 결제일에 며칠을 더할지, 결제하던 시점에 콘텐츠 종료일이 무엇이었는지를 소급해서 알아내야 하는데 그 이력을 남기는 컬럼도 없습니다. 운영 첫날부터 데이터가 그렇게 쌓입니다.
분류를 어떻게 나누느냐가 곧 판매 단위를 정하는 일이었습니다
다른 하나는 권한 판단의 단위입니다. 결제한 항목 하나가 유효하면 그 항목이 속한 분류 전체가 열립니다. 결제 이후에 그 분류로 새로 들어온 콘텐츠까지 같이 열립니다.
새 콘텐츠를 따로 팔려면 분류를 새로 만들어야 합니다. 그런데 분류는 사용자 쪽 화면에서 콘텐츠를 찾는 기준이기도 합니다. 판매를 이유로 분류를 쪼개는 순간 분류는 콘텐츠의 성격이 아니라 판매 묶음을 뜻하게 되고, 사용자가 보는 목록과 필터가 같이 어긋납니다. 듣는 사람 입장에서는 같은 성격의 콘텐츠가 왜 두 군데로 갈라져 있는지 알 수 없습니다.
명세대로 만들어 두고 나중에 발견하면 선택지가 둘입니다. 분류를 쪼개고 사용자 화면 쪽을 포기하거나, 권한 판단 단위를 바꾸느라 이미 팔린 결제 건을 전부 다시 맞추거나입니다. 둘 다 운영 중에 하기에는 큰 작업입니다.
여기서 멈췄습니다. 분류를 어떻게 나눌지는 개발이 정할 수 있는 게 아닙니다. 무엇을 한 덩어리로 파는지를 정하는 일이고 그건 사업 쪽 결정입니다. 명세에는 분류가 이미 나뉘어 있었지만 그 나눔이 판매 단위를 겸한다는 이야기는 어디에도 없었습니다. 물어볼 항목이 비어 있는 게 아니라, 적힌 것을 그대로 만들면 그 결정이 자동으로 내려져 버립니다.
되돌릴 수 없는 셋 중 둘이 DB 였습니다
세 건 다 명세에서 빠진 항목이 아닙니다. 적힌 대로 만들면 문제가 되는 항목입니다. 이 차이가 이번 작업에서 제일 크게 남았습니다.
빠진 것은 AI 에게 맡겨서 걸러 낼 수 있습니다. 문서에 없으면 없다고 말하게 해 두면 됩니다. 적힌 것이 틀렸다는 판정은 물어볼 대상이 없습니다. 문서는 자기가 틀렸다고 말하지 않고, AI 는 그 문서를 근거로 답하니까요. 근거로 삼는 물건 자체를 의심하라는 지시는 지시로 성립하지 않습니다.
그리고 이 세 건이 앞에서 적은 것의 증거이기도 합니다. 검토를 한 번이라도 했으면 셋 다 걸립니다. 한 사람만 기간을 늘려 주는 상황을 떠올려 보면 기간 컬럼이 없다는 것이 드러나고, 새 콘텐츠를 따로 팔아 보려고 하면 분류가 곧 판매 단위라는 것이 드러납니다. 「앱」은 실물을 한 번 열어 보면 끝나는 일이었습니다. 셋 다 어려운 판정이 아니라 아무도 해 보지 않은 판정입니다. 문서를 만드는 데 든 공은 분량으로 남아 있는데, 그 문서를 돌려 본 흔적은 어디에도 없었습니다.
명세를 지켰는지 아닌지는 대조로 확인할 수 있습니다. 화면번호마다 목업이 있으니 만든 화면이 그것과 같은지 확인하면 됩니다. 검수 담당 에이전트가 하는 일이 그겁니다. 반대로 명세가 맞는지는 대조할 상대가 없습니다. 기준으로 삼는 문서가 검사 대상이 되는 순간 기준이 하나 사라집니다. 그 부분을 지금은 사람이 메우고 있습니다.
그리고 이 셋 중 둘이 DB 설계 문제입니다. 첫 커밋에 마이그레이션 12개와 RLS 정책이 들어 있던 것과 같은 이유라고 봅니다. 화면은 틀리면 다시 만들면 됩니다. DB 는 운영 데이터가 쌓이는 순간부터 수정 비용이 크게 올라갑니다. 그래서 화면보다 DB 를 먼저 확정했고, 확정하려고 스키마를 들여다보는 동안 결함이 나왔습니다. 화면부터 만들었으면 이 둘은 결제를 붙이는 시점에나 보였을 겁니다.
커밋 76건은 가운데 날에 몰려 있습니다
9월 5일에 29건, 9월 6일에 37건, 9월 7일에 10건입니다. 가운데 날이 제일 많습니다.
목업 스물일곱 장을 실제 화면으로 옮기는 작업이 커밋을 잘게 쪼갠 결과라고 보고 있습니다. 만들 것이 이미 그림으로 나와 있으면 판단할 게 적고 손만 빠르면 됩니다. AI 를 투입해서 시간이 확실히 줄어든 구간을 하나 고르라면 이쪽입니다. 반대로 첫 커밋 전의 서른두 시간과 마지막 한 시간 십육 분은 커밋 수로는 거의 잡히지 않는 구간입니다. 이틀이라는 숫자를 이 분포 없이 말하면 손이 빨라서 이틀인 것처럼 들립니다.
이틀의 마지막 한 시간 십육 분도 하네스였습니다
9월 7일 커밋은 10건인데 그중 9건이 하네스 정비입니다. 16시 52분에 시작해서 18시 8분에 끝났습니다.
되돌릴 수 없는 삭제 명령을 훅으로 막고 배포를 승인 대상에 넣었습니다. 상태 파일 여기저기에 흩어져 있던 배포 상태를 한 자리로 모으고, 점검용으로 만든 하네스도 타입 검사를 받게 했습니다. 운영 기억에 적힌 내용과 앱 담당 에이전트의 지시를 실제 상태에 맞췄습니다. 테스트용 합성 이메일의 사본이 실제로 몇 곳에 있는지 세어서 일곱 곳으로 맞추고 그 대조를 자동화했습니다. 재고 목록이 최신인지 보는 검사에 커밋 전 호출자를 붙였고, 콘솔 오류 점검 대상에 상세 화면 다섯을 넣었고, 공지 데이터가 0건인 상황에 걸려 있던 점검을 옮겼습니다.
커밋 제목에 「실제 상태에 맞춘다」가 두 번 그대로 들어가 있습니다. 하나는 운영 기억이고 하나는 에이전트 지시입니다. 둘 다 이틀 전에 제가 직접 작성한 것입니다.
어긋난 이유는 간단합니다. 이틀 동안 실제 구조가 바뀌었기 때문입니다. 첫 커밋 시점에 앱은 README 한 장이었고 이틀 뒤에는 화면과 상태 관리와 오디오 재생이 다 들어가 있습니다. 그 사이 앱 담당 에이전트가 들고 있던 지시는 README 한 장이던 시점의 문장 그대로였습니다.
이틀 만에 어긋났습니다. 미리 세워 둔 것이 그대로 간다는 이야기가 아니라, 세워 두면 어디가 어긋났는지 보이는 상태가 된다는 정도로 보고 있습니다. 세워 둔 게 없으면 어긋난 것도 안 보입니다. 이틀짜리 작업에서 정비에 한 시간 십육 분을 쓴 건 그래서고, 다음 작업이 이 저장소를 이어받을 때 걸리는 것을 여기서 줄여 둔 셈입니다.
삭제를 막으려고 넣은 훅이 삭제를 이야기하는 글까지 막았습니다
16시 52분에 되돌릴 수 없는 삭제 명령을 막는 훅을 넣었고, 18시 8분에 그 훅을 고쳤습니다. 명령을 실행할 때만이 아니라 문서에 그 명령을 적기만 해도 걸렸기 때문입니다. 한 시간 십육 분 사이입니다.
훅은 사람이 아니라 명령 문자열을 봅니다. 문자열만 보는 검사에 예외를 붙이기 시작하면 검사 자체가 헐거워지니까, 처음에는 넓게 걸어 놓고 실제로 걸리는 걸 보면서 좁히는 편이 낫다고 판단했습니다.
이틀 작업의 마지막 커밋이 그날 오후에 자기가 세운 방어의 과잉 작동을 고치는 내용이었습니다. 방어를 세우면 그 비용을 바로 치릅니다. 그래도 순서는 이쪽이 맞다고 판단합니다. 과하게 막아 놓고 푸는 것과 안 막아서 지워진 걸 복구하는 건 되돌리는 비용이 다릅니다.
하네스라고 불렀지만 원래 하던 환경 구축이었습니다
첫 커밋의 파일 스물한 개를 원래 하던 일로 바꿔 적어 봤습니다. 에이전트 다섯은 담당 분리입니다. 누가 설계문서를 해석하고 누가 데이터 모델을 잡고 누가 화면을 맡는지를 정하는 일입니다. 스킬 아홉은 작업 종류별 규약입니다. 마이그레이션을 어떤 순서로 올리는지, 화면 수용기준을 어떤 형식으로 적는지가 여기 들어갑니다. 스펙 문서 하나는 요구사항 기준선이고, 세션 상태 파일 둘은 인수인계 문서입니다.
폴더 구조 스킬이 특히 그렇습니다. Feature-Sliced Design 을 쓰기로 하고 레이어를 여섯으로 나눈 다음, 위에서 아래로만 의존하고 같은 레이어끼리는 직접 참조하지 않는다는 규칙을 적었습니다. 그다음에 이 프로젝트의 entities 를 일곱 개로 확정하고 제외한 셋은 왜 제외하는지를 붙였습니다. 화면번호 하나가 페이지 하나에 대응하고 모달은 페이지가 아니라는 판정도 여기 있습니다. 판단의 근거도 한 줄 적혀 있습니다. 슬라이스를 잘게 쪼갤수록 좋아 보이지만 혼자서는 화면에 나오지 않는 것을 슬라이스로 만들면 실제로 여는 파일 수만 늘어난다는 내용입니다.
이건 프론트엔드 아키텍처 문서입니다. 프로젝트를 시작할 때 원래 정하는 것들인데, 보통은 정하고 나서 문서로 남기지 않습니다. 첫 화면을 만들면서 즉흥으로 정해지고, 그 결정은 폴더 구조에만 남습니다. 나중에 들어온 사람은 구조를 보고 규칙을 역산해야 하고, 역산이 틀리면 다른 규칙으로 파일이 하나 더 쌓입니다.
나머지 세 개는 작업 중에 추가됐습니다. 관리 웹 스캐폴딩이 9월 5일 오후 5시 18분이고 서버 상태 규약 스킬이 5시 30분입니다. 12분 차이입니다. 공통 자산을 먼저 확인하게 하는 스킬이 그날 밤 10시 43분, 디자인 시스템 스킬이 11시 17분에 붙었습니다. 환경을 세우면서 나온 결정을 그때그때 파일로 옮긴 것입니다.
정리하면 제가 이틀 동안 한 일 중 하네스라고 부른 부분은 원래 하던 환경 구축이고, 달라진 건 그 결정을 말이 아니라 파일로 적었다는 것뿐입니다. 사람에게 시킬 때는 말로 해도 통합니다. 옆자리에서 물어보고, 리뷰에서 걸리고, 몇 번 어긋나면 맞춰집니다. AI 에게는 그 경로가 없습니다. 적어 두지 않은 규칙은 존재하지 않는 규칙이고, 적어 두지 않으면 매 세션 처음부터 시작합니다.
신입 다섯 명에게는 하는 일을 AI 에게는 건너뜁니다
원래 하던 일이라면 왜 AI 작업에서는 이걸 건너뛰는지가 남습니다.
신입 다섯 명이 같은 날 들어오면 아무도 알아서 해 보라고 하지 않습니다. 누가 무엇을 맡을지 나누고, 코딩 컨벤션을 알려 주고, 브랜치를 어떻게 따는지 설명하고, 리뷰는 누가 보는지 정합니다. 그 절차를 건너뛰면 일주일 뒤에 다섯 사람이 다섯 가지 방식으로 짜 놓은 코드를 보게 된다는 걸 알고 있습니다.
AI 에게는 그 절차를 건너뜁니다. 혼자 다 해 줄 것처럼 보이기 때문입니다. 실제로 시켜 보면 화면 한 장은 잘 나옵니다. 문제는 열 장째부터고, 그때는 이미 열 장이 서로 다른 규칙으로 쌓여 있습니다. 신입 다섯 명일 때와 같은 결과인데, 다섯 명일 때는 시작 전에 막고 AI 일 때는 안 막습니다.
이번에 제가 한 것도 특별한 판단이 아닙니다. 사람 여럿에게 일을 나눠 줄 때 하던 순서를 그대로 했을 뿐입니다. 달라진 건 상대가 사람이 아니라는 것 하나입니다.
이틀이 끝나고 남은 열다섯 건은 개발이 못 닫습니다
이슈 문서의 마지막 장 제목이 「지금 남은 것」이고 첫 문장이 이렇습니다.
개발로 끝낼 수 있는 것은 없다. 아래는 전부 판단이나 외부 확인을 기다린다.
남은 항목을 처리 주체로 나눠 보면 사업 판단이 여덟 건, 발주처 확인이 세 건, 사업과 법무가 같이 봐야 하는 것이 한 건, 앱과 콘텐츠 쪽 판단이 세 건입니다. 개발이 혼자 닫을 수 있는 항목이 하나도 없습니다.
해결 표시가 붙은 두 건도 성격이 같습니다. 하나는 코드를 옮기는 작업이 끝나고 옛 키를 언제 끄느냐는 시점 판단만 남았습니다. 다른 하나는 발주처 회신이 와서 범위 안으로 들어왔습니다. 개발이 끝냈다기보다 판단이 와서 진행된 것입니다.
이틀 동안 나온 것은 관리자 웹 한 벌과 Flutter 앱, Edge Function 네 개와 마이그레이션과 스토리지, 테스트 파일 16개에 케이스 84개입니다. 그중 e2e 가 9개 파일입니다. 작업하면서 만든 문서가 여섯 종이고 개발자에게 넘기는 문서가 431줄, 이슈 분석이 355줄입니다. 개발을 모르는 사람이 같은 명세를 받았으면 훨씬 오래 걸렸을 거라고 보지만, 대조군이 없는 제 추정입니다.
개발자에게 넘기는 문서를 431줄 작성한 것도 같은 이유입니다. 판단이 오면 그 지점에서 이어서 개발할 수 있게 어디까지 왔고 무엇이 왜 열려 있는지를 적어 둔 것입니다.
이 목록을 확인하면 이번 작업에서 제 시간이 실제로 어디에 들어갔는지가 다시 드러납니다. 개발은 이틀에 끝났고 그 이틀은 명세가 정해 준 대로 움직이는 구간이었습니다. 남은 열다섯 건은 정해 줄 사람이 아직 정하지 않은 것들이라 제가 앉아서 더 빨리 할 수 있는 게 없습니다. 개발이 빨라져도 이 목록은 짧아지지 않습니다. 오히려 개발 시간이 줄어든 만큼 이 목록이 전체 일정에서 차지하는 비중이 커집니다.
명세를 AI 가 작성했고 구현도 AI 가 했습니다. 그 경로에서 사람이 손을 댄 것은 사이에 낀 열다섯 건뿐입니다.
개발에 걸린 시간이 이틀이고, 만들고 나서 남은 것이 개발로는 못 닫는 열다섯 건입니다. 빨라진 만큼 남는 것이 판단으로 몰립니다.
아이 둘에게 무엇을 준비시켜야 할지는 못 정했습니다
이번 이틀에 제가 실제로 작업한 부분을 되짚어 보면 코드를 작성한 손이 아닙니다. 결제매핑 테이블을 확인하다가 기간 컬럼이 없다는 것을 알아챈 순간, 「앱」이라는 단어를 그냥 넘기지 않고 실물을 열어 본 순간, 분류를 쪼개면 사용자 화면이 어긋난다는 것을 먼저 확인한 순간입니다. 셋 다 코드를 작성하기 전입니다.
이러한 경험이 어떻게 쌓였는지 저도 정확히 모르겠습니다. 서른 해 가까이 남의 설계문서를 받아서 만드는 동안 몇 번 실패하면서 쌓였다고 짐작할 뿐입니다. 그 실패를 겪으려면 일단 틀린 명세대로 만들어 보고 운영에서 장애를 겪는 것을 확인해야 합니다. 그 과정이 한 번에 몇 달, 몇 년씩 걸렸습니다.
지금은 만드는 데 이틀입니다. 개발 시간이 줄면 틀린 것을 끝까지 만들어 보고 실패하는 횟수도 같이 줄어듭니다. 저는 그 실패를 다 겪고 여기 왔는데, 아이들은 그 경험 없이 도구부터 쥐게 됩니다.
틀린 것을 만들어 보는 경험을 일부러 시킬 수도 없습니다. 틀린 줄 알고 만드는 건 실패가 아니니까요. 명세를 읽다가 이건 이대로 만들면 안 된다고 말하는 일이 지금은 사람 쪽에 남아 있고, 이번 이틀이 그걸 한 번 더 보여 줬다고 생각합니다. 그런데 그 몫이 십 년 뒤에도 사람 쪽에 남아 있을지는 모르겠습니다. 남는다고 보고 준비시키는 것도 없어진다고 보고 준비시키는 것도 지금은 근거가 없습니다.
goldtagworks.com 에 발자취를 정리하고 있습니다. 정작 아이 둘에게 무엇을 준비시켜야 하는지는 아직 못 정했습니다. 명세를 읽다가 멈추는 감각을 실패 없이 얻는 방법이 있는지부터 모르겠습니다.
댓글
댓글 쓰기