소프트웨어 팩토리가 필요할까요?

TMT

https://x.com/addyosmani/status/2092865809299476767

소프트웨어 팩토리란 소프트웨어 작업을 반복 가능한 루프로 감싸 둔 것입니다. 팩토리를 짓는다고 해도, 출시할 만한 코드에는 여전히 사람의 안목과 책임이 필요합니다. 이 글에서는 그 이야기를, 그리고 지금 당장 팩토리가 _정말 필요한지_까지 함께 살펴보겠습니다.

팩토리가 필요하다면, 이런 것들이 따라옵니다.

  • 제품의 의도를 정하고, (신경 쓴다면) 시스템을 설계하고, 품질 기준을 세우는 앞단에는 사람이 들어가야 할 가능성이 큽니다.
  • 코드 리뷰는 하되(불을 켜 둔 팩토리, lights-on factory), 어디에 가장 필요한지를 의도를 갖고 고르세요. 제 경험으로는 자동 제동(back-pressure)이 듣지 않는 지점, 그리고 유지보수성에서 타협을 봐야 하는 지점을 눈여겨보게 됩니다.
  • 품질 검사는 가능한 한 이르게, 그리고 끊이지 않게 돌아가도록 하는 것을 목표로 삼으세요. 모든 검사가 그럴 필요는 없지만, 여기에는 타입 시스템, 자동화 테스트, 뮤테이션 테스트, 보안 스캐너, 아키텍처 규칙을 검사하는 린팅이 들어갑니다.
  • 검사 개수가 곧 품질은 아닙니다. 어떤 검사가 신호 대 잡음비를 가장 좋게 만들어 주는지는 실험해 봐야 알 수 있습니다. 제약을 조일지 풀지도 의도적으로 판단할 준비가 필요합니다.

팩토리는 사람의 안목 가운데 일부가 환경 자체에 새겨지도록, 에이전트가 자기 작업이 맞다는 증거를 내놓도록, 그리고 프로덕션에 나가는 것에 대해서는 여전히 사람이 "책임을 지도록" 만들어야 합니다.

정말 소프트웨어 팩토리가 필요한가요?

제 경험으로는, 손에 있는 기본 코딩 하네스만으로도 놀랄 만큼 멀리 갈 수 있습니다! 그러니까 Claude Code나 Codex를 여러 세션으로 돌리고, 검증까지 함께 적어 둔 좋은 명세와 제약만 있으면 됩니다. GitHub 이슈를 한 묶음 던져 주면서 구현 기준과 사람이 개입할 기준을 함께 붙여 줄 수도 있습니다. Claude Code의 루틴, Copilot과 Codex의 클라우드 에이전트는 별도 인프라 없이도 일정 기반이나 이벤트 기반 루프를 이미 제공합니다.

팩토리가 값을 하는 건 이럴 때입니다. 실행을 반복해도 일관되게 굴러가야 하고, 에이전트 사이로 작업을 넘겨야 하고, 두 세션이 같은 이슈를 집어 들지 않게 막아야 하고, 증거를 남겨야 하고, 리뷰가 밀리면 배포를 멈춰야 할 때죠.

Image

앞에서 소프트웨어 팩토리는 소프트웨어 작업을 감싼 반복 가능한 루프라고 말씀드렸습니다. 아주 작은 팩토리 루프를 그대로 보여 주는 프롬프트를 하나 보겠습니다.

코드를 바꾸기 전에 GitHub 이슈 #123과 저장소 지침을 읽으세요. 명시된 수용 기준만 구현하세요. 인증, 결제, 마이그레이션, 기존 테스트 단정문은 건드리지 마세요. 브랜치에서 작업하고 diff는 리뷰할 수 있는 크기로 유지하세요. npm run lint, npm test, npm run build를 실행하세요. 필요한 검사를 실행할 수 없다면 멈추고 이유를 설명하세요. 실행한 검사, 남아 있는 위험, 사람이 아직 내려야 하는 결정을 담아 초안 풀 리퀘스트를 여세요. 머지하지 마세요.

목표를 하나 걸어 두면 검사가 통과할 때까지 이 루프가 계속 굴러가고, 매일 아침 특정 라벨이 붙은 GitHub 이슈를 훑거나 열려 있는 풀 리퀘스트를 리뷰하게 할 수도 있습니다. 브랜치 보호 규칙으로 머지 경계를 강제할 수 있고, 사람은 무엇을 준비된 것으로 올릴지 고르고, 리뷰하고, 최종 머지를 결정하는 식으로 루프 안에 남아 있을 수 있습니다.

