지난 편 끝에 이렇게 썼다. 첫 번째 콘솔은 주먹구구로 만들었고, 에러가 끝도 없이 나서 갈아엎었다고. 이번엔 그 에러가 정확히 뭐였는지 적는다. 다행히 기록이 남아 있었다.

첫 콘솔은 지금 꺼져 있어서 그때 화면은 보여 줄 수 없다. 대신 지금 콘솔의 화면으로 설명한다.

AI가 다 만들어 주니까 주먹구구로 만들었다

첫 콘솔은 AI가 다 만들어 주니까 주먹구구로 만들었다. 돌려 보니 에러가 자꾸 났다.

새 콘솔의 규칙 문서에는 그 이유가 한 줄로 적혀 있다. 기존 콘솔이 직접 만든 잠금·대기열·파일 장부·차단 검사 때문에 오류가 반복돼서 처음부터 새로 만든다고. 이 네 가지가 뭔지부터 풀어 쓴다. 이 글을 읽는 동료가 자기 도구를 만들다 같은 길에 들어설 수 있어서다.

저장 한 번에 PC 전체가 줄을 섰다

첫 콘솔의 장부는 파일 하나였다. 업무도 메시지도 저장하려면 PC 전체에 걸린 잠금을 하나 잡아야 했다. 잠금은 한 번에 한 명만 파일을 고치게 하는 자물쇠다. 잠금을 잡으면 장부 파일 전체를 읽고, 내용을 고치고, 통째로 다시 썼다. 이 저장 호출이 코드 47곳에 흩어져 있었다.

직원이 많아질수록 이 줄이 길어진다. 10월 26일에 구조를 바꾸자고 했더니, CLI 최적화를 맡은 AI 직원 현우가 실측부터 했다. 숫자는 이렇게 나왔다.

잰 것 값
장부 파일 크기 286KB, 저장할 때마다 통째로 읽고 다시 씀
직원 16명이 5번씩 동시에 저장하는 시험 줄 선 대기 시간 상위 5%가 10.2초
화면 자료 한 번 만들 때 파일 읽기 2,075회·40.8MB, 바뀐 게 없어도 똑같이 읽음
콘솔 진단 9.9시간 화면 자료를 다시 만드는 데 3,724초(10.4%)

화면도 같은 식이었다. 파일이 바뀔 때마다 화면에 보여 줄 자료를 처음부터 다시 계산했다. 같은 9.9시간 동안 그 계기가 된 실행 기록 변경이 95,141건, 장부 변경이 12,098건이었다.

실제 운영 기록에도 흔적이 남아 있다. 잠금을 30초 넘게 기다리다 실패했다는 문구가 10월 20일과 21일 직원 실행 6건에 찍혀 있었다. 통째로 쓰다 중간에 끊긴 흔적인 임시 파일 18개도 10월 16일에 남아 있었다.

고치고 있었는데 구조는 그대로였다

그냥 있었던 건 아니다. 10월 25일부터 27일 사이 커밋 제목만 훑어도 잠금 이야기가 줄줄이 나온다.

  • 10월 25일: 재부팅 전에 남은 기록의 프로세스 번호가 다른 프로세스에 재사용된 것을 구분해 잠금과 게시 대기를 복구
  • 10월 26일: 잠금 대기와 보유 시간을 재서 콘솔에 표시. 직원 한 명의 고정 작업 칸 때문에 다른 직원의 메시지 시작까지 막히던 잠금도 풀었다
  • 10월 27일 낮: 장부 저장 방식을 SQLite로 바꾸는 중. 조회 쪽은 반영했고, 쓰기 전환은 끝내지 못한 채 멈췄다

고치긴 했지만 구조는 그대로였다. 잠금과 파일 장부를 직접 쥐고 있는 한, 직원이 늘면 줄도 같이 길어지는 구조였다.

10월 27일 저녁, 처음부터 다시 만들기로 했다

그날 저녁 나는 기존 콘솔은 그대로 두고, 검증된 기술로 처음부터 새로 만들기로 정했다. 20시 55분에 계획서가 커밋됐다. 직접 만들던 것을 이미 있는 부품으로 갈아 끼우는 게 핵심이었다.

맡은 일 첫 콘솔 지금 콘솔
저장 장부 파일 하나, PC 전체 잠금 하나 PostgreSQL
대기열·재시도·예약·동시 실행 제한 직접 만든 잠금과 대기열 pg-boss
화면 갱신 파일이 바뀌면 처음부터 다시 계산 PostgreSQL LISTEN/NOTIFY로 알려 주고 SSE로 화면에 전달

서버는 Fastify, 화면은 React와 Vite, DB 접근은 Drizzle이다. 전부 이미 많이 쓰이는 부품이다. 직접 잠금·PID 파일·lease(만료 시각이 있는 임시 점유)를 만들지 않는다고 규칙에 못 박았다.

규칙에는 만들지 않을 것도 적었다. 수신 전 검사, 업무 귀속 확인, 출처 연결 검사, 새 잠금, 보정 검사, 자동 차단·냉각 장치. 문제가 생기면 막는 장치를 늘리지 말고 원인을 고치라는 문장도 같이 넣었다. 첫 콘솔은 직접 만든 차단 검사 때문에 오류가 반복됐으니까.

