Pi를 사용해 Pi를 개발하면서, 오픈 소스 이슈 트래커에 유입되는 LLM 보조 이슈와 코드, 유지보수 부담, 그리고 올바른 협업의 가치에 대해 돌아본 글.
written on 2026년 5월 24일
Pi는 이제 Earendil의 일부이지만, 중요한 의미에서는 여전히 Mario의 프로젝트다. 그는 나보다 더 오래 그 이슈 트래커와 함께 살아왔고, 오픈 소스 프로젝트에서 나타나는 새로운 형태의 에이전트 트래픽이 얼마나 이상해질 수 있는지도 더 오래 겪어왔다. 이 글은 대체로 내가 트래커에서 더 많은 시간을 보내고, Pi로 Pi를 작업하고, 그 과정에서 지금까지 배운 것을 지켜본 뒤의 개인적인 소회다.
놀랍지 않게도, 우리는 Pi를 만들기 위해 Pi를 사용하고 있다. 귀여운 도그푸딩처럼 들릴 수 있지만, 우리가 무엇을 하는지 이해하는 데 정말 도움이 된다. 에이전트와 함께 개발할 때 나타나는 흥미로운 효과 하나는 이슈 트래커의 역할이 아주 조금 바뀐다는 점이다. 이슈 설명은 더 이상 단순히 사용자에서 유지보수자에게 보내는 메시지가 아니다. 우리는 그것을 Pi 세션의 프롬프트 입력으로도 사용한다. 내가 내 clanker1에게 건네며 이렇게 말할 수 있는 것이다. “이걸 이해하고, 재현하고, 코드를 살펴보고, 수정안을 제안해.”
이 말은 곧 이슈의 형태가 새로운 방식으로 중요해졌다는 뜻이다. 나쁜 이슈는 예전에도 늘 성가셨지만, 적어도 많은 이슈는 그냥 모호한 정도였다. 이제 우리는 5%는 인간이고 95%는 clanker가 생성했으며 대체로 부정확한 헛소리로 이루어진 이슈 부류도 상대하고 있다. 그럴듯하지만 틀린 진단이 담긴 나쁜 이슈는 추가 작업을 만들어낸다.
지금 가장 짜증 나는 실패 양상은 사람들이 자기 목소리로 쓰지 않은 이슈를 제출한다는 점이다. 어딘가에 관찰된 문제가 들어 있긴 한데, 그걸 clanker에 던져 넣었고 clanker가 다시 써서 완전히 엉망으로 만들어 놓는다. 대개 프롬프트를 너무 형편없이 줬기 때문에, 거기서 나온 결론은 틀릴 때가 더 많으면서도 언제나 자신감만 넘친다. 그 결과 근본 원인에 대한 완전한 추측, 가짜 최소 재현 사례, 제안된 구현 전략, 인접하지만 종종 잘못된 코드에 대한 비유, 그리고 중요할 수도 있고 아닐 수도 있는 오류 종류의 긴 목록이 생겨난다.
그건 진단이 아예 없는 것보다 더 나쁘다.
특정 이슈를 지목하고 싶지는 않다. 누구를 험담하고 싶은 마음은 정말 없기 때문이다. 하지만 분명히 짜증 나는 일이다. 또 내가 그 이슈를 Pi에 넘기면 Pi도 그 잘못된 진단을 보게 된다는 점에서 더욱 답답하다. Pi는 이슈 본문을 소문처럼 다루지 않는다. 증거처럼 다룬다. 문체는 자신만만하고 코드 참조도 그럴듯해 보이기 때문에, 이슈가 이미 준비해 둔 길을 기꺼이 따라가 버린다. 우리는 /is라는 커스텀 슬래시 명령을 쓰는데, 거기에는 특히 이런 지시가 들어 있다.
이슈에 적힌 분석을 믿지 마라. 동작을 독립적으로 검증하고 코드와 실행 경로에서 직접 분석을 도출하라.
불행히도 이것도 완전히는 먹히지 않는다. 인간이 먼저 자기 이슈를 clanker 분쇄기에 한 번 돌려 버리면, 그들의 clanker는 거의 즉시 범위를 확장해 버리기 때문이다. 원래는 매우 좁고 사실 기반이던 버그 관찰이, 가설로 가득한 훨씬 넓은 표면으로 바뀌어 버린다. 그래서 적어도 나는 점점 더 이슈 리포트가 인간이 실제로 관찰한 것만으로 압축되기를 원하게 된다.
그 정도면 충분하다. 문제를 이해하려고 LLM을 사용했다면 좋다. 아마 후속 댓글로 남기면 될 것이다. 하지만 이슈와 이슈 본문은 당신이 책임질 수 있는 것이어야 한다. 근본 원인을 모른다면, 모른다고 말하면 된다. 나도 clanker를 다룰 수 있고, 당신의 허접한 결과물을 쓰느니 차라리 이 작업은 내가 직접 하고 싶다. 재현 사례가 추측이라면, 추측이라고 말하면 된다. 확실한 사실이 스택 트레이스 하나뿐이라면, 그 스택 트레이스를 주고 거기서 멈추면 된다.
허접한 내용으로 가득 찬 이슈를 보게 되는 것은 그저 오늘날 이 기계들의 품질이 그런 수준이기 때문이다. 안타깝게도 좋은 이슈를 만들지 못하는 그들의 실패는 생성된 코드의 많은 부분으로도 이어진다. 전부는 아니지만, 상당수의 코드가 그렇다. 나는 계속해서 이들이 이슈와 구현을 필요 이상으로 과하게 설계하는 모습을 마주친다.
예를 들어 “이 잘못된 세션 로그 때문에 리더가 크래시 난다”고 말하면, clanker는 종종 관대한 리더를 추가한다. 그러고는 폴백을 넣고, 아마 마이그레이션도 넣고, 디버그 출력도 더하고, 이 모든 것에 대한 테스트까지 붙인다. 각각 따로 떼어 놓고 보면 꼭 틀린 것은 아닐 수 있다. 하지만 시스템 전체로 보면 잘못된 선택일 수 있다.
Pi의 핵심에는 반드시 지켜져야 하는 불변 조건을 가진 꽤 잘 설계된 세션 로그가 있다. 오늘날 clanker의 동작은 그런 불변 조건이 존재하지 않는다고 그냥 가정하고, 대신 온갖 종류의 잘못된 상태를 시스템이 처리하도록 만들어 버리며, 그 과정에서 복잡도를 폭발시킨다.
거의 언제나 올바른 수정은 나쁜 상태를 처리하는 것이 아니라, 나쁜 상태가 불가능하도록 만드는 것이다. 이것은 Pi 세션 로그처럼 영속화된 데이터에서 특히 중요하다. 그것들은 열리고, 분기되고, 압축되고, 내보내지고, 공유되고, 분석된다. 여기서의 목표는 나쁜 세션 데이터를 절대 쓰지 않는 것이다. 그런데 clanker를 마음대로 돌아다니게 두면, 세션 로그 안의 모든 나쁜 데이터 사례를 더 관대한 리더로 처리하려 들 것이다.
나는 이 점에 대해 이미 충분히 불평해 왔지만, Pi 코드베이스를 작업할수록 그 요점이 계속 강화된다. 이것이 바로 LLM이 작성한 코드가 그렇게 많은 불필요한 복잡성을 키우는 방식 가운데 하나다. 이 모든 모델은 국소적인 실패를 보고 국소적으로 방어하려 한다. 유지보수자인 우리는 대화를 계속 전역 불변 조건으로 되돌려 놓아야 하는데, 그건 필요 이상으로 어렵고, 무척 고된 일이다.
그리고 양의 문제도 있다. 트래커에는 많은 이슈와 PR이 들어오고 있고, 그중 상당수는 명백히 LLM의 도움을 받았다. 괜찮은 것도 있지만, 뛰어난 것은 하나도 없고, 대부분은 그냥 나쁘다. 전체 처리량 자체가 이미 유지보수 문제다.
아는 사람도 있겠지만, Pi의 이슈 트래커는 신규 기여자가 올린 모든 이슈와 풀 리퀘스트를 자동으로 닫도록 되어 있고, 그중 일부를 다시 열거나 특정 개인을 승인할지에 대한 수동 절차가 있다. 그래서 자동 닫힘 -> 재오픈 -> 다시 닫힘 같은 흐름은 우리에게 흥미로운 통계다.
이 글을 쓰는 동안 지난 90일간의 공개 GitHub 트래커 데이터를 뽑아 봤다. Earendil 멤버를 제외하면 외부 이슈와 풀 리퀘스트는 3,145건이었다. 그중 2,504건은 승인되지 않은 사용자가 올렸기 때문에 자동으로 닫혔다. 그중 17%는 다시 열렸지만, 이 숫자는 이슈를 다소 과소 집계한다. 일부는 우리가 여전히 고치고 있어도 닫힌 상태로 남아 있기 때문이다. 메인 브랜치 커밋이나 머지된 풀 리퀘스트에서 참조된 이슈까지 포함하면 그 수치는 26%까지 올라간다. 풀 리퀘스트 쪽은 더 나쁘다. 자동으로 닫힌 PR 714건 가운데 최종적으로 머지된 것은 60건으로, 약 8%다.
![]()
많은 이슈와 PR은 완전한 허접함 그 자체이고, 어떤 경우에는 인간이 자기가 그런 것을 만들었다는 사실조차 인식하지 못했다. 저품질 스팸의 출처로는 OpenClaw 인스턴스도 있고, 사람들이 자기 컨텍스트에 넣어 두는 일부 스킬도 있는데, 그것들이 이슈 생성을 부추기는 것처럼 보인다.
GitHub는 분명 이런 새로운 형태의 오픈 소스를 다루도록 만들어진 것이 아니다. 하지만 나는 점점 이 경험을 고통스럽게 만드는 책임을 GitHub보다 그 과정에 관여한 사람들에게 더 돌리게 된다. 당신의 clanker가 남의 이슈 트래커에 똥을 싸면, 그건 GitHub의 잘못이 아니라 오롯이 당신 잘못이다.
Pi는 Pi로 만들어질지 몰라도, 오늘 우리는 Bun과 OpenClaw가 이미 가 있는 지점, 즉 완전히 분리된 자동화 소프트웨어 엔지니어링과는 아직 꽤 거리가 있다. 언젠가 그 지점에 도달할지도 모른다. 나도 모르겠다. 하지만 오늘 보기에는 우리가 다크 팩토리를 어떻게 구현할지 아직 아는 것 같지도 않고, 솔직히 아직 그럴 의지도 없다. 그렇다고 해도 꽤 많은 병렬 작업이 이뤄지고 있고, 그 대부분은 이슈 재현을 위한 것이다.
우리가 이를 위해 쓰는 작은 구성은 Pi 저장소에 커밋된 자체 .pi 폴더 안의 세 가지 작은 조각이다. /is(analyze issue)는 GitHub 이슈 분석용 프롬프트다. 이 명령은 이슈에 라벨을 붙이고 담당자를 지정하며, 전체 스레드와 링크를 읽고, 그런 다음 에이전트에게 이슈 안의 분석을 믿지 말고 코드에서 스스로 진단을 도출하라고 명시적으로 지시한다. 그다음 확장 하나가 prompt-url-widget을 추가하는데, 이것은 에이전트가 시작되기 전에 프롬프트를 감시하다가 /is(또는 PR용 동등 명령)가 프롬프트에 넣은 GitHub 이슈나 PR URL을 인식하고, gh로 제목과 작성자를 가져와 작은 UI 위젯에 렌더링하고 세션 이름을 바꾼다. 또한 세션 시작이나 세션 전환 시 그 상태를 다시 구성하므로, 예전 조사 세션을 다시 열어도 창은 여전히 그 세션이 어느 이슈에 속하는지 개발자에게 알려 준다.
실제로 이것이 뜻하는 바는, 서로 다른 이슈에 대해 /is를 실행하는 여러 Pi 창을 열어 둘 수 있고, UI가 각 조사 작업을 시각적으로 구분해 주는 동안 에이전트들은 각자 독립적으로 재현과 코드 읽기를 수행할 수 있다는 것이다. 조사가 끝나면 그것들을 순차적으로 처리하면 된다. 마지막 마무리를 위해 /wr(wrap it up)은 이에 대응하는 정리용 프롬프트다. 이것은 세션에서 GitHub 컨텍스트를 추론하고, 변경 로그를 갱신하고, 면책 문구가 포함된 최종 이슈 댓글을 초안 작성하거나 게시하고, 그 세션에서 변경된 파일만 커밋하고, 이슈가 정확히 하나일 때는 적절한 closes #...를 추가하고, main에서 푸시한다.