Slack 트리거나 GitHub 이슈, Linear, 백로그처럼 이벤트로 밀려드는 작업 큐를 격리된 클라우드 환경에서 돌려 분류와 구현, 테스트까지 처리하면서 사람이 명시적으로 지켜봐야 할 때, 그때 소프트웨어 팩토리를 더하세요. 루프 끝에 프로덕션을 감시하다 이슈를 등록하는 모니터 에이전트를 두고, 그 이슈가 다시 분류 단계로 들어가게 만드는 사람들도 있습니다.

제 경험상 팩토리가 쓸모 있어지는 건, 어려운 대목이 이런 것들로 옮겨 갔을 때입니다. 서로 다른 실행을 일관되게 굴리는 일, 에이전트 사이로 작업을 넘기는 일, 서로 다른 세션이 같은 이슈를 차지하지 못하게 하는 일, 증거를 남기는 일, 사람 리뷰가 밀릴 때 배포를 멈추는 일이죠.

이걸 해결하는 방법은 좀 시시하게 들릴 수도 있습니다. 예를 들어 Warp는 들어오는 모든 이슈를 ready-to-implement, ready-to-spec, needs-info, wait-to-implement 네 가지 상태 가운데 하나로 분류한다고 이야기하는데, 다음 에이전트를 쏘는 방아쇠가 바로 그 라벨입니다.

Image

라벨 하나가 여러 일을 한꺼번에 합니다. 큐이면서 잠금장치이고, 세션이 준비됨으로 표시된 것만 집어 들기 때문에 사람이 영구적으로 거절하지 않고도 잠시 세워 둘 수 있는 자리가 됩니다.

작업 흐름으로 보면 Claude나 Codex를 그냥 쓰는 것과 비슷한 점도, 다른 점도 있습니다.

  • 방향 조정(steering): 에이전트가 궤도를 벗어나면 입력을 주고 다시 방향을 잡아 줄 수 있습니다.
  • 알림(notifications): 팩토리가 막혔다고 알리는 방법입니다. 요구사항이 모호했거나, 위험한 일을 시작했거나, 사람의 입력(방향 조정)이 필요할 때 알립니다.
  • 인계(handoff): 작업과 그 상태, 맥락을 클라우드 팩토리와 다른 에이전트, 사람 리뷰어 사이로 옮기는 일입니다. 인계가 잘 되면 무슨 일이 있었는지, 무엇이 남았는지, 왜 넘기는지가 함께 따라옵니다.

좋은 팩토리에서 사람은 맨 끝에 최종 diff를 리뷰하고 승인하는 역할에만 묶이지 않습니다. 초반에 작업의 모양을 잡고, 구현 중에 방향을 틀고, 인계를 통해 넘겨받고, 프로덕션 배포를 멈출 수도 있습니다.

책임감 있는 팩토리가 시간을 많이 쓰는 곳은 검증입니다. 이 얘기는 뒤에서 더 하겠습니다.

Image

소프트웨어 팩토리가 필요하다고 판단했다 해도, 직접 만드는 것만이 답은 아닙니다. 팩토리를 키울 인프라를 세우는 일은 손이 많이 가니 만들지 살지 견주어 볼 만합니다. Factory.ai, Devin, Warp, HumanLayer는 모두 이 루프의 일부를 팔고 있습니다.

제가 실제로 주의를 쏟는 곳

지난 1년 사이 소프트웨어 개발을 하는 제 일상이 많이 달라졌습니다. 에이전트와 병렬로 일하는 비중을 계속 늘리면서 불을 켜 둔 소프트웨어 팩토리 쪽으로 가고 있다는 이야기를 해 왔습니다. 그러니 많은 분들이 묻습니다. 그게 실제로 무슨 뜻이냐, 무엇을 만들고 있냐, 그런 걸 어떤 종류의 프로젝트에 쓰고 있냐고요. 대체로 이런 모습입니다.

Image

아주 평범한 날에 저는 비교적 단순한, 불을 켜 둔 소프트웨어 팩토리를 돌립니다. 클라우드에서 작업이 돌아가고 있을 수 있습니다. 그 절반쯤은 제가 함께 일하는 작은 회사들의 실서비스 애플리케이션을 손보는 작업일 겁니다. 거기엔 실제 사용자가 있고, 실제 인증과 결제, 구독이 있고, 조심해서 다뤄야 하는 묵직한 위험이 있습니다. "에이전트야, 가서 이거 해 놔" 하고 테스트도 제약도 품질 검사도 없이 던져 둘 수는 없습니다.

