오픈 소스 開發(개발) 近況(근황)

어쩌다 보니 最近(최근) 꽤 많은 오픈 소스 프로젝트를 만들게 되어서、近況(근황) 報告(보고) () 進行中(진행중)인 오픈 소스 프로젝트들을 글로 整理(정리)해 본다。() 프로젝트들은 어떤 ()으로든 서로 關係(관계)가 있다。

Hollo

事實(사실) 最近(최근) 내가 만들게 된 오픈 소스 프로젝트들의 始發點(시발점)이 되는 게 바로 이 프로젝트이다。Elon Musk가 Twitter를 사들이고 이름을 X로 바꾸고 나서부터 元來(원래)부터 쓰던 Mastodon을 더욱 熱心(열심)히 쓰게 되었는데、國漢文混用體(국한문 혼용체)로 글을 쓰다 보니 사람들이 읽기 不便(불편)하지 않을까 눈치를 보게 되었다。그래서 Seonbi利用(이용)하여 國漢文混用體(국한문 혼용체)를 한글專用體(전용체)로 바꿔주는 機能(기능)을 Mastodon에 넣을까도 생각했으나… 나 말고는 아무도 쓸 것 같지 않은 이 機能(기능)을 Mastodon 업스트림에 넣는 것은 애()無理(무리)。그러면 다운스트림 패치를 維持(유지)하며 Mastodon 서버도 스스로 運營(운영)해야만 한다는 소리인데、Mastodon이 워낙 무겁기로 有名(유명)해서 그러고 싶지가 않았다。그래서 自家用(자가용) 輕量(경량) ActivityPub 具顯(구현)을 만들고자 한 게 바로 Hollo이다。혼자 쓰는 ActivityPub 서버 소프트웨어라서 홀로라고 이름 지었다。

개밥 먹기(dogfooding)에 成功(성공)하여 現在(현재)는 내 聯合宇宙(연합우주)(fediverse) 어카운트를 Hollo로 옮겼다。聯合宇宙(연합우주) 핸들은 @hongminhee@hollo.social國漢文混用體(국한문 혼용체)로 마음껏 글을 쓰고 있으며、漢字(한자) 위에 한글 讀音(독음)<ruby> 태그로 달린다。

()은 개밥 먹기를 達成(달성)以後(이후)로는 내게 切實(절실)機能(기능)은 모두 具顯(구현)되어서 버그 修正(수정) () 維持補修(유지보수) 爲主(위주)로만 하고 있다。

Fedify

앞서 이야기한 Hollo를 처음 具顯(구현)할 때는 ActivityPub 具顯(구현)을 바닥부터 하려고 試圖(시도)했었다。그런데 만들다 보니 ActivityPub 具顯(구현) 코드가 생각보다 두껍고 할 게 많다는 생각이 들었다。그래서 Hollo를 만들던 것을 中斷(중단)하고 ActivityPub 서버 프레임워크를 만들게 된 게 Fedify이다。만들고 나서 半年(반년)이 채 안됐을 때 Ghost로부터 資金(자금) 支援(지원)을 받게 되었고、그 뒤로 한 동안 專業(전업)으로 Fedify 프로젝트를 하게 되기도 했다。現在(현재)情報通信産業振興院(정보통신산업진흥원)(NIPA) 傘下(산하) 오픈 소스 소프트웨어 統合(통합) 支援(지원) 센터에서 主催(주최)하는 오픈 소스 컨트리뷰션 아카데미(OSSCA)의 參與型(참여형) 프로젝트로 選定(선정)되어 훌륭한 멘티 분들과 함께 프로젝트를 進行(진행)하고 있다。

Fedify 以前(이전)에도 ActivityPub 서버 프레임워크가 없었던 것은 아니다。하지만 어떤 것도 내가 必要(필요)로 하는 抽象化(추상화) 水準(수준)提供(제공)하지 않았다。어떤 것들은 WebFinger나 署名(서명) 알고리즘 程度(정도)提供(제공)하는 작은 라이브러리에 가깝고、또 어떤 것들은 거의 Mastodon과도 比較(비교)할 수 있는、프레임워크라기 보다는 完成(완성)된 소셜 미디어 플랫폼 구현에 가까웠다。譬喩(비유)하자면 HTTP 라이브러리나 WordPress 같은 CMS는 있어도、Rails나 Django에 가까운 프레임워크를 없었던 것이다。

