/// LAB · 작업 환경

이렇게 만들어 두었다

AI에게 일을 맡기려면 손과 눈을 줘야 한다. 파일을 직접 고칠 손, 그리고 고친 결과를 스스로 확인할 눈. 거기에 하나 더 — 세션이 바뀌어도 남는 기억. 환경 대부분이 그 셋을 만드는 데 쓰였다.

웹 쪽은 규모가 작아 감이 잘 안 오는데, 같은 방식으로 지은 게임 쪽은 소스가 141개 파일에 6만여 줄, 시험이 120개 파일에 1,200개가 넘는다. 아래 숫자는 대부분 그쪽에서 잰 것이다.

2026-08-22 · 계속 고쳐 나가는 문서
PART 1 — 무엇을 어디에 두는가

무엇으로 짓고 있나

작업 기계
일반 데스크톱 윈도우 한 대. 특별한 것 없다. 터미널에서 AI를 띄워 쓴다.
서버
집에 둔 가정용 서버. 가상화 위에 NAS를 올리고, 그 안에서 컨테이너로 웹을 돌린다.
공개
터널로 도메인에 연결한다. 공유기 포트를 하나도 열지 않는다.
관리
사설 VPN으로만 들어간다. 관리 화면은 인터넷에 올리지 않는다.

집 서버를 공개하는 방법으로 오래 포트포워딩을 썼는데, 계속 풀렸다. 임대 시간이 끝나고, 공유기를 재부팅하면 초기화되고, 주소가 바뀌면 규칙이 무효가 됐다. 터널로 바꾸고 나서 그 문제가 사라졌다. 여는 포트가 없으니 풀릴 것도 없고, 집 주소도 드러나지 않는다.

AI가 손댈 수 있는 자리에 둔다

프로젝트를 서버의 공유 폴더에 두고, 작업 기계에서 경로로 바로 붙인다. 그래서 AI가 파일을 직접 읽고 쓴다. "이 파일 내용 붙여 줄게" 같은 단계가 없다.

별것 아닌 차이 같지만 크다. 내용을 옮겨 붙이는 방식으로는 서른 개 파일을 한 번에 훑어보는 일을 시킬 수 없다. 자료가 몇 장인지, 어느 폴더가 실제로 쓰이는지 같은 질문은 폴더를 직접 걸어야 답이 나온다.

편집이 곧 배포

웹 서버가 그 폴더를 그대로 들여다보게 해 두었다. 그래서 화면 쪽 파일은 저장하면 그 순간 반영된다. 빌드도 업로드도 없다. 뒤쪽(서버 코드)만 컨테이너를 다시 올린다.

확인까지의 거리가 짧을수록 AI에게 맡길 수 있는 단위가 커진다. 고치고 새로고침하면 끝이면, 열 군데를 한 번에 고쳐도 겁나지 않는다.

PART 2 — 세션이 바뀌어도 남게

다음 세션에게 넘기는 문서

AI와 일할 때 가장 자주 잃는 것은 맥락이다. 대화는 끝나면 사라진다. 어제 왜 그렇게 정했는지, 무엇이 아직 안 끝났는지가 함께 사라진다.

그래서 저장소 뿌리에 문서 두 개를 두었다. 하나는 규칙이고 하나는 지금 상태다.

인계 문서에는 뜻밖의 절이 하나 있다 — "다음 세션에게 건넬 첫 문장". 다음 대화를 어떻게 열어야 하는지를 문서가 스스로 써 둔다. 그래서 새로 시작할 때 내가 상황을 설명하지 않는다. 그 문장을 붙여 넣으면 된다.

컴퓨터를 바꿔도, 몇 주가 지나도 같은 자리에서 이어진다. 기억을 사람이 들고 다니지 않게 만드는 것이 요점이다.

결정을 코드에 남긴다

주석에 태그를 붙여 그 줄이 왜 그렇게 되었는지를 기록한다. 가장 많이 쓰는 태그가 [사용자]인데, 게임 소스에만 1,636번 나온다.

단순한 표시가 아니라 내가 한 말을 그대로 박아 둔다. 이런 식이다.

경계나 정찰을 맡기고 나면 자동으로 다음 유닛으로 안넘어가고 스페이스 눌러야 넘어감 그래서 K만 누르고 있으면 경계했다가 풀었다를 반복함 이민족의 토목처럼 처리 되어야 일관성있을거 같은데 — 소스 주석에 그대로 남아 있는 요청
모든 건 조화롭게 하는 걸 최대 목표로. — 이 한 줄이 "조화를 숫자로 재는" 도구 하나가 되었다

