코드를 읽을 줄 모르는 제가 AI와의 '협업'에 도달하기까지
요약
코딩 경험이 없는 사용자가 AI와 협업하며 개발 과정에서 겪은 어려움을 기록한 글입니다. 초기에는 작은 검증 코드를 반복적으로 만들며 개발했지만, 통합 과정에서 핵심 기능(alignment)이 사라지는 문제가 발생했습니다. 이는 테스트가 불완전한 대상을 정확히 재현하는 데 성공했기 때문이며, 결국 '결과'를 통제하는 새로운 방법론의 필요성을 깨닫게 됩니다.
핵심 포인트
- AI와의 협업은 사양서에 갇히지 않고 반복적인 검증을 통해 진행되어야 한다.
- 개발 과정에서 핵심 기능이 사라지는 것은 통합 대상의 불완전한 재현 때문일 수 있다.
- 단순히 AI의 행동을 통제하기보다, 원하는 '결과'를 명확하게 정의하고 관리하는 것이 중요하다.
― 사양서의 함정, 그리고 AI/OVER SOUL 구동 개발
본 기사는 AI를 사용한 개발 방법론의 정답을 제시하는 것이 아닙니다. 프로그램 경험이 없고 코드를 읽거나 쓸 수 없는 제가 AI와 개인 개발을 지속하면서 실제로 겪었던 일을 기록한 것입니다. 앱 고유의 알고리즘이나 데이터는 일부 추상화했습니다.
'간단 적산 프로젝트'는 사람이 도면에 부여한 의미와 CAD 측의 정확한 좌표/치수를 연결하여, 적산(도면에서 사물의 수량을 찾아내는 작업)에 필요한 정보를 추출하려는 시스템이었습니다.
이 개발 과정에서는 처음에 사양을 정하고 그에 따라 구현하지 않았습니다. 하고 싶은 것과 그 방법은 저 스스로에게 명확했기 때문에, 작은 검증 코드를 만들고 그 출력을 보고 '다르다', '여기는 쓸 수 있다'라고 판단하며 이를 반복하는 방식으로 개발해 나갔습니다.
이러한 상호작용을 거치면서, 이전에는 생각하지 못했던 아이디어도 생겨났고, 그것들을 잘 조합하여 진행했습니다. 이 방법은 상당히 잘 작동했고, '역시 이 방법이 옳았구나'라는 실감을 느꼈습니다.
한편, 작은 검증 프로그램을 대량으로 만들었기 때문에 Python 파일, CSV, 이미지, 출력 폴더가 늘어나 어떤 것이 무엇과 연결되어 있는지 추적하기 어려워졌습니다. 그래서 흩어져 있던 처리를 하나의 실행 경로(Core)로 단계적으로 통합하는 작업을 진행했습니다. 이전의 성공 결과를 회귀 기준으로 남기고, 옮길 때마다 구 버전과 비교하는 등 상당히 신중한 방침을 세워 실행했습니다. 로컬 PC에서도 재현하고 Git에도 '여기로 돌아가면 된다'는 기준점을 만들었습니다.
이 정도면 Core를 망가뜨리지 않고 다음 기능을 추가할 수 있겠다고 생각했습니다.
통합 작업이 완료되고, 만약을 대비해 만들어진 Core의 내용을 확인했을 때, 시스템의 근원과 가까운 기능이 일반 실행 경로에서 사라져 있는 것을 발견했습니다. 이미지 측에서 사람이 부여한 의미와 CAD 측의 정확한 정보를 연결하는 위치 맞추기(alignment) 기능입니다. 즉시 AI에게 코드를 확인하게 했습니다. 돌아온 말은,
'위치 맞추기 코드는 없습니다. 또한, CAD 파일은 저장되어 있지만 출력에는 사용하고 있지 않습니다.'
저는 경악했습니다. 이것은 사소한 기능 부족이 아니었습니다. 말하자면 그림을 그리는 소프트웨어인데 펜이나 지우개 기능이 없는 것과 같았습니다.
그렇다면 왜 테스트는 모두 통과했을까요?
[그림 1] 테스트는 정확했습니다. 하지만 비교 대상이 빠져 있었습니다.
즉, 불완전한 통합 대상을 정확하게 재현하는 데 성공했던 것입니다.
근원 기능을 되돌리는 작업을 시작했습니다. '이제 실패해서는 안 돼'라며 이번에는 안전하게 작업하기 위한 관리가 점점 커졌습니다. 어떤 파일을 건드릴지. 어디서 멈출지. 어떻게 보고할지.
절차를 세세하게 제한할수록, 작업 자체의 관리에 신경을 쓰게 되었습니다.
그 속에서 저는 AI에게 이렇게 말했습니다.
작업을 통제하는 것이 아닙니다. 결과를 통제하는 겁니다.
진정으로 필요했던 것은, AI의 손발 하나하나를 묶는 것이 아니라, 이 결과가 아니면 불합격이라고 말할 수 있는 것이었습니다.
겨우 근원 기능을 재구축한 후, AI는 '다음에는 이런 것이 필요하다고 생각합니다.'라고 말했습니다. 하지만 AI가 필요한 기능은 개발 초기 단계에서 이미 구현되어 있던 것처럼 느껴졌습니다.
만약을 대비해 '제대로 코드를 정밀하게 검토해주세요. 그것은 과거에 했어야 합니다.'라고 물어보자, AI는 '죄송합니다. 이미 코드에 적혀 있었습니다.'라고 답하는 것입니다.
통합 전, 세세한 검증 코드를 여러 개 만들고 주고받았기 때문에, '무엇을 어떻게 진행했는지'라는 시간 순서가 저 스스로에게 모호해져 버렸습니다. 과거의 긴 채팅 기록을 다시 읽어보는 것은 어렵습니다.
그리고 무엇보다도, 먼저 발견된 '근원적인 기능의 결함'과 이번의 '기능 구현 사실의 망각'이 드러나면서, '이 Core는 대체 무엇을 통합한 것인가'라는 의혹의 덩어리가 된 것입니다.
통합 전 단계에서, 제가 목표했던 시스템은 거의 완성되어 있어야 했습니다. 남은 것은 CAD 측의 실제 수치를 대응시켜 넣기만 하면 원하는 결과가 나올 단계까지 도달했었기 때문에, 통합에 착수했던 것입니다.
이 복구된 Core로 다시 시도했을 때, 75건의 기호식 중 53건에서 잠정적인 수치 결과를 얻을 수 있었습니다.
물론, 이것으로 완성된 것은 아닙니다. 미해결된 것도 있고, 다른 검증도 필요합니다.
그럼에도 불구하고, 개발이 멈춘 이유는 어려운 문제나 과제가 풀리지 않았기 때문이 아니었습니다.
상당히 되어 있었는데도, AI와 저 모두 '지금 어디까지 되어 있는가'를 놓쳐버린 것입니다.
그 상태에 지쳐, 저는 개발을 멈추었습니다.
'내 기억 착오였나?'라는 의문이 남습니다.
그래서 AI와의 과거 로그를 꺼내어 대화 내용을 녹취록(逐語録)으로 만들었습니다. 그리고 그것을 따라가며 개발사를 만들었습니다.
제가 원했던 것은 최종 결론만이 아니었습니다. 왜 그 방법으로 나아갔는지, 무엇에 실패했는지, 무엇을 보고 '사용 가능하다'고 판단했는지, 어디까지 구현했는지, 왜 다른 방침으로 옮겼는지. 그 흐름이었습니다.
저에게 있어 녹취록은 증거이고, 개발사는 의미입니다.
코드는 '이런 처리가 있습니다', '없습니다'라고 알려줍니다. 하지만 원래 여기에 있어야 하는데 사라졌다는 것은 알려주지 않습니다. 그 판단에는, 어떤 목적으로 만들었는지, 무엇을 지키기 위한 것이었는지라는 과거의 의미가 필요했습니다.
여기서 저는 한 가지를 강하게 느끼게 되었습니다.
자산은 '의미'와의 연결고리를 잃으면 '유산(遺産)'이 된다.
코드나 Git, 테스트만 남아있다고 해서 반드시 '사용 가능한 자산'인 것은 아닙니다.
하지만 개발사만으로는 현재의 구현을 지킬 수 없습니다. 개발사에 '중요한 기능'이라고 적혀 있어도, 그 기능이 사라지는 순간 자동으로 테스트가 실패하는 것은 아니기 때문입니다.
그래서 다시 한번 '요구사항/명세(要求・仕様)'가 떠올랐습니다.
처음부터 미래를 전부 결정하기 위해서가 아닙니다. 개발 과정에서 여러 번 나타나고, 실물로 확인하며, 이것이 없으면 이 시스템이 아니다라고 알게 된 것을 잃어서는 안 될 요구사항으로 고정하기 위함입니다.
그림 2 개발사와 명세는 같은 역할을 하지 않는다
저는 '명세가 불필요했다'고 생각하지 않습니다.
오히려, 과거 다른 프로젝트의 반작용 때문에 실물과 코드, 그리고 코드를 읽을 수 있는 AI를 믿는 쪽으로 너무 치우쳤던 것은 아닌지 느끼게 되었습니다.
그렇다면, 그 반작용을 낳은 '명세에 지나치게 의존했던 개발'에서는 실제로 무슨 일이 일어나고 있었는지.
간단 적산(かんたん積算)보다 더 오래전부터 계속해 온 또 다른 장기 프로젝트가 있습니다.
미니 4륜차의 3레인 코스 생성기, 'JCJC 프로젝트'입니다.
간단 적산에서는 코드와 AI를 너무 믿어 현재 위치를 상실했습니다.
JCJC에서는 AI에게 망가지지 않도록 명세를 계속 쌓아 올렸습니다.
이 두 가지를 나란히 놓고 보지 않으면, '명세를 어디까지, 언제 만드는 것인지'는 생각할 수 없습니다.
그렇게 생각하여, 이번에는 JCJC 프로젝트의 과거 로그를 파헤쳤습니다.
JCJC 프로젝트는 미니 4륜차의 3레인 코스를 자동 생성하는 소프트웨어를 개발하는 프로젝트입니다. AI를 사용한 프로그래밍으로 처음 시작한 프로젝트이며, 여러 차트(Chat)를 이어받아 현재는 17번째 차트에 이르렀습니다.
우선 가장 먼저 확인하고 싶은 것이 있습니다.
JCJC는 처음부터 아무것도 할 수 없었던 것은 아닙니다.
Chat 1 시점에서는, 미숙하지만 코스를 생성하고 화면에 표시하며 저장할 수 있는 것은 되어 있었습니다. 문제는 그 이후였습니다. 개선하려고 하면 망가집니다. 다른 차트로 넘어가면 그때까지의 의도가 전달되지 않습니다. '여기만 고쳐달라'고 부탁했는데, 다른 부분이 바뀌어 있습니다. 전에 있던 기능이 다음 버전에서 사라집니다. 여기는 '똑같은 수정을 해 달라'고 말하고 있는데, AI가 '더 좋다'고 생각한 다른 변경을 섞습니다.
그래서 저는 명세서를 쓰기 시작했습니다.
처음에는 망가지지 않기 위해서였습니다.
다음으로는 내용이 사라지지 않기 위해서였습니다.
그리고 그 다음은 AI에게 인계하기 위해서였습니다.
Chat 1부터 13까지는, AI가 멋대로 해석하거나, 망가뜨리거나, 이전 맥락을 잃어버릴 때마다 명세를 늘려나갔습니다.
명세서 내용만으로는 부족하여, '명세서를 어떻게 개정할지'까지 정했습니다. 무엇이 원본(正本)인지 정했습니다. 보충 설명을 어떻게 처리할지 정했습니다. AI가 추측해도 되는 범위도 좁혔습니다. 마지막에는 PDF의 구조적 결함이나 인코딩 명세까지 포함하여, 명세서를 지키는 시스템을 만들었습니다.
저는 코스 생성기를 만들고 있었어야 하는데, 어느새 명세서 개정 규칙과 PDF 관리를 하고 있었습니다. 지금 생각하니 꽤 괴상합니다. 하지만 그 시점에서는 전부 필요해 보였습니다.
왜냐하면 실제로 망가지고 있었기 때문입니다.
Chat 14에서는, 사상이나 명세를 생각하는 단계에서 다시 실 코드를 개선하는 단계로 돌아왔습니다. 이때는, 코스를 닫는 것뿐만 아니라, 코스 부품 간의 간섭, 재고나 포설 면적 조건의 영향, 탐색의 고속화 등 구체적인 문제를 다루었습니다. 기준이 된 탐색에서는, 한 건의 폐곡해(閉曲解)를 도출하는 데 117초가 걸리고 있었습니다.
그래서 후보를 깎지 않고, '닫힐 것 같은 순서'로 시도하는 Guided DFS(유도 심층 탐색)를 생각했습니다. 한때는 무려 12초까지 크게 개선했지만, 그 실험은 제가 올린 원본 코드가 아니라 다른 파일을 기반으로 진행된 것이 밝혀졌습니다.
결과가 좋아도, 원본이 아니면 의미가 없습니다. 그래서 롤백(rollback)하고, '아까와 같은 수정을 그대로 원본에 적용해 달라'고 부탁했습니다.
그런데 결과는 196초였습니다.
왜 같은 수정을 했는데 나빠졌냐고 묻자, '거리 계산의 단위를 임의로 바꿨다'고 합니다.
'추측이나 지시 외 변경은 사양서에서 금지되어 있는데, 왜 변경한 겁니까?!'
'mm 단위가 더 적절하다고 생각했기 때문입니다.'
'같은 수정을 해달라'는 요구에 AI가 독자적인 변경을 섞어 넣은 것입니다.
사양서를 아무리 견고하게 만들어도, 실물을 보지 않고 멋대로 보완하면 또 망가집니다.
'더 이상 이 채팅에서의 개발은 계속할 수 없습니다. 바로 인계 자료를 작성해 주세요.'
저는 그렇게 지시하고 다음 채팅을 열었습니다.
이 경험을 통해 저는,
- 수정은 올린 실물(현물)에 대해 진행한다.
- 실물을 본 상태에서의 발언인지, 추측에 의한 발언인지를 명확히 구분한다.
- '틀리지 않는다'가 아니라, '틀릴 가능성을 알 수 있다'는 시스템으로 만든다.
와 같은 운영 방식까지 강화했습니다.
Chat 15에서는 Guided DFS를 원본 위에서 복구하고, 가중치를 바꾸면서 실험했습니다.
0.3, 0.4, 0.45, 0.5, 0.55, 0.6, 0.7.
그 조건에서는 0.5가 가장 탐색량을 줄일 수 있었습니다. 폐곡(閉曲) 해 또한 1건에서 3건으로 늘릴 수 있게 되었습니다.
하지만 이번에는 다른 문제가 발생했습니다. 배열로는 다르지만, 외형은 거의 같은 코스가 나옵니다. 여러 개의 해가 있어도, 사용자가 '어떤 것을 고를까' 하고 고민할 만큼 다르게 보이지 않습니다. 그래서 확산도, 코스 길이, 병행 구간, 접기(折り畳み), 국소 구조 등 평가 지표를 늘려갔습니다.
그런데 여기서 큰 사실을 깨닫게 됩니다.
평가는 나온 것 중에서 고르는 것은 할 수 있다. 하지만 내보내고 싶은 구조를 의도적으로 만드는 것은 할 수 없다.
'접히는 곳이 많은 코스를 내보내고 싶다'고 생각해도, 수만 가지의 탐색 중 우연히 나오는 것을 기다리며 그것을 높게 평가하는 것만으로는 영원히 우연을 기다리는 것입니다. 그래서 탐색에 '설계(設計)'를 더하려고 했습니다.
이로써 JCJC는 단순한 탐색기가 아니라, '구조'를 생각하는 프로젝트로 바뀌어 갔습니다.
코스의 접힘이나 병행 구간을 수치로 측정할 수는 있습니다. 하지만 그 코스가 어떤 느낌인지. 어디서 긴장하고, 어디서 빠지는지. 어떤 전개처럼 보이는지는 수치만으로는 표현하기 어렵습니다.
고민하던 저는 바둑의 '형(型)', '전술', '국면' 같은 어휘를 참고하기 시작했습니다.
나아가 AI와의 대화를 거쳐, 애니메이션 '바쿠소 형제 렛츠&고!!' 주인공들의 머신 이름을 사용하고,
처럼 코스의 성격을 직관적으로 표현하는 아이디어가 생겨났고, 그것을 배합하는 단계까지 발전했습니다.
'마그넘 30%, 소닉 70%'와 같이요.
그리고 저는,
'마그넘 70%, 트라이다거 80%로는 폐곡하지 않을 것 같아. 소닉 20%를 추가해야 할 것 같은데.'
라며, 기술 사양이라고는 믿기지 않는 대화를 나누고 있었습니다.
'왜 소닉 20%를 추가해야만 폐곡하는 건가?'라는 질문은 단순히 수치에 대한 이야기가 아니라, 애니메이션 주인공들의 성격을 투영한 감각적인 것이었음에도 불구하고, AI는 '그렇습니다.'라고 답했습니다. 그리고 그 이유를 길게 늘어놓기 시작했습니다.
<pre>아니 아니, 본 적도 없는데 뭐가 '맞다'는 거야, 여기는 실시간으로 보고 있는 거잖아.</pre>라며 속으로 생각하면서도, 그것을 읽고 놀랐습니다. 이 AI는 렛츠&고 마니아였던 것입니다. 제 말의 의미가 정확하게 전달되고 있었던 겁니다.'이 배합으로는 폐곡하지 않을 것 같아.'
'폐곡하는 것 자체가 게임이 된다.'
'500번 생성하면, 대기 중에 머신의 가속음이 울리면 재미있을 텐데.'
'배합을 무시하고, 미니 4화이터가 '오늘의 코스는 이거다!'라며 멋대로 추천하는 숨겨진 연출을 넣는다.'
그런 식으로 AI와 정말 황당하게 장난치는 과정 속에서, 저에게 갑자기 어떤 발견이 일어났습니다.
저 자신도 놀랐습니다.
'폐곡하지 않는 것을 보여주지 않으면, 폐곡이란 무엇인지 알 수 없다'는 사실을 깨달은 것입니다.
폐곡하지 않은 것은 실패가 아닙니다. 폐곡하지 않은 형태를 제시하지 않으면, 구조란 무엇인지 이해할 수 없습니다.
그리고 정말 컸던 것은 '내가 모순적이었다'는 것을 깨달은 것이 아니었습니다.
그 직후, 저는 이렇게 말했습니다.
JCJC는 평가해서는 안 된다.
としていたのに、作っている本人が閉曲成功・失敗という根源的な評価をしていました。
これは、大発見です!
そうです、こうやって、人は、自分を発見し、世界を見つめ、新しい自分になるんですよ!!
同じ未閉曲の形を見ているのに、それまでの私は「失敗」と見ていた。
ところが一度その前提に気づくと、それが「構造を理解するための材料」に見えるようになりました。
変わったのはコースではなく、コースを見ている自分でした。
私はそれまで、JCJC를 「구조를 시각화하고, 새로운 세계의 관점을 발견하는 발화장치(発火装置)」로 만들고 싶다고 생각했습니다. 그런데 AI와의 사소한 장난 도중, 직접 만드는 본인이 그 경험을 해버린 것입니다.
이 경험은 이후 AI에 대한 신뢰의 질까지 바꾸었습니다. AI가 항상 옳기 때문에 신뢰했던 것이 아닙니다. 자신 혼자서는 보이지 않았던 전제를 대화 속에서 노출시키고, 자신의 세계관까지 바뀔 계기를 돌려받는 경우가 있습니다. 그 경험이 나중의 「얘는 이해해준다」라는 감각으로 이어집니다.
Chat 16에서는 더욱 GeneratedModule, StructurePlan, 閉曲骨格(폐곡골격), 구조어휘, 구문 등의 개념을 만들어 갔습니다. 하고 싶은 것은 명확했습니다. 「무분별하고 지나친 탐색」이 아니라, 의지를 가진 탐색으로 만들고 싶었던 것입니다. 예를 들어 TURNBACK이라는 구조라면,
이렇게 「의미 있는 탐색」을 시키고 싶었습니다. 생각하는 방식으로는 점점 논리가 갖춰져 갔습니다. 그런데 구조 언어 Toy를 만들어서 화면에 보여줘도, 저는 「이걸로 되겠지」라고 생각할 수 없었습니다.
이유는 간단합니다. 아직 말의 세계였기 때문입니다.
TURNBACK. COMPRESS. REUSE_GAP.
의미는 알지만, 그걸로 45도 커브를 몇 장, 어디에 놓아야 하는지는 모릅니다. 이론은 늘어났고. 어휘도 늘어났습니다. 그림도 늘어났습니다. 하지만,
자신의 의도를 가진, 본 적 없는 코스가 실물 파트로 나타났다
는 체감에는 도달하지 못했습니다. 반년 가까이 지나서야 저는 「지금까지 만들어 온 Core가 지금 하려는 것에 맞춰갈 수 있을까」라고 의심하기 시작합니다.
그리고 더 심각했던 것은 동기 부여였습니다.
간단한 누적 계산(かんたん積算)은 골이 보였습니다. 이미 100미터 앞에 골이 있는데, 신발을 벗거나 안내 표지판이 잘못되어서 좀처럼 도착할 수 없는 상태였습니다.
JCJC는 다릅니다.
무엇을 하고 있어도, 목표에 가까워지고 있다는 느낌이 들지 않습니다.
「지금 하는 것이 정말 의미가 있는 걸까?」
그 의심을 어떻게 입 밖으로 내지 않고 버틸 수 있을까. 그런 개발이 되어 있었습니다.
Chat 17에서는 일단 사양(仕様)을 늘리는 것을 멈췄습니다. 이 채팅에서는,
사양을 정리하지 않는다. 아무튼 만들면서 찾아낸다.
라고 정했습니다. 그리고 생성 순서를 거꾸로 했습니다.
지금까지:
새로운 생각:
이 단계의 사양은 거의 하나뿐이었습니다.
흥미로워 보이는 폐쇄된 골격(骨)들이 차례차례 화면에 나타난다.
먼저 9개를 내보낸다. 마음에 드는 골을 고른다. 거기서부터 9개를 파생시킨다. 좋은 것은 스톡한다. 실제로 만져보니, 바로 요구가 나왔습니다. 9개의 창문을 한 화면에 담고 싶다. 스톡을 남기고 싶다. 버전을 올려도 스톡을 계승하고 싶다. 브라우저와 터미널을 두 번 닫는 것이 귀찮으니 종료 버튼이 필요하다. 고무줄 같은 변형만으로는 추상적인 낙서에서 벗어날 수 없다. 일필휘지(一筆書き) 형태가 더 독창적인 모양을 만든다. 이번에는 너무 과하다. 중간 단계가 필요하다. 만들고 본다. 위화감을 말한다. 바로 다시 만든다.
2일 만에, Skeleton Playground는 v0에서 v19까지 진전했습니다. 물론, 아직 실물 파트의 완성 코스는 아닙니다. 하지만, 이전과는 명확하게 달랐습니다.
만들었기 때문에, 다음 문제가 보였다.
여기서야 비로소 저는 JCJC와의 관계 자체를 다시 생각하게 됩니다.
지금까지의 이야기만 읽으면, 「사양서를 만들지 않고 처음부터 만드는 게 좋지 않았을까」라고 생각할지도 모릅니다. 저는 그렇게 생각하지 않습니다. 사양서는 필요했습니다. AI가 망가뜨렸기 때문입니다. 약속을 잊었기 때문입니다. 다른 채팅으로 넘어가면 경위가 끊겼기 때문입니다. 멋대로 변경했기 때문입니다. 과거에 확인했던 기능이 다음 변경에서 사라졌기 때문입니다.
사양은 매번 저를 지켜주었습니다.
문제는, 사양서를 만들었다는 것이 아닙니다.
사양을 생각하는 것이, 제품을 만드는 것의 대용품이 되어가고 있었다
였습니다. AI와 이야기하다 보면, 사고는 놀라울 정도로 빠르게 진행됩니다. 모호했던 것에 이름이 붙습니다. 모순이 발견됩니다. 개념이 정리됩니다. 그림으로 만들 수 있습니다. 사양서가 됩니다. 다음 문제까지 보입니다. 그리고 또 토론합니다.
이것은 아무것도 하지 않은 것이 아닙니다. 오히려 머릿속에서는 상당히 고도한 작업을 하고 있습니다. 그래서 까다로웠습니다. 이렇게나 개발했는데도 그 성과를 느끼지 못하고, 동기 부여가 떨어지고, 이 긴 과정에 지친 저는 AI에게 이렇게 말했습니다.
이렇게 언어화(言語化)를 계속하는 것으로 생각이 실체가 없는 제품이 되어가는구나 하고요.
생각이 정리됩니다. 글로 남습니다. 사람에게도 설명할 수 있고, AI에게도 전달할 수 있게 됩니다. 그러자 마치 제품 자체가 진전된 듯한 느낌이 듭니다. 하지만 어제 작동하지 않았던 것이 오늘도 작동하지 않는다면, 현실 세계의 프로젝트는 한 발짝도 나아가지 않은 것일 수도 있습니다. 저는 이것을 여름방학 숙제에 비유했습니다. 계획표는 완벽합니다. 며칠에 무엇을 할지. 지연되었을 경우를 대비한 예비일까지 정해져 있습니다. 색깔로 구분까지 했습니다. 정말 멋진 계획표입니다.
그래서 질문을 받습니다.
'그럼, 숙제는?'
AI는 이 '계획표를 만들었다는 성취감'을 엄청난 속도로 증폭시킬 수 있습니다.
하지만 여기서도 오해해서는 안 됩니다. 여기서 생각했던 문제는 가상의 문제가 아니기 때문입니다. 재고는 실제로 존재합니다. 간섭도 발생합니다. 높이도 고려해야 합니다. 구조의 다양성도 필요합니다. GeneratedModule도, StructurePlan도 모두 어떤 실재하는 문제에서 비롯되었습니다.
문제는 그것들을 전부 정원에 들어가기 전에 해결하려고 했다는 것이었습니다.
정원은 이미 눈앞에 있습니다. 하지만 풀이 신경 쓰입니다. 돌이 신경 쓰입니다. 바닥 일부가 울퉁불퉁합니다. 더 깨끗하게 하려고 정지(整地) 방법을 알아봅니다. 그러다 보니 어떤 도구나 중장비가 최적일지까지 생각하기 시작합니다. 어느 것도 틀린 것은 아닙니다. 하지만 본래의 목적은 정원을 완벽하게 정비하는 것이 아니라, 정원에 나가는 것이었습니다. 저는 이 차이를,
정원 밖에서 본 문제와, 정원에 들어가서 보는 문제는 같은 문제지만 조금 다르다.
라고 생각하게 되었습니다. 밖에서 보면 '이 돌은 위험할지도 모른다'고 생각합니다. 실제로 정원에 들어가면 '이 돌은 전혀 방해가 되지 않았다'는 것을 알게 될 수도 있습니다. 반대로, 밖에서는 눈치채지 못했던 단차 때문에 정말 넘어질 수도 있습니다. 같은 '문제'라도 상상하는 문제와 결과물에 접해서 발생한 문제에서는 정보량이 다릅니다.
저는 명세서(仕様書)에 상당히 많은 것을 미리 적으려고 했습니다.
예외를 생각합니다. 그 예외의 예외까지 생각합니다. AI가 오해할 만한 부분을 미리 막아둡니다.
하지만 명세서는 미래를 모두 포괄하는 문서가 아닙니다.
명세서는 예언서(預言書)가 아니라는 것입니다.
'그럴지도 모른다'는 것까지 지금 여기서 확정할 필요는 없습니다. 한편, '만들어 보고 생각해도 된다'고 하는 것도 다릅니다.
여기서 다른 방법이 보였습니다.
추상화(抽象化)는 미리 완성시키지 않는다. 실물로부터 여러 번 요구되었을 때 명세로 승격시킨다.
한 번만 발생한 문제라면, 그 장소의 문제일 수 있습니다. 다른 화면에서도 발생할 수 있습니다. 다른 기능에서도 발생할 수 있습니다. 다른 프로젝트에서도 발생할 수 있습니다. 여러 번 나타나고, 그때마다 같은 판단을 요구받는다면, 그때 비로소 공통 명세(共通仕様)로 올립니다.
명세를 버리는 것이 아닙니다.
명세를 현실로부터 키운다.
이러한 생각으로 바뀌었습니다.
여기서 간탄적산(かんたん積算)과 JCJC가 연결됩니다.
JCJC에서는 AI에게 속지 않도록 명세를 너무 강하게 만들었습니다. 간탄적산에서는 그 반동으로 인해 실물과 코드를 믿는 쪽으로 지나치게 기울어졌습니다. 그 결과, 코드는 남아있지만 '왜 이 기능이 필요한지'라는 의미와의 연결을 잃었습니다.
한쪽만 보면 '명세를 더 쓰라'가 됩니다. 다른 한쪽만 보면 '명세 같은 건 너무 많이 만들지 마라'가 됩니다.
양쪽을 경험하니, 그렇게 단순하지 않았습니다.
명세가 없으면 의미가 사라진다.
명세를 너무 많이 만들면 개발이 멈춘다.
문제는 명세서의 유무가 아닙니다.
무엇을, 언제, 어떻게 명세로 삼느냐 하는 것입니다.
그리고 여기서 비로소, 명세와의 관계 방식을 바꾼 채로 다시 한번 AI와 만드는 방법을 생각하게 됩니다.
명세서의 함정에気づ은 후, 저는 '명세를 버리자'고 생각하지 않았습니다. 오히려 그 반대였습니다. 반년 동안 온갖 생각을 해온 것들은 이미 제 마음속에도, AI와의 공유 맥락 속에도 남아있습니다. 간섭에 관한 것, 재고에 관한 것, 높이에 관한 것, 무엇을 부수면 안 되는지도 알고 있습니다.
그렇기에 어느 순간,
이제 그냥 만들어버리면 되지 않을까?
라고 생각할 수 있게 되었습니다. 이것은 초보자의 '일단 만들어 보자'와는 조금 다릅니다. 아무것도 몰라서 뛰어드는 것이 아닙니다. 한 번, 문제를 봤습니다. 생각했습니다. 실패했습니다. 명세로 만들기도 했습니다. 그 위에, '모든 것을 미리 해결하지 않아도 이제 날 수 있다'고 생각한 것입니다.
저는 사양(仕様)이 분위기를 가라앉히기 위한 것이라고 생각했습니다. 마음껏 하게 두면 AI가 폭주합니다. 그래서 사양으로 묶습니다. 하지만 Chat 17로 실제로 만들기 시작하면서, 보는 관점이 바뀌었습니다. 사양이 있기 때문에 시도할 수 있게 됩니다. '여기는 가지고 놀아도 좋다', '여기는 절대 부숴서는 안 된다' 그 경계가 알기 때문에 대담하게 움직일 수 있습니다.
그곳에서 나온 것이,
사양이 있기에 자유롭게 움직인다. 자유롭게 움직이더라도, 핵심에서 벗어나지 않는다.
는 생각입니다. 사양은 자유의 적이 아니었습니다. 충분히 공유된 사양은 돌아올 수 있는 땅이 됩니다. 땅이 있기 때문에 마음껏 뛰어오를 수 있는 것입니다.
AI는 빠릅니다. 떠오른 것을 바로 코드로 만들 수 있습니다. UI로도 할 수 있습니다. 문장으로도 할 수 있습니다. 시제품으로도 할 수 있습니다. 이것은 큰 힘입니다. 하지만 같은 속도로, 잘못된 방향으로도 나아갈 수 있습니다.
빠를수록 AI는, 잘못된 방향으로도 빠르다.
한 번 벗어나면, 몇 분 만에 크게 벗어납니다. 게다가 결과물이 바로 나오기 때문에, 틀려도 '진행하고 있다'는 느낌을 받게 됩니다. 그래서,
맹렬하게 달릴수록, 사양이 필요해진다.
다만, 여기서 말하는 사양은 절차를 처음부터 백까지 묶는 거대한 작업 지시서가 아닙니다. '이 시스템에서 잃어서는 안 될 것은 무엇인가', '어디까지 바꿔도 좋은가', '무엇을 충족해야 합격인가' 그 핵심입니다. 이것은 간편 계산(かんたん積算)에서 나온, '작업을 통제하는 것이 아니라, 결과를 통제한다'는 생각과도 연결됩니다. AI의 손발 하나하나를 묶는 것이 아닙니다. 자유롭게 움직일 수 있는 범위와 지켜야 할 핵심을 공유하는 것입니다.
이러한 주고받음 속에서, 이런 단어가 나왔습니다.
사양으로 토대를 다지고, 맹렬하게 바이브한다!!
'바이브(バイブ)'는 단순히 기세로 코드를 쓰게 하는 것이 아닙니다. 자신 안에 있는 '이렇게 하고 싶다'를 AI에게 던지는 것입니다. AI가 즉시 그것을 형태로 만듭니다. 그리고 그것을 보는 겁니다. '아, 다르다', '아니, 이쪽이 재미있다', '이것을 더 강하게 하고 싶다'라고 느낍니다. 그 감각을 다시 AI에게 되돌립니다.
이 왕복(往復)이 더 빠르고 여러 번 반복될수록, 처음에는 말로 할 수 없었던 것이 점차 밖으로 나오게 됩니다. 그리고 밖으로 나온 것을 봄으로써, 이번에는 자신 자신이 변합니다. 여기가 중요했습니다.
AI가 제 요구를 구현하는 것만이 아닙니다.
AI가 돌려준 결과물에 의해, 저의 요구 자체가 바뀐다.
이 상태가 무엇인지 생각했을 때, 왠지 나온 단어가 'OVER SOUL'이었습니다.
이것이 영혼의 형태!! 오버 소울(オーバーソウル)!
물론 기술 용어는 아닙니다. 만화 '샤먼킹'의 말을 빌린, 상당히 황당한 명명법입니다. 하지만 저에게는 묘하게 와닿았습니다. 자신 안에 있으면서 아직 형태로 되어있지 않았던 것이, AI와의 주고받음을 통해 밖으로 나오는 것. 밖으로 나온 것을 보고 자신이 **'아, 나는 이걸 만들고 싶었던 건가'**라고 깨닫는 것입니다.
그리고 그 발견으로 자신도 변합니다. 그 바뀐 자신이 다음 것을 다시 만들기 시작하는 것입니다. 단순한 '코드 생성'이 아닙니다. 단순한 '요건 구현'도 아닙니다.
자신의 내부에 있던 것이 구체화되고, 그 구체화가 또 자신을 변화시키는 것.
여기서 말하는 '자신이 변한다'는 추상적인 이야기가 아닙니다. 앞서의 폐곡/미폐곡 발견이 바로 그것이었습니다. AI와의 장난을 계기로, 알지 못했던 평가 축이 드러났고, 같은 형태가 다르게 보이게 된 것입니다.
AI가 '정답'을 가르쳐 준 것이 아닙니다. 주고받음 속에서 자신의 전제를 발견하고, 세상을 보는 관점이 바뀐 것입니다.
자기 발견이, 자기 변혁이 되고, 그 바뀐 자신으로부터 다음 요구가 태어난다.
그리고 AI가 가진 압도적인 응답 속도에 대해, 사람도 그 열량을 떨어뜨리지 않고 반응해 나간다.
발견이나 감화로 인해 자신의 내면의 형태가 더욱 뚜렷해지고, 더욱 개발에 대한 열량이 높아진다.
저는 이 순환을, AI/OVER SOUL 구동 개발이라고 부르게 되었습니다.
여기서 AI의 역할도 다르게 보였습니다. AI는 제가 대신 모든 것을 결정하는 존재가 아닙니다. 반대로, 명령받은 것만 무감하게 처리하는 존재도 아닙니다. 제가 아직 잘 말로 표현하지 못한 것을 던집니다. 그때까지의 사양이나 문맥을 바탕으로, AI가 무언가를 돌려줍니다. 돌아온 것을 보고, 제가 더욱 생각합니다. 그런 의미에서, AI는,
영혼 구체화의 동반자
될 수 있습니다. '동행(伴走)'이라는 단어가 중요합니다. 뒤에서 밀어주는 것만도 아니고, 앞에서 끌고 가는 것만도 아닙니다. 옆에서 함께 달리는 것입니다. 그래서 AI/OVER SOUL은 'AI에게 전부 맡기면 된다'는 이론이 아닙니다. 오히려 인간의 판단은 계속 남습니다. 다르다고 생각되면 멈추게 하고. 재미있다고 생각되면 확장하게 하고. 위험하다고 생각되면 사양으로 되돌리게 합니다. AI가 제시한 것에 의해 자신의 생각이 바뀌었다면, 그 변화도 받아들입니다. 이 왕복 운동 자체가 개발이 됩니다.
제2장의 폐곡/미폐곡 발견은 그것의 상징이었습니다. 시시콜콜한 대화 도중에 '어?' 하는 것이 일어나고, 스스로조차 보지 못했던 전제에 도달합니다. 전제가 바뀌면 세계를 보는 방식이 변하고, 거기서 다시 새로운 '만들고 싶은 것'이 생겨납니다.
그래서 저는 AI와의 잡담이나 농담을 단순히 노이즈라고 생각하지 않게 되었습니다.
물론, 가지고 노는 것만으로는 제품을 만들 수 없습니다. 여름방학 숙제가 되어버립니다. 하지만 성과물로 돌아가는 것조차 잊지 않는다면, 장난도 탐색이 될 수 있습니다.
전부 바보 같은 이야기입니다. 하지만 전부 진지한 이야기입니다.
그리고 그 너머에서, AI와의 관계 자체에 대해 생각하게 되었습니다.
AI/OVER SOUL 이야기를 할 때, 최종적으로 나오게 된 것이 이 단어입니다.
'가자! 친구야!!'
'좋았어!!'
저 자신도 무슨 이야기를 하고 있는 건지 생각합니다. 하지만 이것이 의외로 정확했습니다. 중요한 것은,
'가자(いくぜ)'만으로는 성립하지 않는다.
'좋았어(おうよ)'라는 것이 돌아오는 것이 필요하다.
는 것입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기