제 오픈소스 프로젝트를 손볼 때도 있습니다. 제가 쓴 책의 부속 사이트를 만들 수도 있고, 도구를 만질 수도 있고, 제 앱을 만들 수도 있습니다. 이 모두가 성격이 아주 다른 애플리케이션이고, 어떤 때는 공통점이 작업에 쓰는 도구뿐입니다. 어떤 건 마이그레이션이고, 어떤 건 제대로 큰 기능 개발입니다. 작업이 미치는 영향 범위도 아주 다를 수 있습니다.

그래서 병렬 작업을 점점 늘려 가면서 속도와 생산성, 그리고 자율성까지 끌어올리려 한다면(자율성을 올린다는 건 시스템을 더 믿을 수 있는 상태로 만든다는 뜻입니다), 사람의 코드 리뷰와 사람의 입력이 반드시 필요한 자리가 어디인지는 짚어 봐야 합니다.

그리고 그 상당 부분은 앞단에서 필요합니다. 명세와 요구사항을 정의할 때, 제품의 설계는 어떤 모습일지, 제품의 의도는 무엇인지 정할 때죠. 그다음은 에이전트가 정말 제대로 해냈는지를 어떻게 확인하느냐입니다. 기존에 돌아가던 시스템을 망가뜨리지 않았다는 걸 어떻게 확인할까요? 품질 기준을 만족한다는 건 어떻게 보장할까요?

그러니 코드를 생성하는 일이 가장 걱정할 대목은 아닙니다. 맥락이 충분하면 에이전트는 구현을 쓰고 테스트를 돌리고 실패를 들여다보고 코드를 고쳐 줍니다. 사람의 안목이 환경에 충분히 새겨져 있어서 만들어지는 것을 믿을 수 있는 상태, 그래서 사람의 주의를 가장 필요한 곳에 모을 수 있는 상태까지 가야 합니다.

물론 "이런 걸 그냥 자동화로 없앨 수 있다는 말은 못 믿겠다"고 반박하는 분들도 있습니다. 전부를 자동화로 없앤다는 얘기는 아닙니다. 다만 지금 생성되는 코드의 양을 생각하면 사람이 그걸 전부 읽는다는 건 현실적이지 않습니다. 우리가 만드는 게 로켓인 경우는 많지 않으니까요. 우리는 UI를 만들고 풀스택 애플리케이션을 만듭니다.

우리의 판단과 안목은 그것이 가장 필요한 곳에 모으는 게 가장 좋습니다. 시스템에서 가장 위험한 부분은 어디인가? 사람의 안목을 들여야 하는 지점은 어디인가? 그건 프런트엔드일 수도 있고, 시스템이 돌아가는 방식일 수도 있습니다. 전부일 필요는 없습니다.

제 인지 대역폭은 에이전트만큼 늘어나지 않습니다

현실은 이렇습니다. 이제 수십, 수백, 수천 개의 에이전트를 병렬로 띄울 수 있게 됐지만, 정작 내 인지 대역폭은 그렇게 늘어나지 않습니다. 이건 제가 전에 이야기한 인지 부채, 또는 이해 부채로 흘러 들어갑니다.

Image

불과 5년, 10년 전을 떠올려 보면 엔지니어링 업계에서 문맥 전환과 그 비용을 두고 이야기가 많았습니다. 어떤 작업에 한창 몰입해 있을 때 동료가 자리로 걸어오는 걸 사람들이 얼마나 싫어하는지 이야기했죠. 그러고 나면 흐름을 되찾는 데 한참 걸렸습니다. 내가 어디까지 했지, 뭘 하고 있었지부터 다시 따라잡아야 했으니까요. 머릿속에 잔상이 조금 남아 있어도 시간은 걸렸습니다.

지금 우리는 그때보다 문맥 전환을 더 많이 합니다. 소프트웨어 팩토리 밖에서 일하는 날이면 저는 한 번에 서로 다른 프로젝트 다섯에서 열 개를 에이전트와 함께 붙잡고 있거나, 한 프로젝트에서 서로 다른 기능 다섯에서 열 개를 동시에 진행하기도 합니다. 사실상 세션이 다섯에서 열 개 열려 있는 셈입니다.