다듬지 않고 그대로 두는 이유가 있다. 정리된 요약은 왜 그게 문제였는지를 잃는다. "일관성있을거 같은데"라는 말투에는 판단의 근거가 들어 있는데, 요약하면 그게 빠진다.

그리고 내가 뭔가 이상하다고 의심했을 때, 확인해 보고 맞았으면 주석이 "맞다."로 시작한다. 누가 맞았는지를 적어 두면, 다음에 같은 종류의 의심이 들 때 그걸 무게 있게 다루게 된다.

확신의 등급을 갈라 적는다

규칙을 옮기는 작업에서는 확실히 아는 것과 짐작한 것과 아직 몰라서 지어낸 것이 섞인다. 섞인 채로 두면 나중에 무엇을 다시 봐야 하는지 알 수 없다. 그래서 등급을 나눠 붙였다.

태그횟수
[확정]확실히 아는 것553
[재창조]없던 것을 새로 설계한 것41
[임시]아직 몰라서 지어낸 것 — 나중에 교체할 것36
[추정]정황으로만 알아낸 것19

그리고 게임에게 물어볼 수 있게 해 두었다. 함수 하나를 부르면 아직 지어낸 규칙 목록이 나온다. 그 함수의 설명에는 이렇게 적혀 있다 — "이 목록은 진행되면 반드시 줄여야 한다. 낡은 채로 두면 이미 확정된 것을 아직 모르는 것으로 오해하게 된다(실제로 한 번 그랬다)."

버그는 두 곳에 나눠 적는다

결함을 고칠 때 기록을 둘로 쪼갠다.

이게 규칙이라는 증거가 통계에 있다. [회귀 방지] 태그는 소스에 0번, 시험에 21번 나온다. 우연이 아니라 분업이다 — "고쳤다"는 소스에, "다시 안 깨진다"는 시험에.

PART 3 — 확인하는 장치

AI에게 눈을 달아 준다

가장 공들인 부분이다. AI는 "했습니다"라고 말한다. 그 말을 확인할 수단이 없으면 나는 믿거나 직접 다 뒤지거나 둘 중 하나다. 그래서 확인 통로를 세 개 뒀다.

화면을 본다

게임은 창을 열지 않고 화면만 저장하는 방식으로 찍는다. 게임을 실제로 구동시켜서 찍기 때문에, 자료만 따로 불러 보는 미리보기와 달리 겹쳐 그리는 순서까지 그대로 탄다. 화면 안에서는 단축키 하나로 찍힌다.

서비스를 직접 찔러 본다

공개 주소에 요청을 보내 응답 머리를 읽는다. 실제로 이걸로 잡은 게 있다 — 내려받기 파일을 새 빌드로 갈아 끼웠는데, 캐시가 옛 파일을 스물두 시간째 내주고 있었다. 페이지만 봐서는 절대 몰랐을 문제다.

코드는 시험이 본다

지금 게임 쪽에 자동 시험이 1,200개 넘게 있다. 상당수는 기능을 재는 것이 아니라 내가 정한 결정이 그대로인지를 묻는다. 이건 따로 적었다 — NOTE 01.

게임에게 상태를 물어본다

화면을 찍는 것만으로는 부족하다. 지금 안이 어떤지를 물어볼 창구를 여러 개 뚫어 두었다.

이게 있으면 AI에게 "지금 상태가 어떤지 봐 줘"를 시킬 수 있다. 없으면 나에게 화면을 요구하거나, 추측한다.

도구는 기본이 읽기 전용

직접 만든 도구가 아흔 개를 넘는데, 그중 상당수는 만드는 도구가 아니라 재고 검사하는 도구다. 지도에서 눈에 거슬리는 자리를 점수로 매기는 것, 맞닿은 타일의 색이 어울리는지 픽셀로 재는 것, 그림이 정해진 색표를 지키는지 보는 것.

공통 규약이 하나 있다. 확인이 기본이고 고치기가 선택이다. 그냥 실행하면 보고만 하고 아무것도 안 고친다. 고치라고 따로 말해야 고친다.

AI에게 도구를 돌리게 시킬 때 이 규약이 값을 한다. 잘못 시켜도 최악이 "쓸데없는 보고서"이지 "망가진 자료"가 아니다.

