Requests 3 모금, 비동기 지원 개발, 그리고 오픈소스 커뮤니티의 신뢰와 책임성에 관한 개인적 설명.
[콘텐츠 경고: 이 글의 일부는 가스라이팅이나 다른 형태의 학대를 경험한 분들에게 자극이 될 수 있습니다]
Kenneth Reitz는 유명한 Python 개발자로, Requests 프로젝트를 만든 것으로 가장 잘 알려져 있습니다. 몇 년 전까지만 해도 저는 그와 진지하게 상호작용한 적이 한 번도 없었지만, 그를 높이 평가하고 있었습니다.
저는 그의 디자인 감각과, 사용성과 아름다움에 대한 강조를 좋게 생각했습니다(지금도 그렇습니다). Requests는 소프트웨어 세계의 큰 부분을 떠받치는 핵심 인프라의 일부이고, 그가 이것이 사실은 하나의 "예술 프로젝트"라고 장난스럽게 고집하는 태도는 제 아나키스트적 공감과도 잘 맞았습니다. 저는 그가 자신의 정신 건강 문제를 공개적으로 이야기한 것을 존경했습니다(지금도 존경합니다). 제가 Trio 프로젝트를 시작했을 때, 그 친근함과 접근성을 강조하고 싶어서 그의 "for humans"라는 태그라인을 빌렸고, 문서도 그의 말을 인용하며 시작했습니다.
그러다 저는 requests에 비동기 지원을 추가하는 작업을 시작했습니다.
2017년 8월, 저는 Requests가 사용하는 기반 HTTP 라이브러리인 urllib3에 비동기 지원을 추가하는 작업을 시작했습니다. 이것은 매우 실험적인 작업이었습니다. 역사적으로 최첨단의 상태는 동기 코드용 HTTP 클라이언트 라이브러리 하나, Twisted용 하나, Tornado용 하나, asyncio용 하나, 이런 식이었습니다. 각각은 코드를 공유하지 않는 독립 프로젝트로 유지되어 왔습니다. 모두가 이것이 어리석다는 건 알고 있지만, 고치기는 매우 어렵습니다. HTTP에 대한 깊은 전문성도 필요하고, 이런 서로 다른 네트워킹 접근법 전반에 대한 전문성도 필요하며, 겉보기에는 양립 불가능한 API들을 어떻게든 조화시키기 위한 영리한 아이디어도 필요합니다. 그래서 이전의 모든 시도는 실패했습니다. 그런데 저는 영리한 아이디어가 하나 있다고 생각했고, 그래서 시도해 보았습니다.
Reitz는 이 작업에 큰 관심을 보였습니다. 그는 Requests에서 비동기 지원을 몹시 원하고 있었지만, 제게 말하길 자신은 이런 문제들을 어떻게 해결해야 할지 모르겠다고 했습니다. 우리는 몇 차례 화상 통화와 IRC 대화를 했고, 그는 자신의 유명세를 활용해 자원봉사자들을 모집해 제 쪽으로 보내려 하기도 했습니다. 이것으로 큰 성과가 난 것은 아니었지만, 저와 다른 Trio 기여자들은 계속 작업을 이어 갔습니다.