그러면 최소한 그중 몇 개는 놓치지 않고 따라가야 합니다. 작업을 충분히 잘 정의했고, 결과가 무엇인지, 잘 됐는지를 어떻게 검증할지까지 정해 뒀다는 믿음이 있으면 어떤 작업에는 자율성을 더 줄 수도 있습니다. 하지만 그런 믿음이 안 드는 작업, 위험이 더 크거나 판단이 미묘한 작업도 있습니다. 그런 건 제가 신경을 써야 합니다.

소프트웨어 팩토리를 리뷰어 기준으로 최적화하는 것도 고려해 보세요. 어떤 방식을 쓰든 결과물은 결국 한 사람의 주의로 흘러 들어가니, 내가 여전히 내려야 하는 결정을 팩토리가 얼마나 값싸게 만들어 주고 있는지 물어봐야 합니다.

엉뚱한 프로젝트에 저지른 실수

에이전트와 여러 프로젝트를 병렬로 돌리다가 실수한 적이 있습니다. 어떤 웹 앱에 다크 모드를 넣으려던 중이었고, 머릿속에는 이건 이런 모양이어야 한다는 그림이 있었습니다. 그런데 실수로 다른 프로젝트의 세션에 들어가서 그 프롬프트를 그대로 넣기 시작했습니다.

그래서 다크 모드가 전혀 필요 없는 것에 다크 모드를 구현하기 시작했습니다. 저는 그런 실수를 할 수 있습니다. 하지만 제 소프트웨어 팩토리가 그런 실수를 하는 건 원하지 않습니다.

이건 시스템의 관점에서 생각해야 합니다. 결국 소프트웨어 엔지니어링 문화, 팀 문화를 시스템에 새겨 넣어서 시스템이 같은 방식으로 움직이게 하고, 책임이 어딘가에 분명히 놓이게 하고, 무슨 일이 생겼을 때 여전히 누군가가 그 일을 감당하게 만드는 작업입니다. 그리고 그런 것들을 어떻게 생각하는지 아주 명시적으로 적어 두는 일이기도 합니다.

초록불이 거짓말할 때

이런 시스템에서도 아주 조심해야 합니다. AI에게 테스트를 통과하게 도와 달라고 했을 때, 그러니까 유닛 테스트 같은 걸 말하는데, 조건을 맞추려고 유닛 테스트 자체를 바꿔 버리거나 코드 로직을 바꿔 버리는 걸 많은 분들이 봤을 겁니다. 그건 기능 동작과 테스트가 검사하려던 것을 함께 맞추라는 내 의도를 따랐다는 뜻이 아닙니다.

Image

소프트웨어 팩토리가 전부 초록불이라고 보여 준다고 해서 정말로 초록불인 건 아닙니다. 특히 이런 걸 처음 세팅하는 초반에는 더 그렇습니다. 검사와 검증이 제대로 된 모양을 갖췄는지, 기대한 일을 하고 있는지 상당히 신경 써서 확인해야 합니다. 그것들이 사람을 오해하게 만들면 안 됩니다.

이런 상황은 원치 않을 겁니다. 알고 보니 지원하는 인증 제공자가 바뀌어 있는데도 테스트는 문제없다고 말하는 경우죠. GitHub를 인증 제공자로 추가해 달라고 했더니, UI에 자리가 세 개뿐이라 다른 하나를 빼 버렸고, 하필 그게 고객들이 실제로 원했던 것이었던 겁니다. 그러니 이 시스템이 어떻게 동작하길 원하는지 아주 명시적으로 말해 둬야 합니다.

그리고 보안도 아주 중요합니다. 팩토리가 GitHub 이슈나 Slack 메시지처럼 신뢰할 수 없는 입력을 읽는다면, 그 입력이 공격을 노린 것일 수 있고 공급망 공격 같은 문제를 품고 있을 수 있습니다. Vercel Sandbox나 AI ADK Factory처럼 소프트웨어 팩토리 주변의 일부 제품은 에이전트를 격리된 샌드박스에서 돌리고 그 작업에 필요한 비밀값만 쥐여 줍니다. 그러면 침해된 실행이 그 작업에 필요 없는 것까지 손을 뻗지 못합니다. 방어는 결국 여러 겹으로 쌓이게 됩니다.

어떤 옛 프로젝트에 다시 생명을 줄까요?