AI 특유의 실수를 겨냥한 시험

일반적인 시험과 별도로, AI와 일할 때 유독 자주 나는 종류를 노린 시험이 몇 개 있다. 전부 실제로 당하고 나서 만들었다.

쓰는 쪽만 넣고 만드는 쪽을 빼먹는 실수

기능 하나를 두 화면에 넣으면서, 한쪽에는 변수를 만들고 다른 쪽에는 쓰는 줄만 넣은 일이 있었다. 그 화면이 새 게임의 첫 화면이라 새로 시작하면 그 자리에서 죽었다.

시험 1,189개가 못 잡았다. 이유는 분명했다 — 화면을 실제로 띄우는 시험이 없었다. 실행될 때만 죽는 결함은 소스를 읽는 시험으로 안 걸린다.

그래서 두 겹으로 막았다. 파이썬 심볼 테이블로 정의 안 된 이름을 전수 조사하고, 그 화면을 창 없이 실제로 돌려 본다. 만들고 나서 같은 갈래를 하나 더 찾았다 — 특정 키를 누르면 죽는 자리가 남아 있었다.

마크다운이 게임 화면에 찍힌 사고

화면을 한 장씩 찍어 눈으로 점검하다가 웃지 못할 것을 찾았다. 게임 안 조작 안내에 별표가 그대로 찍혀 있었다**도시 둘레**를 돈다. 강조 문법이 그림으로 렌더된 것이다.

같은 점검에서 안내문이 상자를 뚫고 나간 것, 표가 오른쪽을 비운 것, 같은 이름의 세력이 둘 있는 것도 나왔다. 다 코드만 읽어서는 안 보이던 것들이라, 찾은 조건을 그대로 시험으로 굳혔다.

검사 도구 자체가 틀리는 경우

쓰지 않는 그림을 골라내는 검사가 세 장을 잘못 셌다. 코드가 이름을 통째로 적지 않고 조립해 부르는 자리를 못 봤기 때문이다. 정규식을 버리고 구문 트리로 다시 짰고, 원칙을 하나 정했다 — 애매하면 남기는 쪽.

시험을 돕는 코드에도 같은 일이 있었다. 검사 범위를 고정 길이로 자르고 있었는데, 함수가 자라면 검사할 줄이 창 밖으로 밀려나 거짓으로 깨졌다. 여섯 번 그랬다. 그 여섯 번을 주석에 이름까지 적어 두었다.

PART 4 — 실수를 구조로 막는다

경계는 규칙이 아니라 구조로

"조심하자"로 두면 언젠가 무너진다. 구조로 막으면 조심할 일이 줄어든다. AI와 일할 때는 특히 그렇다 — 조심해 달라고 부탁할 상대가 매번 새로 오기 때문이다.

되돌릴 길을 먼저 만든다

마지막 것이 제일 중요하다. 로그인에 시도 제한을 걸 때, 잠긴 뒤에 어떻게 푸는지를 먼저 정하고 나서 만들었다 — 시간이 지나면 저절로 풀리게, 계정이 아니라 주소별로 잠기게, 집 안에서는 제한을 안 받게, 그리고 다시 띄우면 초기화되게. 네 갈래로 열어 두면 스스로 갇힐 일이 없다.

한 곳만 고치면 되게

판 번호는 파일 한 줄에만 있다. 그 한 줄이 타이틀 화면, 실행 파일 속성, 설치 파일 이름, 빌드 스크립트까지 끌고 간다. 내려받기 목록도 손으로 안 쓴다 — 폴더를 훑어 크기와 검증값을 자동으로 채운다.

이렇게 두는 이유는 게으름이 아니다. 여러 곳을 맞춰 고쳐야 하는 일은 반드시 한 곳이 빠진다. 사람이 해도 그렇고, AI가 해도 그렇다.

PART 5 — 숫자로 정한다

결정 하나에 숫자 하나

게임 소스에 "실측"이라는 낱말이 452번 나온다. 대개는 이런 모양이다 — 무엇을 어느 세이브에서 몇 턴 돌려 재었더니 얼마였고, 그래서 이렇게 정했다. 세이브에 이름을 붙여 두어서 같은 조건으로 다시 잴 수 있다.

마지막 것이 특히 값졌다. "안 쓰이는 것 같다"와 "60프레임 동안 0회"는 지울 때의 담력이 다르다.

느린 것도 숫자로