Fedify를 만들 때 念頭(염두)에 둔 目標(목표)以下(이하)와 같다。

  1. 可及的(가급적) 많은 開發者(개발자)들이 쓸 수 있게 한다。
  2. 데이터베이스나 스토리지에 無關(무관)(agnostic)해야 한다。애플리케이션 開發者(개발자)가 쓰고 싶은 데이터베이스를 쓸 수 있어야 한다。
  3. ActivityPub 프로토콜을 活用(활용)하는 方式(방식)制約(제약)이 없어야 한다。이를테면 마이크로블로그 같은 完成(완성)된 애플리케이션의 形態(형태)前提(전제)하지 않는다。
  4. ActivityPub을 具顯(구현)한다면 갖추어야 하는 모든 것들—認證(인증)署名(서명)發信函(발신함)(outbox) 및 受信函(수신함)(inbox) 待機列(대기열) ()一切(일절)提供(제공)한다。
  5. ActivityPub을 잘 모르는 사람도 쓸 수 있을 만큼 豐富(풍부)文書化(문서화)提供(제공)한다。
  6. 타입 安全(안전)해야 한다。

그리고 이 글을 쓰는 現在(현재)以上(이상)目標(목표)는 거진 이룬 것 같다。結果的(결과적)으로 Hollo는 Fedify 基盤(기반)으로 만들어지게 되었고、그 ()에도 (아래서 다룰) Hackers’ Pub、Ghost ()이 Fedify를 써서 ActivityPub을 具顯(구현)하게 되었다。또한、아직 完成(완성)되지는 않았지만 KosmoCosmoslide ()의 프로젝트가 Fedify를 利用(이용)해 ActivityPub을 具顯(구현)하고 있다。

LogTape

Fedify에 로그 體系(체계)追加(추가)하려고 JavaScript로 만들어진 로그 라이브러리를 찾아보았으나 내가 ()하는 條件(조건)의 라이브러리가 없어서 새롭게 만들게 된 것이 LogTape이다。

내가 ()하는 條件(조건)이라는 것도 크게 대단치도 않은 것이었다。그저 Python 표준 라이브러리의 logging 모듈에 該當(해당)하는 것을 찾은 것인데、돌이켜 생각해 보니 logging 모듈이 꽤 잘 만든 物件(물건)이었던 것 같기도 하다。내가 바라는 條件(조건)은 다음과 같았다。

  1. 라이브러리에서 로그를 남기되、애플리케이션에서 라이브러리의 로그 出力(출력)制御(제어)할 수 있어야 한다。애플리케이션에서 出力(출력) 設定(설정)을 따로 하지 않는 ()、라이브러리의 로그는 어디에도 出力(출력)되어서는 안 된다。
  2. 로거가 階層的(계층적)으로 管理(관리)되어야 한다。上位(상위) 로거에 設置(설치)出力處(출력처)(sink)는 下位(하위) 로거에도 適用(적용)되어야 한다。
  3. 出力處(출력처)具顯(구현)하기 쉬운 인터페이스여야 한다。
  4. 타입 安全(안전)해야 한다。
  5. Node.js、Deno、Bun、에지 函數(함수)(edge functions)、웹 브라우저 () 多樣(다양)한 JavaScript 런타임에서 두루 動作(동작)해야 한다。

大體(대체)로 애플리케이션이 아니라 라이브러리에서 로그를 남기기 ()必要(필요)條件(조건)들이었다。於此彼(어차피) Fedify에 쓸려고 만든 것이기 때문에、만들어 놓고 放置(방치)하고 있었는데 昨年(작년) 가을 지나서부터 어쩌다 입所聞(소문)이 나서 사람들이 많이 쓰게 되었다。

Hackers’ Pub

소프트웨어 開發(개발)關聯(관련)된 글들을 올릴 블로그를 만들고 싶어서 velog를 조금 쓰게 되었는데、ActivityPub을 支援(지원)하지 않는 게 아쉬워서 velog 이슈트래커에 이슈를 남기게 되었다。多幸(다행)스럽게도 肯定的(긍정적)으로 檢討(검토)하겠다는 答辯(답변)을 받긴 했지만、製作陣(제작진) 분들이 바쁘셔서 그 以後(이후)消息(소식)이 없었다。結局(결국) 내가 스스로 ActivityPub을 支援(지원)하는 소프트웨어 開發者(개발자)들을 ()한 소셜 미디어 및 블로그 플랫폼을 만들어보자고 생각한 게 Hackers’ Pub이다。

昨年(작년) 겨울에 첫 開場(개장)을 하고서 얼마 되지 않아 李在烈(이재열) 님께서 加入(가입)하셨는데、招待制(초대제)임에도 不拘(불구)하고 李在烈(이재열) 님께서 이곳저곳에서 엄청나게 熱情的(열정적)으로 Hackers’ Pub 弘報(홍보)를 해 주신 德分(덕분)相當(상당)히 많은 분들께서 加入(가입)하여 活動(활동)하시게 되었다。短期的(단기적) 目標(목표)韓國(한국)에서 널리 쓰이게 되는 것이고、나아가 中長期的(중장기적) 目標(목표)()아시아 全般(전반)英語圈(영어권)을 아우르는 것이다。하지만 아직은 大部分(대부분)의 콘텐츠가 韓國語(한국어)로 되어 있으며、少數(소수)日本人(일본인) 분들이 間歇的(간헐적)으로 日本語(일본어) 콘텐츠를 올려 주시는 程度(정도)이다。