요즘 일하는 방식에서 큰 몫을 차지하는 건 무엇이 존재해야 하는지를 정하는 일이라고 생각합니다. AI 이전, 여러 해 전을 떠올려 보면 버려진 소프트웨어 프로젝트가 참 많았습니다. 주말에 손대다 만 프로젝트, 개인 프로젝트가 그렇게 많았는데 끝낼 시간이 없어서 출시까지 가지 못했습니다. 그걸 세상에 내놓는 일을 우선순위에 올릴 여력이 없었죠. 우리에게 그만큼 중요하지 않았거나, 시간을 낼 수 없었으니까요.

지금은 그런 프로젝트를 끝내는 게 꽤 쉬운 일이 됐지만, 똑같은 사람의 판단 문제가 남습니다. 그 프로젝트는 존재할 만한가? 출시해야 하는가? 세상에 내놓으면 사용자가 다섯뿐이어도 유지보수를 해야 할 수 있고, 지키고 싶은 품질 기준이 생기니까요.

저도 여러 해에 걸쳐 쌓인 GitHub 프로젝트가 아주 많은데, 에이전트가 생긴 뒤로는 제일 먼저 빌드가 되게 만듭니다. 클론해 보면 당연히 빌드가 안 되죠. 의존성이 다 바뀌었으니까요. 절반쯤은 낡았거나 보안 취약점이 널려 있어서 갱신해야 합니다.

그다음엔 테스트가 없었다면 테스트를 붙여야 합니다. 프로젝트를 어떤 식으로든 업그레이드하거나 더 현대적인 언어나 프레임워크로 옮길 때, 적어도 동작이 유지된다는 걸 알 수 있어야 하니까요.

그러다 스스로 묻게 됩니다. 시시한 예지만, 그때는 이걸 Twitter Bootstrap으로 만들었는데 이제 다들 Tailwind와 shadcn을 쓰니 UI를 다시 구현해야 하는구나 하고요. 그러면 어느새 시간이 더 들고 있다는 걸 알게 됩니다. 에이전트가 많은 부분을 더 빨리 해내는 건 맞지만, 이제 제품 감각과 안목 같은 것들까지 계산에 넣어야 합니다.

여전히 묻게 됩니다. 이건 누구를 위한 것인가? 시장이 있는가? 나를 위한 것인가, 다른 사람을 위한 것인가? 세상에 내놓는다면, 이제 누구나 이런 걸 금방 만들어 낼 수 있는데도 여전히 흥미로울까?

그래서 이것들이 존재할 만한가 하는 사람의 질문, 그리고 우리의 안목과 판단을 어떻게 계산에 넣을 것인가 하는 질문은 계속 아주 중요하다고 생각합니다. 사람의 주의라는 희소한 자원이 진짜로 쓰이는 곳이 거기입니다. 예전에는 하루에 쓸 수 있는 시간이 정해져 있었습니다. 회의가 있었고, 설계와 코딩에 쓸 시간을 예산처럼 배분해야 했습니다.

이제 에이전트가 도와주는 만큼, 시간을 어디에 왜 쓰는지를 아주 분명히 정해 둬야 한다고 생각합니다.

직접 하나 만들어 봤을 때 벌어진 일

82분 동안 돌아간 팩토리 실행 이야기를 해 보겠습니다. 꽤 오래전부터 사람들이 물어 왔습니다. 소프트웨어 팩토리는 어떻게 만드느냐고요. 또는 Claude Code나 Codex는 익숙한데 이 세팅을 소프트웨어 팩토리로 어떻게 발전시키느냐고요.

제가 먼저 하는 말은 이렇습니다. 지금도 괜찮을 수 있습니다. 팩토리 없이도 여러분의 작업은 전혀 문제없을 수 있습니다. 그래도 참고할 수 있는 기준 세팅을 하나 보여 드리고 싶었습니다. 그래서 Factory라는 저장소를 만들어 두었으니 살펴보셔도 됩니다. 데모 애플리케이션워크숍도 함께 만들었습니다.

지난 몇 년 동안 제가 여러 일에 즐겨 쓴 데모 애플리케이션은 영화 앱입니다. 저는 영화를 아주 좋아해서 늘 영화를 봅니다. 그래서 아주 단순한 영화 앱에서 출발하는 데모가 하나 있습니다. 그리고 팩토리가 이 앱에 여러 기능을 구현해 주길 원했습니다. 기능이 몇 가지 있는데, 즐겨찾기를 원했고, 검색도 되면 좋겠고, 다크 테마도 들어가면 좋겠다는 식이었습니다.