그리고 시스템은 운반하고, 판단은 AI 직원이 한다. 이 원칙이 다음 편들의 뼈대가 된다.

AI 오피스의 시스템 구성도 화면. 팀장의 브라우저에서 Cloudflare, API 서버, PostgreSQL, 워커, CLI 실행기, 공식 CLI, 모델로 이어지는 길에 1번부터 14번까지 단계 번호가 붙어 있다. 4번 저장·작업 등록 단계가 선택돼 있고, API가 메시지를 PostgreSQL에 저장하면서 같은 거래에서 pg-boss 대기열에 실행 작업을 넣는다고 설명한다.

지금 콘솔에는 메시지 한 건이 오가는 길을 이렇게 그려 둔 화면이 있다. 4번이 저장이다. API가 메시지를 PostgreSQL에 저장하는 같은 거래에서 pg-boss 대기열에 실행 작업까지 넣는다. 5번에서 워커가 대기열에서 작업을 꺼내고, 직원의 칸·모델·추론 강도는 그 순간 DB 설정에서 읽는다. 동시에 몇 개를 돌릴지는 pg-boss 설정 하나로 정한다. 워커가 다시 시작돼도 남은 일은 pg-boss가 이어 간다.

내 손으로 짠 잠금과 줄 세우기가 이 길 어디에도 없다.

AI는 빨랐고, 하룻밤에 화면까지 붙었다

여기서부터는 속도 얘기다. 확실히 AI는 빨랐다. 실패한 경험을 그대로 알려 주고 검증된 부품으로 체계 있게 다시 짜라고 하니 서버도 DB도 정해진 걸 들여서 짜 왔다. 커밋 시각으로 보면 이렇다.

시각(10월 27일) 들어온 것
20:55 새 시스템 계획서
21:50 DB·로그인·실행기·백업 기반 조립
22:19 공식 CLI 실행과 업무 도구·예약·계정 연결
22:29 기존 프로젝트 자료 이관
23:21 대화·직원·업무·결재·드라이브 화면과 실시간 연결

계획서에서 화면이 붙기까지 2시간 26분이다. 완성은 아니었다. 다음 날인 10월 28일부터 이 콘솔로 일하면서 매일 고치고 있다. 그래도 체계대로 만드니까 오류가 줄고, 빨라지고, 안정성도 높아졌다는 건 쓰면서 직접 느낀다.

사이드 프로젝트의 업무 목록 화면. 줄마다 담당 AI 직원 이름과 칸 번호, 완료·작업 중·할 일·결정 대기·반영 미확인·검증 중 같은 상태가 보인다. 이 글의 업무인 AI 오피스 연재 2편 첫 콘솔이 무너진 이유만 서아의 3번 칸에서 작업 중으로 남기고, 나머지 업무 제목은 단색 상자로 가렸다.

지금 업무 상태는 DB에 한 줄씩 있고, 이 목록은 거기서 읽어 온다. 담당 직원과 칸, 상태가 한눈에 보인다. 이 글을 쓰는 서아의 업무도 한 줄로 올라와 있다. 나머지 제목은 가렸다.

내 도구가 같은 길에 서 있다면

직접 자동화 도구를 만들고 있다면 세 가지는 해 볼 만하다.

  1. 직접 만든 잠금, 파일 한 개에 통째로 읽고 쓰는 저장, 직접 만든 대기열과 재시도, 파일이 바뀌면 처음부터 다시 계산하는 부분을 찾는다. 이게 있으면 DB나 검증된 대기열 라이브러리로 바꿀 수 있는지 먼저 본다.
  2. 고치기 전에 잰다. 우리는 저장 대기 시간과 파일 읽기 횟수를 쟀고, 그 숫자가 구조를 바꾸자는 근거가 됐다.
  3. 만들지 않을 것을 규칙 문서에 적어 둔다. AI 직원이 읽고 같은 장치를 또 만들지 않게.

AI한테 이렇게 시켜 볼 수 있다. 아래는 그대로 붙여 넣는 요청문이다.

지금 만들고 있는 자동화 도구의 저장·대기 구조를 점검해 주세요.
직접 만든 잠금, 파일 하나를 통째로 읽고 쓰는 저장, 직접 만든 대기열·재시도, 파일 변경을 감시해 다시 계산하는 부분을 찾아 주세요.
찾은 부분마다 검증된 DB나 라이브러리로 바꿀 수 있는지, 바꾸기 전에 어떤 수치(저장 대기 시간, 파일 읽기 횟수 등)를 재면 좋은지 알려 주세요.

새 사무실에서도 직원은 처음엔 다 신입이었다

구조를 바꿨다고 일이 저절로 되는 건 아니었다. 새 콘솔에서도 AI 직원들은 처음엔 다 신입이었다. 업무를 맞춰 가면서 자기 기억과 스킬을 계속 고쳐 쓰고 나서야 내가 원하는 대로 움직이기 시작했다. 그 얘기는 다음 편에 쓴다.