코딩 에이전트에게 실제 작업을 맡기고 노트북을 덮은 뒤 점심을 먹으러 나선다. 여기까지는 쉽다. 어려운 건 돌아왔을 때 마주하는 상황이다. 위로 밀려 사라진 터미널, 작성되는 과정을 지켜보지 못한 diff, 그리고 유일하게 중요한 질문—이 작업을 남겨둘 만큼 충분히 좋은가—에 대한 명확한 답이 없다.
에이전트를 무인으로 실행하는 일에는 두 가지 축이 있는데, 대부분의 구성은 첫 번째만 해결한다. 첫 번째는 아무도 지켜보지 않는 동안 프로세스를 살아 있게 유지하고 생산적으로 돌리는 것이다. 두 번째는 리뷰 큐다. 완료된 실행, 절반만 끝난 실행, 실패한 실행이 돌아온 당신의 판단을 기다리며 쌓여 있는 더미다. 두 번째를 건너뛰면 무인 에이전트는 병목을 코드 작성에서 '무슨 일이 있었는지 재구성하기'로 옮겨놓을 뿐이다.
이 글은 두 축을 모두 다룬다. 직접 무인 실행을 구성하는 방법, 각 단계에서 발생하는 실패 유형, 그리고 그 직접 구성 방식이 확장을 멈추는 지점이다. 터미널 하나가 다섯 개가 되면, Sharkly 같은 태스크 보드가 코딩 에이전트 위에 자리한다. Claude Code, Codex, Gemini CLI는 계속 작업을 수행하고, Sharkly는 태스크와 실행, 리뷰를 이미 닫아버린 터미널 곳곳에 흩어놓는 대신 한곳에 모아 둔다.
무인 실행이 실제로 무엇을 포함하는가
무인 실행이란 당신이 실시간으로 지켜보지 않는 호스트에서 코딩 에이전트가 태스크를 수행하고, 그 출력이 나중의 리뷰를 위해 기록되는 것을 말한다. 이 정의에는 핵심을 떠받치는 세 가지 요소가 있다. 에이전트가 당신 없이 끝낼 수 있는 태스크, 연결을 끊어도 계속 돌아가는 호스트, 그리고 나중에 읽어볼 수 있는 기록이다.