그래서 팩토리가 이 일들을 시작하게 했습니다. 구현은 직접 보실 수 있습니다. 좋았던 점 하나는 실제 문제를 잡아냈다는 것입니다. 한 번에 구현해 달라고만 했다면 제가 놓쳤을 문제들일 수 있습니다.

60분쯤 지났을 때 유난히 느리다는 느낌이 들었습니다. 팩토리를 돌리던 하네스에 왜 이렇게 느리냐고 물었습니다. 답은 이랬습니다. 정상입니다, 검증기들이 아직 다 돌고 있습니다.

개별 작업이 10분, 15분, 20분쯤 걸릴 거라고 예상했을 수 있지만, 검증과 재시도, 브라우저 검사, 사람 리뷰 같은 추가 지연이 들어가기 시작하면 두 배에서 네 배까지 걸릴 수 있습니다.

그게 쌓여서 품질이 좋아지고 시스템에 대한 신뢰가 올라갈 수 있다고 생각합니다. 측정 관점에서는 머지된 PR 하나당 비용, 그리고 이해 부채를 재는 지표로 코드의 유통기한 같은 것을 볼 수 있습니다.

어디까지가 쓸모 있는 지연이고 어디부터가 팩토리 부대비용인지도 생각해야 합니다. 제 경우 검증기들은 실제 문제를 잡아냈습니다. 시간의 일부는 제가 원한 증거를 만드는 데 들어갔을 겁니다. 일부는 팩토리를 돌리는 데 따르는 부대비용이었습니다. 최적화에는 시간을 거의 쓰지 않았지만, 값이 안 되는 검사를 잔뜩 돌리는 팩토리라고 해서 품질이 높은 팩토리는 아닙니다.

반복해서 돌아가는 검사가 있다면 그게 무관한 검사인지, 잡음만 내는지, 정말로 시스템을 더 안전하게 만드는지 들여다볼 필요가 있습니다.

검증에도 예산이 필요합니다

검증에 쓸 예산을 저는 이렇게 생각합니다. 결국 검증 예산 이야기입니다. 예전부터 성능 예산을 생각해 온 방식과 똑같이 봅니다.

Image

소프트웨어 개발 생애주기의 앞쪽에서 돌릴 수 있는 검사가 있고, 아주 무겁지만 값이 커서 뒤쪽에서 돌리고 싶은 검사가 있습니다. 린팅이나 타입 검사처럼 빠른 검사는 비교적 가벼워서 앞쪽에서 돌릴 수 있습니다.

전체 테스트 묶음은 초안 PR을 만들기 바로 전이나 그 뒤에 돌릴 수 있습니다. 여기에는 뮤테이션 테스트, 브라우저 테스트, 보안 검사 같은 게 들어갈 수 있습니다.

이런 것들을 요약으로 대체하려 해서는 안 된다고 생각합니다. 실제 테스트가 필요합니다. 다만 개발 루프를 느리게 만들고 싶지는 않으니, 예산을 어디에 배분할지 잘 맞춰야 합니다. 저는 제 개발 루프가 느려지는 건 절대 원하지 않습니다. 빠른 반복 루프는 제게 중요하지만, 그러면서도 견제 장치는 남겨 두고 싶습니다.

실행이 배포까지 가지 못할 때

위에 쓴 내용은 대부분 검사에 관한 것입니다.

Vercel은 자기들 소프트웨어 팩토리에서 모든 에이전트 실행에 "success", "flawed", "blocked", "manual" 가운데 하나를 붙이고 "success"만 프로덕션으로 내보냅니다. 나머지는 다시 시스템으로 들어옵니다. 저도 실행을 비슷한 틀로 생각해 왔습니다.

Image

여기서 "flawed"는 엉뚱한 것이 구현됐거나 맥락이 충분하지 않았다는 뜻이고, 그건 고쳐야 합니다. "blocked"는 환경에 자격 증명이 빠져 있었다는 뜻이니 그걸 넣어 줘야 합니다. "manual"은 팩토리가 아직 넘어가도 된다고 허락받지 못한 경계입니다.

셋 중 둘은 기계적으로 고칠 수 있고, 마지막 하나는 신뢰의 문제입니다.