Fedify를 ()해 ActivityPub을 具顯(구현)했으므로 當然(당연)히 Hollo、Mastodon、Misskey ()疏通(소통)可能(가능)하며、X처럼 短文(단문)(Note)을 쓸 수도 있고 긴 揭示(게시)글(Article)을 쓸 수도 있다。繪文字(에모지) 反應(반응)이나 引用(인용)처럼 Mastodon에는 없는 機能(기능)提供(제공)하고 있다。

그리고 Hackers’ Pub의 또 하나의 자랑거리는 安全(안전)하고 平等(평등)共同體(공동체)를 이루기 ()行動(행동) 綱領(강령)이다。()히 내가 가장 좋아하는 句節(구절)은 다음과 같다。

差別(차별)嫌惡(혐오)對抗(대항)하는 發言(발언)과、差別(차별)嫌惡(혐오) 自體(자체)同一線上(동일선상)에 두지 않습니다。

技術的(기술적) 側面(측면)에서는、元來(원래)DenoFresh利用(이용)해서 만들었었으나、現在(현재)는 웹 프런트엔드 開發(개발)造詣(조예)가 깊으신 申義河(신의하) 님의 도움을 받아 GraphQLSolidStart 基盤(기반)으로 移住(이주)하고 있다。1

소스 코드는 AGPL 3.0으로 GitHub公開(공개)되어 있다。實際(실제)로 꽤 많은 Hackers’ Pub 會員(회원)들께서 不便(불편)()을 스스로 고치는 풀 리퀘스트를 보내주고 계신다。

參考(참고)로 내 Hackers’ Pub 어카운트는 @hongminhee@hackers.pub이다。

Upyo

Hackers’ Pub을 만들면서 이메일을 發送(발송)할 일이 생겼는데、이메일 提供(제공) 業體(업체)를 쉽게 交替(교체)할 수 있는 이메일 發送(발송) 라이브러리를 찾다가 마음에 드는 게 없어서 만들게 된 게 Upyo이다。이름에서 알 수 있는 것처럼、韓國語(한국어) 單語(단어) 郵票(우표)에서 이름을 따 왔다。

元來(원래)는 .NET 쪽의 FluentEmail 같은 걸 JavaScript 生態系(생태계)에서 찾고 있었는데、意外(의외)로 마땅한 게 없어서 놀랐다。이메일 提供(제공) 業體(업체)交替(교체)하거나 多重化(다중화)하는 일이 생각보다 잘 없는 걸까?

LLM 基盤(기반)의 코딩 에이전트2本格的(본격적)으로 써 본 첫 프로젝트이기도 했다。그럼에도 아직 LLM의 力量(역량)期待(기대)가 그렇게 높지 않은 탓에、設計(설계)初盤(초반) 코딩은 스스로 했고、나중에 트랜스포트(transport)의 種類(종류)를 늘릴 때 LLM의 도움을 많이 받았다。만드는 데에 이틀 걸렸던 것 같다。코딩 에이전트의 놀라운 生產性(생산성)印象(인상) 깊었다。

내가 만든 다른 라이브러리들과 마찬가지로 Node.js、Deno、Bun、에지 函數(함수)、웹 브라우저 () 多樣(다양)한 JavaScript 런타임을 지원하는 것도 特徵(특징)이다。

Optique

Fedify는 프레임워크이기도 하지만 fedify 命令(명령)이라는 CLI 道具(도구)提供(제공)하는데、旣存(기존)에는 Deno 專用(전용) CLI 프레임워크인 Cliffy를 그럭저럭 잘 쓰고 있었으나、Deno 以外(이외)에 Node.js、Bun ()支援(지원)해야 하게 되면서3 Cliffy의 代案(대안)을 찾게 되었다。그런데 이()에도 비슷한 패턴으로… 마음에 드는 걸 찾지 못했다。

事實(사실) 내 마음속에는 이미 理想(이상)에 가까운 CLI 파서 라이브러리가 存在(존재)하긴 했다。다만 그게 optparse-applicative라는 Haskell 라이브러리였기 때문에 Fedify에서는 쓸 수 없었을 뿐이다。이 optparse-applicative라는 라이브러리의 아이디어는 單純(단순)하다。CLI 파서도 파서이니 파서 컴비네이터(parser combinators)로 만들자는 것이다。