한 턴이 8.4초까지 늘어난 적이 있다. 프로파일을 떠 보니 원인이 두 자리였고 — 도시를 매번 처음부터 훑는 함수가 31만 8천 번 불렸다 — 색인을 붙여 2.95초가 됐다.

여기서 한 걸음 더 갔다. 그 병목이 돌아오지 못하게 시험을 붙였다. 해당 함수의 소스를 읽어서 "전체를 훑는 구문이 있으면 실패"하게 만든 것이다. 성능도 계약이 될 수 있다.

실패도 적는다

[실패 기록]이라는 태그가 따로 있다. 시도했고 안 됐던 것을 남기는 자리다.

강줄기가 직각으로 꺾여 보이는 문제를 굽이가 모자란 탓으로 보고 값을 여덟 조합 바꿔 봤는데 전부 나빠졌다. 그러고 나서야 전제가 틀렸음을 알았다 — 해상도가 달라서 애초에 견줄 수 없는 숫자였다.

이걸 적어 두는 이유는 단순하다. 안 적으면 몇 주 뒤에 똑같이 시도한다. AI는 특히 그렇다. 문서에 "이 방향은 막혔다"가 없으면, 가장 그럴듯한 그 방향을 다시 제안한다.

다 만들고 나서 걷어낸 것

실시간 전투를 넣어 본 적이 있다. 설계 문서를 쓰고, 세 단계로 나눠 구현하고, 시험 48개를 통과시켰다. 그리고 직접 해 보고 철회했다.

데이터 처리가 많아서 그런지 느리고 조작이 잘 안되고 하는 문제가 있어 실시간이 우리 시스템에 맞는지 다시 한번 고민이 필요할것 같네 — 설계 문서의 철회 절에 남은 원문

문서에 결론을 이렇게 적었다 — "연속 시간의 환상을 씌우는 비용이 재미보다 크다. 환상을 걷고 정직한 턴으로 돌아간다." 그리고 무엇을 남기고 무엇을 걷어낼지 표로 정리한 뒤 "되살아나는 것" 절까지 썼다.

되돌리는 일이 이만큼 깔끔했던 건 처음부터 설정이 비어 있으면 원래 동작으로 돌아가게 만들어 뒀기 때문이다. 새 기능을 얹을 때 "끄면 원래대로"를 지키면, 걷어낼 때 한 줄도 안 고쳐도 되는 경우가 생긴다.

착수 전에 영향 분석

기능을 시작하기 전에 하는 절차가 하나 있다. 그 값을 읽는 자리를 전부 찾아 표로 만들고, 각 자리가 새 상태에서 어떻게 보일지 판정한다.

실제 표에는 이런 줄이 있다 — 어떤 화면은 "변화 없음 ✓", 다른 화면은 "'지금 목표'로 잘못 보인다 ⚠️ 표시를 갈라야 한다". 미리 해 두면 고칠 곳을 빠뜨리지 않는다.

그리고 이 분석이 "한 줄도 새로 쓰지 않는다"는 결론으로 끝난 적도 있다. 기존 구조가 이미 그 성질을 갖고 있었기 때문이다. 분석의 가장 좋은 결과는 안 만들어도 된다는 답이다.

PART 6 — 일하는 순서

실제로 이런 순서로 일한다

  1. 무엇을 왜 바꾸는지 한두 줄로 말한다. 어떻게 고칠지는 대개 말하지 않는다. 방법을 지정하면 내가 아는 방법 이상은 안 나온다.
  2. AI가 고친다. 여러 파일에 걸쳐도 한 번에 맡긴다.
  3. 눈으로 본다. 화면을 찍거나, 주소를 찔러 보거나, 시험을 돌린다. 이 단계를 건너뛰면 나머지가 다 무의미해진다.
  4. 지켜야 할 결정이면 시험으로 못박는다. 말로 남긴 결정은 다음 세션에서 사라진다.
  5. 왜 그렇게 됐는지 주석에 남긴다. 무엇을 했는지는 코드가 말해 준다. 왜 했는지는 아무도 말해 주지 않는다.

다섯 번째가 시간이 지나면서 제일 값어치가 커졌다. 몇 주 전에 왜 그렇게 뒀는지 기억이 안 날 때, 주석에 이유가 적혀 있으면 그 자리에서 판단이 이어진다. 없으면 처음부터 다시 생각해야 한다.

사소하지만 실제로 겪은 것들

← 글 목록 NOTE 01 · AI는 "했습니다"라고 말한다 →