그러다 2018년 3월 7일, 그는 "Requests 3" 작업이 시작되었다고 발표했고, 그 대표 기능은 제가 작업 중이던 네이티브 async/await 지원이 될 것이며, 이를 실현하기 위해 기부를 받고 있다고 밝혔습니다.
대부분의 오픈소스 프로젝트는 모임 한 번 열기 위한 몇 천 달러를 모으는 데도 애를 먹지만, 이 일은 사람들을 흥분시켰습니다. 그는 개인들과 Microsoft, Google, Slack 같은 대기업들로부터 기부를 쏟아지듯 받았고, 모금 총액은 빠르게 약 30,000달러에 도달했습니다.
2018년 3월 15일, 그는 모금에 대해 이야기하자며 제게 연락해 왔습니다. 그는 이 정도 금액을 가지고 무엇을 해야 할지 확신이 없다고 했습니다. 원래 목표는 그냥 컴퓨터를 사기 위한 5,000달러를 모으는 것이었다는 말도 했습니다. 개인적으로 저는 그 5,000달러짜리 컴퓨터가 Requests와 무슨 관련이 있는지 회의적이었습니다. Requests는 작은 순수 Python 라이브러리입니다. 거기서 작업하려면 값싼 노트북이면 충분합니다. 5,000달러는 강력한 서버나 최상급 게이밍 PC 가격입니다. 하지만 설령 그 돈 중 5,000달러를 관련 없는 컴퓨터에 쓴다 해도, 그건 그의 과거 작업에 대한 보상이라고 볼 수 있고, 그래도 모금에서 그가 약속한 일들을 이행하는 데 약 25,000달러가 남는다고 생각했습니다. 그리고 이것은 분명 대단한 새 무언가를 만들 수 있는 좋은 기회였습니다. 그래서 저는 컴퓨터 얘기는 하지 않았습니다.
대신, 저는 모금과 보조금 경험에서 얻은 일반적인 조언을 해 주었습니다. 신뢰를 유지하려면 투명성이 중요하다는 점을 강조했고, Python Software Foundation(PSF)이나 유사한 비영리 단체와 재정 후원 관계를 맺을 것을 권했습니다. 그리고 그 돈을 효과적으로 쓸 방법을 찾는 데 도움을 주려 했습니다. 예를 들어 저는 이미 풀타임으로 일하고 있었지만, 저를 도와주고 있던 자원봉사자 중 한 명에게 계약 일감을 맡을 수 있는지 물어보기도 했습니다.
이 즈음 그는 우리가 진행 중이던 urllib3 작업으로 몇 가지 실험도 했고, 그 결과 여러 HTTP 요청을 병렬로 보내는 "Requests Core"를 보여 주는 트윗이 나오기도 했습니다. 여기서 "Requests Core"는 그가 포크하고 이름을 바꾼, 우리 작업의 스냅샷이었습니다. 제가 알기로 추가된 것은 기본적인 HTTP/2 지원 정도였지만, 안타깝게도(그리고 사전에 우리가 경고했음에도) 이것은 막다른 접근법을 사용했기 때문에 그 코드는 유용하지 않았습니다.
이 시점까지도 우리 상호작용에는 분명 이상한 점들이 있었습니다. 하지만 사람은 가끔 이상하기도 하니까요. 저는 개인적으로, 실제로 기능을 작업하는 사람들과 먼저 이야기하지도 않고 그 기능을 약속하는 모금을 발표하지는 않았을 겁니다. 그래도 돈을 효과적으로 쓸 방법은 찾을 수 있다고 확신하고 있었습니다. 그의 HTTP/2 코드는 쓸모없었을지 몰라도, 적어도 그는 async/await에 대한 경험은 쌓고 있었습니다. 저는 결국 괜찮게 흘러갈 거라고 생각했습니다.
그 뒤 몇 달 동안 더 이상한 일들이 있었습니다. Requests 유지보수 팀의 서로 다른 구성원들이 그 돈이 어떻게 되고 있는지에 대해 매우 다른 이야기를 들었다고 보고했습니다. 하지만 큰 변화는 2018년 5월 말에 일어났습니다. 제가 UC Berkeley를 떠나 컨설팅을 시작한 때였습니다. 이것은 윈윈의 가능성처럼 보였습니다. 저는 일을 찾고 있었고 프로젝트에도 의욕적이었고, 그는 쓸 방법이 없는 돈을 안고 있었으니까요. 그래서 저는 더 논의해 보자는 이메일을 보냈습니다.
한 달과 여러 차례의 재촉 끝에, 그는 마침내 답장을 했습니다. 그의 핵심 요지는 이랬습니다.
그는 세부 사항을 논의하기 위해 그 주에 통화를 하자고 제안하며 메일을 마쳤습니다.
저는 어리둥절했습니다. 세금은 그런 식으로 작동하지 않습니다. 약속도 그런 식으로 작동하지 않습니다. 새로운 기술 스택은 공짜인데 몇 페이지짜리 문서에는 28,000달러가 든다는 생각은 기이합니다. 새 기능을 구현할 돈이 없는데, 그 이유가 구현할 돈이 없는 그 새 기능을 문서화하는 데 돈을 쓸 예정이기 때문이라는 발상은... 도무지 말이 되지 않았습니다.
그가 그 돈을 Requests를 위해 다른 방식으로 쓸 길을 찾았다면, 저는 전혀 문제 삼지 않았을 겁니다. 저는 그 돈에 대해 어떤 권리도 없었습니다. 하지만 이건 전혀 다른 문제였습니다. 저는 극도로 우려했습니다. 그래도 프로젝트와 커뮤니티를 위해 우리가 얻을 수 있는 최선의 결과를 원했기에, 소통 창구를 열어 두려 했습니다. 저는 통화가 좋은 생각이라는 데 동의했고, 가능한 시간을 제안했습니다. 또한 이번에는 더 강한 어조로, 그가 자신의 평판을 위험에 빠뜨리고 있다는 우려를 밝혔고, 도와주겠다는 제안을 다시 한 번 강조했습니다. 이렇게 적었습니다. "지금은 requests 3가 영영 실현되지 않고, 대중의 인상이 '아 맞다 Kenneth Reitz가 그 돈 훔쳤지'가 되어 버릴 실제 위험이 있다고 생각해요. 저는 이 둘 다 절대 일어나지 않기를 바랍니다. 하지만 바람만으로는 계획이 되지 않죠. 우리에겐 계획이 필요하다고 생각합니다."
이 시점에서 그는 제 이메일에 답장을 그만두었고, 기부 내역과 그 대가로 무엇을 약속했는지 기록되어 있던 모금 페이지를 자신의 웹사이트에서 삭제했습니다(이전 / 이후). 또한 그는 삭제된 페이지에 대한 언급을 지우기 위해 Requests문서와 자신의 블로그(이전 / 이후)도 수정했습니다. 몇 달 뒤에는 원래 URL에 새 페이지를 올려, 모금에 대해 궁금한 점이 있는 사람은 자신에게 개인적으로 연락하라고 요청했습니다.
그 이후 우리의 유일한 접촉은 그가 올해 2월 9일, 아무 맥락 없이 제게 보낸 이메일이었습니다. 그는 제가 전에 했던 말에 아무 답도 하지 않은 채, 저와 자신이 PSF에 공동 보조금 제안서를 쓰자고 제안했습니다. 그가 말한 그 모금이 자금을 대고 있다고 주장하던 바로 그 일을, 제게 돈을 주기 위해서 말입니다. 물론 이것은 애초에 성립할 수 없는 제안이었습니다. PSF가 다른 돈이 어디로 갔는지에 대한 까다로운 질문도 하지 않고 이런 것에 자금을 댈 만큼 순진하다고는 생각하지 않습니다. 그리고 설령 그렇지 않다 해도, 설령 우리가 어떻게든 윤리적 문제를 무시한다 해도, 그는 사실상 우리의 평판을 서로 묶자고 요구한 셈이었습니다. 그래서 그의 모금 처리 방식이 폭발하면, 저도 함께 연루되게 되는 것이니까요. 저는 답장하지 않았습니다.
모든 사람이 오픈소스 프로젝트 모금을 다루는 표준 관행에 익숙한 것은 아닙니다. 그래서 비교를 위해, Python Software Foundation의 Packaging Working Group이 새 PyPI를 위한 자금 조달을 어떻게 처리했는지 설명해 보겠습니다.
이런 외부 보조금을 받는 것이 처음이었기 때문에, 우리는 먼저 무엇을 할지, 누가 할지를 포함한 계획을 세웠고, 계약자로 일할 수 있는 기존 기여자들도 확인했습니다. 그 모든 것이 갖춰진 뒤에야 자금을 신청했습니다.
그 후 돈이 들어왔을 때도, 우리는 그것을 그냥 넘기지 않았습니다. 각 계약자는 자신의 단가와 무엇을 약속하는지 공식적으로 명시하는 몇 단락짜리 문서를 작성했고, 그룹이 이를 검토한 뒤, 이메일로 간단한 투표를 통해 승인했습니다. Working Group 구성원이기도 한 계약자들은 자신들의 제안에 투표하지 않았습니다. 모두가 정기적으로 청구서를 제출했습니다. 그리고 전체 과정은, 커뮤니티가 선출한 PSF 이사회가 최종적으로 감독했습니다.
이것은 꽤 가벼운 절차이고 완벽무결하지도 않지만, 최소한의 투명성과 책임성을 제공합니다. 그리고 PSF는 Python 관련 프로젝트라면 어디에나 이런 서비스를 기꺼이 제공합니다. 예를 들어 Flask와 관련 프로젝트들의 기부도 처리하고 있습니다.
어쩌면 Reitz는 이런 일이 보통 어떻게 처리되는지 단순히 몰랐고, 이 모든 것이 불행하지만 이해할 수 있는 실수였을지도 모릅니다. 하지만 저는 그렇게 보지 않습니다. Reitz가 이 모금을 진행할 당시, 그는 PSF 이사회에 앉아 있었습니다. 또한 Packaging Working Group의 일원으로서, 자신의 모금을 시작하기 몇 달 전에 이루어진 PyPI 자금 조달 투표에도 참여했습니다. 그런데도 제가 이야기하기 전까지는, 제가 대화한 그 어떤 PSF 직원도 그의 모금에 대해 알고 있지 못했습니다.
요컨대 그는 자신이 잘 알고 있던 표준 책임성 장치를 피하는 모금 구조를 선택했습니다. 그는 약속한 것을 전달할 계획도 능력도 애초에 전혀 없었습니다. 그리고 제가 어떻게든 그 일을 해낼 방법을 제안했을 때, 그는 문서 작성이 얼마나 비싼지에 대한 횡설수설만 늘어놓았습니다. 사실상, Requests 3 자금을 어떻게 쓰겠다는 그의 공개 약속은 처음부터 끝까지 거짓말이었고, 그는 이것이 문제라는 점에 대해 어떤 후회도, 심지어 이해조차도 보여 주지 않았습니다.
이런 신뢰 배반은 공동체 전체를 해칩니다. 오픈소스를 위해 돈을 모으는 일은 원래도 충분히 어렵습니다. 이런 일은 그 어려움을 정말로 더 키울 뿐입니다.
그리고 좀 더 개인적인 수준에서, 저는 그와의 상호작용이 극도로 조종적이었다고 느꼈습니다. 저는 그가 저를 착취하려 했고, 자신의 평판을 지키기 위해 자신의 거짓말을 덮는 일에 저를 공모자로 만들려 했다고 느꼈습니다. 저는 이런 일에 동조한다는 생각이 몹시 불편했습니다. 하지만 그는 상황을 그렇게 만들어서, 제가 택할 수 있는 다른 선택지는 비동기 작업 자체를 포기하거나, 아니면 잠재적으로 제게도 큰 대가가 따를 수 있는 이 모든 이야기를 공개하는 것뿐이었습니다.
저는 무엇을 해야 할지 확신이 서지 않아서, 더 많은 맥락을 얻기 위해 조용히 다른 커뮤니티 구성원들에게 연락하기 시작했습니다. 그리고 곧 Reitz의 공개적 평판과는 달리, 그와 직접 일해 본 사람과 이야기할 때마다 모두가 그에 대해 심각한 불편함을 표현한다는 사실을 알게 되었습니다. 많은 사람들에게는 자신들만의 불안한 이야기들도 있었고, 제 경험은 그중에서도 결코 최악이 아니었습니다. 예를 들어 Ian Stapleton Cordasco는 공개적으로 기록에 남겨도 좋다며 이렇게 말했습니다. "이 모든 세월 동안 Kenneth를 상대해야 했던 일 때문에, 저는 이제 거의 Python 오픈소스 소프트웨어 작업을 하지 않게 되었고, 사실상 조용히 커뮤니티를 떠났습니다."
제가 특히 충격적으로 느낀 점 하나가 있습니다. 그의 장기 협업자들에게 제 경험을 이야기할 때마다, 그들은 즉시 제가 미쳐 가는 게 아니라고 안심시켜 주려 했습니다. 그러니까... 물론 저는 그 지지에 감사했습니다. 하지만 이것이 처음 있는 일이 아니라는 점도 분명했습니다. 사람들은 Reitz와 함께 일하기 시작하고 나면, 언제나 자기 자신의 인식을 믿어도 된다는 안심이 필요했던 모양입니다. 그의 협업자들은 이런 일을 너무 오래 해 와서, 이게 정상처럼 느껴지는 것 같았습니다. 하지만 이것은 정상이 아닙니다.
이것은 전형적인 "missing stair" 문제입니다. 안쪽 집단에 있는 사람들은 문제적인 사람을 조용히 피해 갑니다. 바깥 사람들은 아무것도 모른 채 들어옵니다. 저는 Python 세계에서 꽤 연결이 많은 편인데도, 아무것도 모른 채 들어갔습니다. 돌이켜 보면 몇몇 경고 신호가 보입니다. auteur 지위를 고집하던 태도는 이제 와서 보니 매력적인 기벽이라기보다, 책임은 부정하면서 공로와 권력을 주장하기 위한 계산된 허세처럼 보입니다. "긍정성"을 고집하는 태도는 책임을 회피하려는 사람들이 흔히 쓰는 전술입니다. 하지만 그는 저를 속였습니다.
제가 자꾸 떠올리게 되는 일이 하나 있습니다. Requests의 비동기 지원에 대해 그와 처음 이야기했을 때, 모금보다 몇 달 전이었는데, 그는 이상한 말을 했습니다. 자신은 이것을 구현하는 데 전적으로 저에게 의존하고 있으니, 만약 제가 Requests가 AsyncIO(더 잘 알려진 경쟁자) 대신 Trio(제 라이브러리)를 기본값으로 사용하라고 요구한다면, 그는 달리 선택의 여지가 없어 따를 수밖에 없다는 것이었습니다. 저는 그 이야기를 꺼낸 것 자체가 믿기 어려울 정도로 이상하게 느껴졌습니다. 거의 마치 저더러 자신을 조종하라고 요청하는 것 같았습니다. 당시 저는 협박이 아니라 실력으로 성공하고 싶다는 식으로 얼버무렸고, 아예 기본값을 정하지 말라고 권했습니다. 돌이켜 보면, 사기꾼들이 종종 피해자에게 사소한 비윤리적 행위를 먼저 유도해서, 사기가 커질수록 빠져나오지 못하게 만드는 방식이 떠오릅니다.
그의 협업자들은 또한 그가 무엇을 하든 늘 그의 양극성 장애를 변명으로 들었습니다. 저는 이것이 Reitz에게도, 정신 건강 문제로 고생하는 모든 사람에게도 매우 불공정하다고 생각합니다. 질병이 누군가가 타인에게 가하는 해악이나, 자신의 행동에 대한 책임을 지워 버리지는 않습니다. 많은 사람들은 이런 해를 끼치지 않고도 자신의 상태를 관리하며, 실수했을 때는 우리 모두처럼 수습하고 사과합니다. 누군가가 그렇게 할 수 없다면, 공동체로서 우리는 연민을 가질 수는 있어도 그 사람에게 권력과 영향력을 주어서는 안 됩니다.
많은 사람들이 Reitz가 실제로 Requests 개발과 얼마나 적게 관련되어 있는지 깨닫지 못하는 것 같습니다. 실제 유지보수는 이미 수년 동안 거의 전적으로 다른 자원봉사자들이 해 왔습니다. PyPI의 유지보수자 목록을 보면, 그는 자기 프로젝트에 대한 PyPI 권한도 없습니다. 자꾸 문제를 일으켰기 때문에 실제 유지보수자들이 그의 접근 권한을 회수하자고 강하게 주장했기 때문입니다. Requests git 저장소를 클론한 뒤 git log requests/를 실행하면, 누가 라이브러리의 소스 코드를 변경했는지의 전체 목록을 볼 수 있습니다. 직접 변경했든, 다른 사람의 pull request를 병합했든 말입니다. Reitz가 둘 중 어느 쪽이든 마지막으로 한 것은 2017년 5월이었고, 그때 그는 공백 문자를 정리하는 몇 가지 수정을 했습니다.
적어도 커밋 기준으로 보면, 그 이후 그의 주된 기여는 작은 문서 수정 몇 건을 병합하고, 기부 링크, 광고, 눈에 거슬리는 스폰서 링크 등을 추가해 프로젝트를 수익화하는 일로 보입니다. 이 돈은 모두 프로젝트 유지보수자들이 아니라, 그의 주머니로 직접 들어갑니다.
저는 또한 그가 Requests를 위한 프리미엄 지원 계약을 판매한 전력이 있다는 사실도 알게 되었습니다. 돈은 그가 받았고, 실제 작업은 무급 자원봉사자들에게 떠넘겼습니다.
저는 오픈소스로 돈을 벌려는 시도 자체에는 반대하지 않습니다. 저는 이전에도 오픈소스가 충분한 투자를 거의 받지 못한다고 쓴 적이 있습니다. 제가 반대하는 것은 자원봉사자를 착취하고, 커뮤니티 구성원들을 밀어내고, 후원자와 더 넓은 공동체에게 거짓말하는 일입니다. Reitz는 이 모든 일을 해 온 일관된 이력을 가지고 있습니다.
저는 여기서 무엇을 해야 할지 오랫동안 고민했습니다. 지난해부터 저는 이 일에 대해 사람들에게 말할 때 매우 조심하려 애썼습니다. 거짓 소문을 퍼뜨리거나 인터넷 군중심리를 부추기고 싶지 않았기 때문입니다. (이 때문에 우리는 urllib3의 비동기 지원 작업에 대해서도 조용히 있어야 했고, 저 자신이 그 작업을 하기도 매우 어려워졌습니다.) 그리고 이것을 공개했을 때 그것이 제 평판과 정신 건강에 어떤 영향을 줄지 두렵기도 합니다.
결국 저는 Python 커뮤니티와 그 구성원들을 깊이 아끼기 때문에, 목소리를 내기로 결정했습니다. 우리 커뮤니티에서 가장 두드러진 인물 중 하나가 후원자들에게 거리낌 없이 거짓말하고 자원봉사자들에게 해를 끼치는데도, 우리가 모두 아무 말 없이 넘어간다면, 그건 우리가 함께 쌓아 올린 모든 것을 위험에 빠뜨립니다. 그리고 저는 많은 사람들보다 이 문제를 말할 수 있는 더 나은 위치에 있습니다.
그렇다면 이제 무슨 일이 일어날까요?
여기는 인터넷이므로, 저는 이것을 명시적으로 말해야 합니다. Reitz를 괴롭히거나 학대하지 말아 주세요. 그런 일은 결코 적절하지 않습니다. (그리고 도덕적 주장이 설득력이 없는 유형의 사람이라면, 이렇게 생각해 보세요. 그는 분명 관심을 원하고 있습니다.)
저는 Reitz가 자신이 모금한 돈과 그것이 어떻게 쓰였는지에 대해 공개적으로 설명할 것을 요구합니다.
또한 저는 Requests 프로젝트 유지보수자들이, 프로젝트를 더 정상적이고 덜 기능장애적인 거버넌스 모델로 전환할 것을 촉구합니다. 그의 기여를 인정하는 것과, 그의 개인적 신화를 사들이는 것은 별개의 일입니다. 그의 통찰은 대체 불가능하지 않습니다. 여러분은 이 상황이 자신들과 사용자들에게 해를 끼치고 있다는 것을 알고 있습니다. 여러분과 여러분의 사용자는 그의 자아보다 더 중요합니다.
그 외에는, 저는 제 자신의 작업에 집중할 생각입니다. 저는 더 이상 Reitz를 그의 행동의 결과로부터 보호하기 위해 비밀을 지키지 않을 것입니다. 이제 다음에 무슨 일이 일어날지는 그와 더 큰 Python 커뮤니티에 달려 있습니다.
누구든 들어 줄 사람이 필요하다면, 저는 njs@pobox.com으로 연락받을 수 있습니다. 이번 주말 PyCon에서도 만날 수 있습니다.