아마 이미 눈치챘겠지만, AI 이후의 세계에서 오픈 소스는 이상한 새로운 압박을 받고 있다. 우리는 더 많은 코드, 더 많은 프로젝트, 더 많은 이슈를 받고 있다. 실제 사용자는 없거나 잠시 한 사람만 쓰는 프로젝트가 등장하고, 수천 개의 스타를 받은 프로젝트조차 수명이 몇 주에 불과할 수 있다.
우리에게 Pi의 하니스 계층을 신중하게 유지보수할 가치가 있는 이유는 그것이 어려운 조정 문제를 해결하고, 우리와 다른 이들이 그 위에 구축할 수 있는 플랫폼을 만들기 때문이다. 또한 우리는 조정과 협력이 우리 모두를 끌어올린다는 사실을 알고 있다. 많은 경우 올바른 답은 문제를 로컬에서 우회하는 것이 아니라, 업스트림 동작을 올바르게 만드는 것이다. Mario는 Pi가 설정이 잘못된 모든 게이트웨이를 얼버무리며 덮어쓰도록 만드는 일을 매우 잘 거부해 왔고, 우리도 그 규율을 지키려 하고 있다. 게이트웨이가 올바르게 동작하면 모두가 이익을 본다.
안타깝게도 이런 유형의 사고방식은 빠르게 사라지고 있다. 이 기계들이 로컬 우회를 아주 싸게 만들어 주기 때문에, 코드는 모든 오동작에 대한 로컬 방어를 계속 축적한다. 어느 곳에 수정이 들어가야 하는지를 두고 인간이 인간과 대화하는 대신, 한 인간과 한 기계가 고립된 채 그 문제를 우회해 버린다.
AI가 소프트웨어를 필요로 하는 사람 수를 늘린 것도 아니고, 그것을 리뷰할 수 있는 유지보수자 수를 늘린 것도 아니라는 점을 기억하라. AI는 주로 코드의 양과 관심을 두고 경쟁하는 프로젝트 수를 늘렸을 뿐이다. 그중 일부는 건강한 현상이지만, 많은 부분은 원래 공유되어야 할 노력을 분절시킨다.
우리는 더 약한 토대가 아니라 더 강한 토대가 필요하다. 오픈 소스에는 기계와 함께하는 더 많은 고립된 작업이 아니라, 더 많은 협업이 필요하다. 인간 사이의 소통은 어렵고, 혼자 clanker와 앉아 있을 수 있을 때 그것을 피하고 싶어지는 유혹도 크다. 하지만 고립은 오픈 소스가 가치를 얻는 장소가 아니다. 그 가치는 공동체와, 프로젝트가 원래 창작자를 넘어 살아남을 수 있게 하는 구조에서 나온다.
이 글에는 ai, open-source, pi 태그가 붙어 있다.