아무튼、()하는 CLI 파서 라이브러리를 찾지 못했으니 스스로 만들 수밖에。그래서 만든 게 Optique이다。

처음에는 optparse-applicative와 거의 비슷하게 포팅하려고 했지만、아무래도 Haskell과 JavaScript는 DSL을 構成(구성)해내는 表現力(표현력)에 큰 差異(차이)가 있었다。그래서 苦悶(고민)하던 끝에 TypeScript 開發者(개발자)들에게 이미 親熟(친숙)Zod와 같은 有效性(유효성) 檢查(검사) 라이브러리의 API를 ()뜨기로 했다。

Upyo 프로젝트와는 달리 LLM 코딩 에이전트는 아주 限定的(한정적)으로 文書化(문서화)나 테스트 코드 作成(작성) ()使用(사용)했고、그 때문인지 만드는 데에는 一週日(일주일) 넘게 걸렸던 것 같다。

만들고 나니 JavaScript 生態系(생태계) 안에서는 꽤나 유니크한 CLI 파서 라이브러리가 만들어졌다고 自評(자평)할 수 있었다。勿論(물론)、많은 CLI 애플리케이션이 그렇게 複雜(복잡)한 옵션을 받지는 않지만、어느 程度(정도) 規模(규모)가 있는 CLI 애플리케이션을 만든다면 Optique를 써도 後悔(후회)하지 않을 것이라고 自負(자부)한다。

아、그리고 앞서 紹介(소개)한 다른 라이브러리들과 마찬가지로、Node.js、Deno、Bun、甚至於(심지어) 에지 函數(함수)나 웹 브라우저에서도 動作(동작)한다。그럴 必要(필요)가 있나 싶지만、그저 自己滿足(자기만족)이랄까。다만、德分(덕분)에 테스트 짜기는 아주 쉬운 라이브러리가 되었다。

야크 셰이빙

생각해 보니 내 오픈 소스 開發(개발)原動力(원동력)은 야크 셰이빙(yak shaving)에서 오는 게 아닐까 싶다。Anthony Fu의 「야크 셰이빙에 ()하여」(About Yak Shaving)라는 글을 읽은 적이 있는데、모티베이션을 얻는 方式(방식)이 나와 아주 비슷하다는 印象(인상)을 받았다。뭔가가 不便(불편)해서 道具(도구)를 만드려고 하면、그걸 만드는 途中(도중)에 또 不便(불편)함을 느끼고 그걸 解決(해결)하는 道具(도구)를 만들게 된다。그래서 元來(원래) 하려고 했던 最初(최초)의 일은 못하게 되는 境遇(경우)가 많지만、그렇다고 해서 途中(도중)에 만든 副產物(부산물)들이 어디로 사라지는 것은 아니다。

나도 맨 처음으로 돌아가서 생각해 보면 結局(결국) 하고 싶었던 것은 國漢文混用體(국한문 혼용체)聯合宇宙(연합우주)에 글을 쓰고 싶었던 것인데、이를 ()해 Hollo도 만들고 Fedify도 만들고 LogTape도 만들고 Optique까지 만들게 되었다。그러면서 하고 싶은 다른 것들이 새롭게 생겨났고、Hackers’ Pub 같은 커뮤니티를 ()해 여러 貴重(귀중)因緣(인연)도 맺게 되었다。아、그래서 元來(원래) 하려고 했던 聯合宇宙(연합우주)에서 國漢文混用體(국한문 혼용체)로 글쓰기는 昨年末(작년말)達成(달성)하게 되었다!앞서 紹介(소개)副產物(부산물)들 말고도 Mastodon이나 Misskey ()에 패치를 보내야 했긴 하지만 말이다。4

두 해 남짓한 期間(기간)에 일어난 일들인데 무척이나 재밌고 豐盛(풍성)旅程(여정)이었던 것 같다。앞으로도 當分間(당분간)專業(전업)으로 오픈 소스 開發(개발)을 하게 될 것 같은데、내게 주어진 ()感謝(감사)하며 奮發(분발)해야겠다。


  1. 여러 理由(이유)로 Deno를 쓴 걸 後悔(후회)하고 있긴 하지만、어쩔 수 없이 Deno는 移住(이주) ()에도 繼續(계속) 쓰고 있다。↩︎

  2. Claude Code를 썼다。↩︎

  3. Fedify 프레임워크 自體(자체)는 이미 Node.js、Deno、Bun、Cloudflare Workers ()支援(지원)하고 있긴 했지만、CLI 道具(도구)fedify 命令(명령)만은 Deno 專用(전용)으로 만들어져 있었다。↩︎

  4. 글을 받아 보는 쪽에서도 <ruby> 태그를 렌더링할 수 있어야 했기 때문이다。↩︎