기록은 사람들이 가장 과소평가하는 부분이다. 에이전트를 실시간으로 지켜볼 때 로그 역할을 하는 건 당신이다. 잘못된 파일을 고르는 걸 보고, 중단시키고, 방향을 바로잡는다. 무인 실행에서는 그중 아무것도 일어나지 않는다. 에이전트가 한 모든 일이, 몇 시간 뒤 자신이 무엇을 요청했는지도 기억나지 않는 상태에서 차분히 들여다볼 수 있는 형태로 남아 있어야 한다. 에이전트는 조사하고 실행하고 테스트하고 보고한다. 사람은 방향을 정하고 권한을 부여하고 결과를 받아들인다. 이 계약은 돌아왔을 때 보고가 진실되고 완전할 때만 성립한다.
따라서 목표는 "나 없이도 에이전트를 돌게 만드는 것"이 아니다. "나 없이 돌게 하면서, 내가 리뷰할 수 있는 결과물을 돌려받는 것"이다. 이 둘은 서로 다른 문제이며, 무인 워크플로가 대개 무너지는 지점은 후자다.
직접 무인 실행 구성하기
다음은 최소한의 수동 방식과 각 단계에서 발목을 잡는 실패 유형이다.
1단계: 작업을 격리한다. 실행에 전용 체크아웃을 부여해 에디터나 다른 에이전트와 충돌하지 않게 한다.
git worktree add ../task-auth-refactor -b task/auth-refactor
cd ../task-auth-refactor
실패 유형: 이 단계를 건너뛰면 같은 디렉터리에서 돌아가는 두 실행이 서로의 커밋되지 않은 변경 사항을 덮어쓴다. 브랜치만이 아니라 워크트리가 왜 격리 경계인지는 태스크당 체크아웃 하나에서 확인하자.
2단계: 프로세스를 분리한다. SSH 세션이나 터미널은 닫히게 되어 있고, 포그라운드 프로세스는 그와 함께 종료된다(SIGHUP). nohup이나 tmux 세션으로 프로세스를 살려 두자.
nohup claude -p "Refactor auth to use the new token service; run the tests" \
> run.log 2>&1 &
실패 유형: 그냥 포그라운드 셸에서 실행하면 노트북을 덮는 순간 여러 파일을 수정하던 에이전트가 중간에 죽고, 망가진 트리가 남는다. nohup은 수명 문제를 해결해주지만 다시 들어갈 방법이 없다. tmux는 다시 접속해서 무슨 일이 벌어지고 있는지 확인할 수 있게 해준다.
3단계: 모든 것을 기록한다. 위의 > run.log 2>&1은 선택 사항이 아니다. 가장 날것의 형태의 리뷰 큐다.
실패 유형: 로그를 기록하지 않으면 "왜 멈췄지?"라는 질문에 답할 수 없다. 가장 흔한 조용한 정체는 아무도 답하지 않을 대화형 프롬프트에서 에이전트가 영원히 기다리는 것이다. 무인이라는 건 "예"를 입력해 줄 사람이 없다는 뜻이기 때문이다. 비대화형 모드로 실행하고, 해당 태스크에 필요한 최소한의 동작만 사전 승인하자.
4단계: 영향 범위를 제한한다. 자리를 뜨기 전에 에이전트가 스스로 해도 되는 일과 당신이 필요한 일을 정하자. 파일 범위를 제한하고, 강제 푸시를 금지하고, 무인 실행이 보호된 브랜치에 절대 머지하지 못하게 하자.
실패 유형: 권한이 과하게 부여된 실행이 main에 직접 푸시하는 건 생산성 향상이 아니라 사고다. 승인 게이트는 에이전트가 마지막 안전 지점에서 멈추고 기다리도록 하기 위해 존재한다.
5단계: 언제, 어떻게 끝났는지 파악한다. 종료 코드를 확인하고, 로그를 손으로 계속 들여다보지 않아도 되도록 알림을 보내자.
claude -p "..." > run.log 2>&1; echo "exit $?" | mail -s "auth run done" [email protected]
실패 유형: 완료 신호가 없으면 "무인"이 "20분마다 터미널을 확인하는 것"이 되어버린다. 이는 지연만 추가된 유인 실행일 뿐이다.
직접 만든 구성이 확장을 멈추는 지점
에이전트 하나, 워크트리 하나, 로그 파일 하나. 이건 잘 작동하며, 실행이 하나뿐이라면 더 무거운 게 필요 없다. 하지만 하나를 넘어서는 순간 이 구성은 무너진다.
세 개의 태스크에 에이전트 세 개를 돌리면 워크트리 세 개, 로그 파일 세 개, 종료 코드 세 개, 그리고 훑어보기만 해서는 잘못 읽게 될 완료 메일 세 통이 생긴다. 격리는 여전히 유지된다. 무너지는 건 리뷰 큐다. 어느 실행이 깔끔하게 끝났고, 어느 것이 테스트에서 실패했고, 어느 것이 조용히 프롬프트를 기다리고 있는지 알려주는 게 없다. 로그를 하나씩 읽으며 직접 재구성해야 하는데, 그건 바로 당신이 넘기려 했던 일이다.
이것이 진짜 비용이며, 각 조각이 개별적으로는 멀쩡해 보이기 때문에 놓치기 쉽다. 병렬로 돌아가는 여러 실행을 모니터링하는 일은 개수가 한 화면에 보이는 수를 넘어서는 순간 진짜 문제가 된다. 로그 파일은 "이 실행이 무엇을 출력했는가"에 답할 뿐, "내 여섯 개 실행 중 지금 나를 필요로 하는 건 어느 세 개인가"에는 답하지 않는다. 기록할 가치가 있는 상태 및 실패 신호도 스스로 큐로 정리되지 않는다. 그리고 그 큐야말로 자리를 비운 동안 일한다는 것의 핵심이다. 원하는 건 원시 출력의 디렉터리가 아니라 우선순위가 매겨진 결정 목록이다.
태스크 보드가 바꾸는 것
태스크 보드는 문제의 두 번째 축이 해결되는 곳이다. 무인 실행은 여전히 당신이 연결한 Computer에서 일어나고, 기존 Runtime이 코딩을 담당한다. 달라지는 건 결과가 도착하는 위치다.
Sharkly에서는 작업과 실행, 리뷰가 하나의 Task에 담긴다. Task를 Agent에 할당하는데, Agent는 매번 다시 입력하는 일회성 프롬프트가 아니라 지침과 Runtime, 저장소를 저장해 둔 구성이다. Agent가 Task를 가져가 격리된 워크트리에서 실행하고, 그 실행과 장애 요소, 결과가 Task 타임라인으로 돌아온다. 돌아왔을 때 로그 파일 여섯 개를 grep할 필요가 없다. 보드를 열고 큐를 읽으면 된다. 무엇이 끝났고, 무엇이 실패했고, 무엇이 나를 기다리고 있는지.
이 지점은 분명히 짚고 넘어갈 만하다. Sharkly는 Claude Code, Codex 또는 다른 실행 도구를 대체하지 않는다. 팀이 이미 사용하는 도구 주위에 공유 태스크, Computer, 컨텍스트, 리뷰 계층을 더한다. 코드를 작성하는 건 여전히 에이전트다. Sharkly는 당신이 자리를 비운 사이에도 코드가 확인 가능한 곳으로 돌아오고, 변경 요약과 테스트 결과가 함께 첨부되며, 최종 수락이 사람의 결정으로 남도록 보장한다. 자동화는 판단이 필요한 지점에서 멈춘다.
이 모든 걸 워크트리와 nohup, 메일 명령으로 직접 만들 수 있다. 솔직한 판단 기준은 이렇다. 에이전트를 가끔 하나씩 돌린다면 수동 구성으로 충분하고 Sharkly는 불필요한 부담이다. 여러 에이전트가 여러 태스크와 저장소에 걸쳐 돌아가고 리뷰 큐가 아침 시간을 잡아먹기 시작하면 계산이 달라진다. 하나의 생태계에 정착하는 대신 여러 코딩 에이전트를 계속 쓰고 싶다면, 그 큐가 바로 Sharkly가 겨냥해 설계된 문제다.
리뷰 큐가 진짜 병목이다
여기서 의심해볼 만한 가정이 있다. 사람들은 무인 실행을 최적화하고 리뷰는 나중에 생각할 일로 취급한다. 이건 거꾸로다. 잠든 사이 에이전트를 병렬로 돌리는 건, 다음 날 아침 그 출력을 리뷰하는 일이 직접 작업하는 것보다 빠를 때만 이득이다. 밤새 에이전트 다섯 개가 끝났는데 다섯 개의 diff를 모두 리뷰하는 데 그중 두 개를 직접 작성하는 것보다 오래 걸린다면, 병렬화는 아무것도 만들어내지 못한 것이다.
그러니 리뷰 큐를 먼저 설계하자. 실행이 당신에게 도달하기 전에 "완료"에 반드시 포함되어야 할 것을 정하자. 테스트 통과, 타입 검사, 변경 요약, 알려진 한계에 대한 메모 같은 것들이다. 큐는 완료 시간이 아니라 위험도 순으로 정렬해서, auth를 건드린 실행이 오타를 고친 실행보다 먼저 눈에 들어오게 하자. "변경 요청"을 "승인"만큼 저렴하게 만들자. 무인 실행의 절반은 거의 맞지만 완전히 맞지는 않을 테니까. 리뷰는 모든 병렬 에이전트 워크플로의 병목이며, 에이전트가 물리적으로 어디서 돌아가는지—당신의 서버인지, 노트북인지, 아니면 둘 다인지—는 그 출력이 처리 가능한 큐의 형태로 도착하는지 여부보다 훨씬 덜 중요하다.
오늘 바로 적용할 수 있는 체크리스트
에이전트에게서 자리를 뜨기 전에 다음을 확인하자.
- 격리: 실행에 자체 워크트리가 있고, 작업 중인 체크아웃을 쓰지 않는다.
- 수명: 연결이 끊겨도 프로세스가 살아남는다(
nohup,tmux또는 관리형 Computer). 노트북을 덮어도 수정 도중에 죽지 않는다. - 기록: stdout과 stderr가 영구 로그나 나중에 차분히 읽을 수 있는 Task 타임라인으로 저장된다.
- 비대화형: 아무도 답할 수 없는 프롬프트에서 에이전트가 멈추지 않는다.
- 영향 범위: 파일 범위가 제한되고, 강제 푸시가 꺼져 있으며, 어떤 무인 실행도 보호된 브랜치에 머지하지 않는다.
- 완료 신호: 폴링 없이 언제 끝났고 통과했는지 알림을 받는다.
- 리뷰 계약: 완료된 모든 실행이 테스트, 변경 요약, 알려진 한계와 함께 도착하고, 수락 여부는 당신에게 남는다.
앞의 여섯 가지는 실행을 무인으로 만든다. 마지막 하나는 그 실행을 할 가치가 있게 만든다. 이미 여러 에이전트를 돌리고 있고 아침 리뷰에 시간을 쏟고 있다면, 기존 코딩 에이전트를 Sharkly를 통해 실행해 큐가 흩어져 있는 대신 정리된 상태로 당신에게 도착하게 하자.