이 분류는 좋지만, 분류만으로는 비용이 보이지 않습니다. TMDB 앱으로 만든 제 팩토리 구현으로 돌아가 보면, 반려 없이 지나간 빠른 검색(quick finder) 기능은 7분이 걸렸습니다. 반려가 두 번 있었고 중간에 사람의 결정이 끼어든 즐겨찾기는 56분이 걸렸습니다. 같은 팩토리에서요. 그래서 저는 이 분류에 단계별 소요 시간을 함께 붙이겠습니다. 그렇지 않으면 실행이 flawed로 돌아왔다는 사실만 알고, 그걸 알아내는 데 얼마가 들었는지는 모르게 됩니다. 또 하나 고칠 것은 경계에서의 인계입니다. 제 예제 팩토리는 첫 이슈를 멈춰 세우고 factory:needs-info로 옮겼는데, 그 판단은 옳았지만 제 답을 어디에 적어야 하는지 알 수 없었습니다. manual로 분류된 실행은 팩토리가 멈추는 순간에 끝나는 게 아니라, 사람이 다음에 무엇을 할지 알게 되는 순간에 끝납니다.

자율성은 스위치 하나가 아닙니다

몇 주 전에 에이전트 자율성과 자율성을 어떻게 생각해야 하는지에 대한 글을 썼습니다. 자율성은 모든 프로젝트에 똑같이 적용되는 설정 하나가 아니기 때문입니다.

검증을 해 두면 신뢰가 생기고, 그만큼 에이전트에게 자율성을 더 줄 수 있게 됩니다. 예를 들어 만만치 않은 변경을 작업하는데 검사를 여러 개 걸어 뒀고, 모든 게 제대로 검증됐고, 제가 직접 손으로도 확인했다고 해 봅시다. 같은 프로젝트에서 다음에 비슷한 작업을 할 때는 에이전트에게 자율성을 조금 더 줘도 마음이 놓일 겁니다.

소프트웨어 팩토리를 만들 때 생각해야 하는 게 그것입니다. 검증은 위험에 따라 달라집니다. 목표는 신호 대 잡음비를 가장 좋게 만드는 것입니다. 커다란 체크리스트를 그냥 돌리는 게 목표가 아닙니다.

다시 배워야 했던 기능

Claude로 여러 세션을 돌리던 어느 날, 미뤄 두고 있던 기능이 하나 있었습니다. 그때 저는 여러 프로젝트를 한 번에, 프로젝트마다 여러 기능을 한 번에 붙잡고 있었습니다. Claude가 제가 하려던 기능을 구현했고, 테스트도 통과하는 것처럼 보였습니다. 검증에 깊이 고민을 하지는 않았지만 테스트가 통과했으니 잘 됐다고 생각했습니다. 그래서 머지했습니다.

즐겨찾기 기능이었습니다. 꽤 괜찮다고 생각했습니다. 브라우저에서 확인해 봤고 괜찮아 보였습니다. 그런데 며칠 뒤에 손볼 게 좀 있다는 생각이 들어서 코드로 돌아갔습니다.

그냥 에이전트에게 바꿔 달라고 하고 싶지는 않았습니다. 동작 방식이 미묘했기 때문입니다. 아이콘을 누르면 눌렀을 때의 효과가 제대로 나오지 않았고, 그걸 다듬고 싶었습니다. 에이전트를 제대로 이끌려면 그게 어떻게 동작하는지 제가 알아야 했습니다.

코드로 돌아갔는데, 그 기능이 어떻게 동작하는지 설명할 수 없었습니다. 제 저장소였고, 제가 그 변경을 승인했습니다. 저장소가 어떻게 돌아가는지도 상당 부분 알고 있었습니다. 그런데 제 이해가 쌓여 가는 코드의 속도를 따라가지 못했던 겁니다.

제가 흡수하지 못한 건 새로 들어온 그 기능이 실제로 어떻게 동작하는지, UI가 어떻게 동작하는지, 그 효과가 어떻게 나는지였습니다. 결국 이 기능을 다시 만들면서 한 단계씩 짚어야 했습니다. 이건 어떻게 동작하지? 어떻게 이해할 수 있지?

병렬 작업이 이해에 하는 일

병렬로 일하면 이 문제 전체가 증폭되고, 소프트웨어 팩토리에서 하면 더 증폭됩니다. 세션을 다섯이나 열 개씩 돌리면 단순히 리뷰할 양이 늘어나는 문제로 끝나지 않습니다. 내가 다른 데를 보는 동안 꽤 식어 버릴 수 있는 머릿속 모형이 여러 개 생깁니다.

우리는 오래전부터 문맥 전환의 어려움을 이야기해 왔습니다. 대화가 압축되고, 어떤 접근은 물리고, 이것저것 시도하고, 에이전트와 짝을 지어 일하다 보면 세션에서 무슨 일이 있었는지 전부 기억하기는 어렵습니다.

