AI 코딩 구독 서비스를 최대한 활용하려 했더니 에이전트를 관리해야 했다
요약
AI 코딩 도구(Codex 등)를 사용하며 단순 작업부터 복잡한 기능 구현까지 확장했으나, 여러 에이전트와 클라이언트 간의 세션 관리 및 컨텍스트 공유에 어려움을 겪었다. 결국 모든 에이전트가 하나의 시스템에서 리소스를 효율적으로 공유하고 작업을 순차적으로 처리할 수 있는 'Worktree Control' 같은 통합 컨트롤러를 직접 개발하게 되었다.
핵심 포인트
- AI 코딩 도구 사용 시, 단순 작업 위임부터 복잡한 기능 구현까지 확장됨.
- 여러 에이전트 간의 컨텍스트(Context) 공유 및 동기화가 핵심 과제였음.
- 각 에이전트의 작업을 하나의 리소스 풀에서 효율적으로 관리하는 통합 컨트롤러 필요성 대두.
- 세마포어와 같은 전통적인 OS 개념을 AI 에이전트 관리에 적용하려는 시도.
작은 Codex 플랜으로 시작했다. 지금은 여러 코딩 클라이언트와 자동화된 PR 검토 기능, 그리고 전체 시스템을 관리하기 위해 내가 직접 만든 컨트롤러가 있는 리눅스 개발 워커를 운영하고 있다. 언제부터 이게 프로젝트가 되었는지 아직도 잘 모르겠다.
지루한 코드에서 시작되다
처음에는 Codex에게 작고 고립된 작업들을 맡겼다. 이 함수를 작성해라. 저 클래스를 구현해라. 테스트 몇 개를 써라. 이걸 고쳐라. 그냥... 기본적인 틀(boilerplate)을 짜내는 것이 목표였다. 시간이 절약되었고, 무슨 일이 벌어지고 있는지 흐름을 놓치지 않으면서 결과를 확인할 수 있었다.
모델이 개선되면서, 나는 더 큰 작업들을 맡기기 시작했다. "이 기능을 구현해라"는 합리적인 요청이 되었다. 위임할 수 있는 작업은 더 많았지만, 세션 제한 때문에 내 구독 서비스 중 얼마나 많은 부분을 사용하지 못하고 있는지 의문이 들었다.
내가 잠든 동안에도 에이전트(agent)가 계속 작동할 수 있을까? 백로그(backlog)에서 다음 작업을 스스로 선택할 수 있을까? 다음 세션을 이어갈 충분한 컨텍스트를 어디에 남겨야 할까?
이는 마치 개발자 팀과 함께 일하는 것 같은 느낌을 주었다. 물론 실제로는 그렇지 않았다. 나는 또한 그 팀이 어떻게 작동해야 하는지 알아내고 있었다. 어느 순간부터인가, 나는 마이크로매니징(micromanaging)을 좋아하는 매니저처럼 행동하기 시작했다. 이건 정말 아니라고 맹세한다.
그리고 다른 구독 서비스를 추가하다
한 친구가 나에게 말했다. "야, Claude 한번 써봐."
나는 이미 Codex만으로도 해결해야 할 것들이 있었다. 당연히 또 다른 도구를 추가하게 되었다.
코딩 클라이언트 전반에 걸쳐 세션을 관리할 수 있는 곳을 제공하는 T3 Code를 발견했다. 이것이 도움이 되었지만, 여전히 공유되는 백로그가 필요했다. 그래서 모든 에이전트가 읽을 수 있도록 Git 저장소 안에 JSON 및 Markdown 파일을 유지하려고 시도했다. 아주 간단했다. 하지만 브랜치(branches)와 워크트리(worktrees) 때문에 모두가 자신만의 백로그 버전을 갖게 되었다. 이들을 동기화하는 것이 까다로워졌다. 한 대화에서 결정된 내용이 다른 대화에서도 사용 가능해야 했다. 나는 어떤 아이디어, 백로그 항목, 혹은 프로젝트 기억 같은 것을 한 에이전트와 논의하고, 또 다른 에이전트가 프롬프트에 절반을 복사 붙여넣기 하지 않고도 그것을 이어받게 하고 싶었다.
모델을 변경하는 것은 프로젝트 컨텍스트를 함께 유지하는 것과 비교하면 쉬웠다.
다섯 개의 스레드가 하나의 머신을 공유하다
다음은 하드웨어 문제였다.
한 번에 다섯 개의 스레드를 돌려야 했다. 개발 서버 4개, 종단 간(end-to-end) 테스트 실행 2개. 모두 같은 워커에서 돌아가야 했다. 각 에이전트는 자체 프로세스를 시작할 이유가 있었지만, 머신은 그 모든 것을 구동해야만 했다.
내 Linux 워커는 CPU 6개가 사용 가능하고 RAM은 약 18 GiB였다. 돈을 들여 더 큰 머신을 사기 전에 이 머신을 더 잘 활용하고 싶었다. 더 큰 머신을 얻을 수 있을까? 응! 그걸 비용을 지불하고 원할까? 아니...
메모리 제한(Memory limits)은 리소스 사용량을 제어하는 데 도움이 된다. 그것들은 어떤 개발 서버가 실행되어야 하는지, 다른 테스트가 기다려야 하는지, 또는 내가 현재 에이전트가 전환하려는 브랜치를 확인하고 있는지 여부를 결정하지는 않는다.
내가 공부하던 시절, 아주 오래전에 누군가 나에게 세마포어(semaphore)에 대해 가르쳐 준 적이 있다. 분명히 코딩 에이전트가 등장하기 전부터 제한된 리소스를 공유하는 것은 이미 존재했던 일이었다. 누가 알았겠는가 :-) 그 아이디어는 여러 에이전트가 동시에 같은 머신을 사용하려고 할 때 나에게 다시 떠올랐다. 그래서 나는 Worktree Control을 만들었다.
하나의 포트, 예약, 그리고 큐
시작점은 간단했다. 나는 내 머신에서 한 번에 몇 개의 관리되는 개발 서버가 실행될 수 있는지 제한을 설정했다. 각 프로젝트는 안정적인 포트에 하나의 서버를 할당받고, 에이전트들은 그 서버를 워크트리(worktree) 간에 전환할 수 있다. 이들은 사용하기 전에 프로젝트를 선점하고, 작업이 끝나면 선점을 해제한다. 몇 개의 서버가 머신에서 실행될지 내가 결정한다!
나 자신은 모든 프로젝트에서 가장 중요한 에이전트 ;-), 브라우저에서 무언가를 확인하는 동안 대시보드를 통해 프로젝트를 잠글 수 있다. 다음 에이전트는 그 예약을 존중해야 한다. 선점을 해제한다고 해서 서버가 계속 실행되는 것이므로, 자유로운 예약(free reservation)이 반드시 자유로운 서버 슬롯을 의미하지는 않는다.
[
대시보드에서 프로젝트(Projects), 워크트리(worktrees), 예약(reservations)을 확인할 수 있습니다. 데모 데이터입니다.
빌드와 테스트는 별도의 큐를 통해 진행되며, 동시 실행에 제한이 있고 워크트리당 최대 하나의 활성 체크만 가능합니다. 테스트를 제출한다고 해서 개발 서버가 전환되는 것은 아닙니다. 해당 서버가 필요한 브라우저 테스트 역시 클레임(claim)이 필요합니다. 다른 에이전트가 이 클레임을 보유하고 있다면, 그 테스트는 기다려야 합니다. 또한, 중지된 서버를 시작하는 것조차 서버 제한 내의 공간을 필요로 합니다.
이러한 구분이 제 프로젝트에서는 중요했습니다. 예를 들어, 한 프로젝트에서 공유되는 테스트 픽스처(test fixtures)는 큐에 넣은 작업 내부에서 준비되어야 했습니다. 큐에 들어가기 전에 데이터베이스를 초기화하면 이미 실행 중인 테스트와 간섭을 일으킬 수 있었습니다.
컨트롤러(controller)에서는 리소스 사용량과 워크트리 디스크 사용량도 보여줍니다. 이 .next 디렉토리들이 쌓입니다. 확인 절차를 거치면 중지되고 잠금 해제된 워크트리의 Next.js 캐시를 지울 수 있습니다.
이러한 규칙들은 에이전트가 컨트롤러를 사용할 때 작동합니다. 컨트롤러는 관련 없는 터미널이 다른 서버를 실행하는 것을 막을 수는 없기 때문에, 작업 흐름(workflow) 역시 프로젝트의 에이전트 명령어에 포함되어야 합니다.
실제로 코드를 검사했나요?
'테스트 통과'라는 말은 안심하게 들립니다. 하지만 무엇이 테스트되었는지 여전히 알고 싶습니다.
어떤 워크트리인가요? 어떤 명령어를 사용했나요? 테스트가 큐에 들어간 후에 코드가 변경되지는 않았나요? 그 결과는 지금 제가 보고 있는 것과 여전히 관련성이 있나요?
Worktree Control은 실행 전후의 Git 관찰 기록을 보관하고, 명령어 결과를 그 출처에 대한 증거와 분리하여 유지합니다. 성공적인 명령어가 현재 리비전(revision)이 검증되었다는 것을 자동으로 의미하지는 않습니다. 결과에는 커밋 정보, 워크트리가 오염되었는지 여부, 그리고 실행 전후 변경된 경로에 대한 Git 상태 항목의 다이제스트(digest)가 기록되어 있어, 이 두 관찰 사이에 HEAD 변화가 생기면 플래그가 지정됩니다.
물론 한계도 있습니다. 로컬 체크는 커밋되지 않은 변경 사항을 포함하여 워크트리의 파일을 사용합니다. 이는 불변 스냅샷(immutable snapshots)이 아니며, Git 관찰 기록은 모든 환경 종속성을 포착하지 못합니다. 하지만 채팅창의 클레임보다 검사할 수 있는 더 유용한 무언가를 제공해 줍니다.
검증 실행을 위한 테스트 큐 및 출처 증거. 데모 데이터.
다음 세션이 시작할 곳이 필요하다
서버와 테스트 큐를 제어하게 되면서도, 저는 여전히 작업 자체를 보관할 장소가 필요했습니다.
저는 Knowledge to Worktree Control을 추가했습니다. 이곳은 백로그(backlog), 토론 내용, 그리고 프로젝트 메모리를 담고 있습니다. 태스크는 해당 태스크로 이어진 토론과 연결될 수 있으며, 결정 사항들은 출처와 개정 기록을 유지할 수 있습니다. 메모리 항목을 저장하고 승인하는 것은 별개의 작업입니다.
저는 대시보드에서 이러한 기록들을 읽고 편집할 수 있습니다. 에이전트들은 MCP 또는 CLI를 통해 여기에 접근할 수 있습니다. 이는 코딩 클라이언트를 변경하더라도 여러 세션들이 공통으로 참고할 장소를 제공합니다.
인수인계를 위해, 태스크의 다음 세션 컨텍스트(next-session context)는 연결된 메모리와 출처 개정본들을 모읍니다. 다음 에이전트가 여전히 이를 읽고 이해해야 하지만, 정보가 머무를 곳은 마련되었습니다.
오늘 제가 운영하는 것들
설정은 Codex, Claude Code, OpenCode를 사용하는 하나의 Linux 개발 워커와 코딩 세션 원격 접속을 위한 T3 Code로 구성되어 있습니다. n8n이 PR 검토 자동화를 처리합니다. Worktree Control은 개발 서버를 관리하고, 검사 큐를 운영하며, 공유 프로젝트 컨텍스트를 보관합니다.
Worktree Control은 현재 해당 머신에 다섯 개의 등록된 런타임 프로젝트를 가지고 있습니다. 또한 저는 이 시스템 자체의 작업을 정리하는 데도 이를 사용합니다.
컨트롤러는 SQLite와 브라우저 대시보드를 가진 하나의 Node.js 프로세스로 실행됩니다. Next.js UI는 정적 파일로 내보내지기 때문에 별도의 상주 Next.js 서버가 필요하지 않습니다.
아직 1.0 버전 이전이며, 설정은 계속 변경되고 있습니다. 오늘 제가 사용하는 방식은 이 Linux 워커에서 컨트롤러를 실행하는 것입니다. 검증을 분리된 연결의 워커로 전송하는 것은 아직 개발 중입니다.
얼마나 위임할지 여전히 알아가는 중이다
저는 구독 서비스들을 최대한 활용하려고 노력하는 것부터 시작했습니다. 그 과정에서 채팅 세션이 끝난 후에도 남아있는 큐(queue), 예약(reservation), 기록(record) 같은 예상치 못한 많은 작업들이 생겼습니다.
여전히 제가 무엇이 중요한지 선택하고, 변경 사항을 검토하며, 결과가 충분히 좋은지 결정해야 합니다. 모든 에이전트를 바쁘게 유지하는 것이 진척으로 착각하기 쉽습니다. 저는 어떤 작업에 돌아와서 무엇이 바뀌었는지, 무엇이 확인되었는지, 그리고 여전히 제 주의가 필요한 부분이 무엇인지 보고 싶습니다.
Worktree Control은 GitHub에서 오픈 소스로 공개되었습니다. 만약 한 대의 컴퓨터에서 여러 코딩 에이전트를 실행하고 있다면, 저는 여러분들이 같은 문제들을 어떻게 처리하는지 궁금합니다. 컨텍스트(context)는 어디에 남겨지고, 누가 개발 서버를 사용하게 되나요?
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기