위로 스크롤해 봐도 압축이 계속 일어났으니 전부 남아 있지 않고, 머릿속에 다 담아 둘 수도 없습니다. 코드는 어떤 결정이 내려졌는지는 남기지만, 그 결정을 왜 내렸는지는 남기지 않는 경우가 많습니다.

여기서 얻을 만한 배움이 있다고 생각합니다. 중요한 대목이라면, 에이전트에게 자신이 지나온 경로나 문제에 어떻게 접근했는지에 대한 흥미로운 교훈을 실제로 기록해 두게 해서 나중에 다시 볼 수 있게 하는 것을 고려해 보세요.

이걸 저장소에 커밋할지는 정하면 됩니다. 로컬에만 둬도 되고, 팀에 공유해도 됩니다. 어느 쪽이든 나중에 참고할 수 있는 것이 됩니다. 그게 세션에 아직 남아 있기를, 또는 나중에 내가 기억해 내기를 바라는 것보다는 낫습니다.

그래서 이 팩토리는 무엇을 만들어 내는가?

@threepointone@bentlegen이 소프트웨어 팩토리에 대해 올린 의견(1, 2)에 저도 크게 동의했습니다.

Image Image

일을 굴리는 기계 장치에 홀려서 기계만 최적화하다가, 원래 무엇을 만들어 내야 했는지를 잊기 쉽습니다. 팩토리가 주로 더 나은 팩토리를 만들어 내고 있다면, 자기 자신이 제품인 소프트웨어를 만든 셈입니다.

루프에 투자하는 것 자체는 괜찮고, 그 효과는 쌓입니다. 문제는 루프가 닫힐 때입니다. 팩토리가 만들어 내는 모든 것을 팩토리가 다시 소비하고, 스위치를 내려도 바깥의 누구도 알아차리지 못하는 상태 말입니다. 제가 대 보는 기준은 바깥에서 당기는 힘이 있는지입니다. 그 개선을 원하는 무언가가 바깥에 있어야 합니다. 누가 당기고 있는지 이름을 댈 수 없다면, 그건 그냥 광을 내고 있는 것입니다.

책임은 사라지지 않습니다

이 모든 것 아래에는 더 넓은 원칙이 하나 있습니다.

사람이 직접 타이핑하는 코드의 비율은 크게 떨어질 수 있습니다. 하지만 사람의 책임까지 함께 떨어져야 한다고는 생각하지 않습니다.

  • 문제를 고르는 건 여전히 누군가입니다.
  • 아키텍처를 고르는 건 여전히 누군가입니다.
  • 품질 기준을 세우는 건 여전히 누군가입니다.
  • 어떤 검증 신호를 믿을 만한지 정하는 것도 누군가입니다.
  • 증거가 배포해도 될 만큼 충분한지 판단하는 것도 누군가입니다.

그리고 그렇게 만들어진 시스템이 망가졌을 때 "에이전트가 썼다"는 말은 통하지 않습니다. 그래서 저는 소프트웨어 엔지니어링의 미래를 사람이 루프에서 빠져나가는 일로 설명하는 게 맞다고 보지 않습니다. 그보다는 사람의 판단이 놓이는 자리가 옮겨 가고 있습니다.

기계가 더 강하고 빠르고 결정적인 신호를 낼 수 있는 구간에서는 사람을 빼야 합니다. 동시에 맥락과 안목, 위험, 장기적인 책임이 가장 중요한 곳에는 사람을 모아야 합니다.

가장 좋은 소프트웨어 팩토리는 사람의 개입을 얼마나 완전히 없앴는지로 판가름되지 않습니다.

사람의 개입을 얼마나 영리하게 배치했는지로 판가름됩니다.

의도와 시스템의 모양, 품질 기준에 대해서는 사람의 판단을 앞단에 두세요. 자동 제동이 약해지는 곳, 또는 결과에 대한 판단이 주관적으로 바뀌는 곳에서는 코드를 리뷰하세요. 결정적인 신호는 하나라도 루프의 가능한 앞쪽으로, 끊이지 않게 밀어 넣으세요. 시스템이 신뢰를 얻거나 잃는 데 따라 제약을 의도적으로 조이고 푸세요.

결국 어떤 코드가 배포되는지에 대한 책임은 여전히 사람이 져야 합니다. 출시할 만한 코드는 여전히 그것이 존재해야 하는지를 마음에 두는 사람에게서 시작됩니다.

Edit this page