オープンソースプロジェクト間の協力とコードポーティングを象徴するイメージ

AI時代のオープンソース貢献:HwpLibSharpポーティングプロジェクトから学んだこと

AI時代のオープンソース貢献:HwpLibSharpポーティングプロジェクトから学んだこと Microsoft MVPとして活動して17年になります。その間、.NETコミュニティで最も多く受けた質問の一つが「C#でHWPファイルをどう扱えばいいですか?」でした。韓国のハンコム社の公式ライブラリはWindowsとCOMベースであり、クロスプラットフォーム.NET環境では事実上、解決策がありませんでした。 そんな中、@neolord0さんのhwplibを見つけました。Javaで書かれた、純粋にHWPファイルフォーマットをパースするオープンソースライブラリです。「これを.NETに移植すればコミュニティに貢献できる」とすぐに思いましたが、簡単なことではありませんでした。コードベースが膨大な上に、今も継続的にアップデートされていたからです。 2026年、AIコーディングアシスタントと共にこの作業を始めました。 一回限りのポーティングではなく「同期化」 一見、HWPは頻繁に変わるフォーマットではないため、一度ポーティングすれば手を加える必要はないと思いがちです。しかし、あらゆる技術は変化し続けます。元のプロジェクトが今も活発にメンテナンスされているのはもちろん、.NET技術自体も進化しているため、一回限りの作業では不十分です。 従来のフォーク(fork)は、時間が経つほど原本との距離が開きます。最終的に「自分たちのバージョン」と「オリジナル」がそれぞれ別の道を歩むことになります。当然の流れですが、それでも別のアプローチを選びました。単なるフォークではなく、原本と共に生き続ける「移植された実装(Ported Implementation)」 というアイデンティティを明確にしたのです。 元プロジェクト: hwplib (Java) ↓ 定期的な同期 ポーティングプロジェクト: HwpLibSharp (C#) ↓ .NET特化の改善 エコシステム拡張 そのため、READMEにもこう記載しました。 「本プロジェクトの意思決定および判断の優先権は、オリジナルプロジェクトの作者である @neolord0 氏の意思を優先します。」 これは礼儀のために書いた文章ではありません。2つのプロジェクトが長期的に共存するためには、誰が方向性を決めるのかを最初から明確にする必要があると判断したからです。 AIと共に行ったポーティング作業 正直に言えば、AIコーディングアシスタントなしでこのプロジェクトを進めていたら、初期ポーティングだけで6ヶ月以上かかっていたでしょう。アップストリーム同期は到底手が出せず、結局放置された「もう一つのレガシー」になっていたはずです。 しかし、AIと一緒に作業することで、まったく異なるアプローチが可能になりました。 AIがうまくできたこと 構文変換はほぼ完璧でした。Javaのgetter/setterをC#プロパティに変換し、命名規則をC#コンベンションに合わせ、nullチェックをNullable参照型に変換する作業は、ほとんど自動化できました。 ライブラリのマッピングでもAIの助けは大きかったです。Apache POIをOpenMcdfに置き換える際、「Javaでこのライブラリが果たす役割を.NETでは何で代替できるか」を素早く見つけてくれました。元プロジェクトがアップデートされるたびに変更点を追跡してC#バージョンに反映する反復作業でも、ヒューマンエラーを大幅に削減してくれました。 Upstream変更の自動追跡 この過程で特に効果的だったのは、AIエージェントを活用したupstream変更の自動追跡方式でした。元のhwplibプロジェクトに新しいコミットが入るたびに、AIエージェントが変更されたJavaソースファイルと対応するC#ソースファイルを比較分析し、実装上の差異を検出します。 この同期を体系的に管理するために、ポーティングされたすべてのC#ソースファイルの先頭に、元のJavaファイルとの対応関係を明示するヒントヘッダーを残しました。 // ===================================================================== // Java Original: kr/dogfoot/hwplib/util/compressors/Compressor.java // Repository: https://github.com/neolord0/hwplib // ===================================================================== このヘッダーがあれば、AIエージェントは「このC#ファイルの元はJava側のどのファイルか」を即座に把握できます。upstreamでCompressor.javaが変更されると、AIが対応するC#ファイルを見つけてdiffを分析し、不足している変更点や実装上の差異をレポートしてくれます。人間が数百のファイルを一つずつ照合する必要なく、AIが「この部分が原本と異なっているので確認が必要です」と教えてくれる方式です。 実際にこの方式を導入した後、upstream同期にかかる時間が従来比80%以上短縮されました。以前は変更ログを読んで関連ファイルを一つずつ探しながら手動で反映していたのが、今ではAIが変更リストと影響範囲を自動的に整理してくれるようになりました。 AIができなかったこと 一方、HWPファイルのSection-Paragraph-Control構造、各コントロールの意味、韓国語ワープロ文書ならではの特性といったドメイン知識は、完全に自分の役割でした。AIがもっともらしく提案したコードが実際に正しいかどうかの検証は、やはり人間がやるべき仕事です。 戦略的な意思決定も同様でした。Native AOTをサポートするか、Blazor WebAssemblyでどう動作させるか、どの.NETバージョンまでサポートするか。こうした判断には.NETエコシステム全般への理解と、実際のユーザー環境に対する感覚が必要です。ライセンス文言、原作者との関係設定、韓国の開発者コミュニティの文脈を反映する作業も、AIが下書きを作り、自分が仕上げるという方法で進めました。 .NETエコシステムに合わせた再設計 単にコードを移すだけで終わりではありませんでした。.NET開発者が自然に使えるよう、原本プロジェクトの哲学と意図を損なわない範囲でAPIを整える作業も必要でした。 // Blazor WebAssemblyサポート(ファイルシステムなしでストリームから) var hwpFile = HWPReader.FromStream(memoryStream); // Native AOT互換、URLからの非同期ロード var hwpFile = await HWPReader.FromUrlAsync(url); これらの機能はオリジナルのJavaバージョンには存在しません。しかし.NET開発者なら当然期待するものです。おかげで、Azure FunctionsでHWPを処理したり、Blazorでブラウザ上にHWPをレンダリングすることも可能になりました。 ...

2026年2月7日 · 1 分 ·  rkttu
JavaからNETへのコード移植を表現した抽象的なイメージ

Java hwplibを.NETに移植する:AIと共に歩んだオープンソース移植の旅

始まりは単純な好奇心から 「HWPファイルを.NETで直接扱えたらいいのに…」 こんな考えをした.NET開発者は私だけではないでしょう。HWPファイルは韓国で公共機関を中心に今でも広く使われている文書形式ですが、.NETエコシステムではこれを適切に扱えるオープンソースライブラリがありませんでした。 これまで.NETでHWPファイルを扱うには、Windows OS限定でアレアハングルをインストールすると付属するHWP ActiveXコントロールのCOMタイプライブラリを呼び出して制御する程度しかありませんでしたが、残念ながらこれさえもサポートが終了し、今は道が閉ざされた状態です。 そんな中、Javaで書かれたhwplibを発見しました。neolord0さんが継続的にメンテナンスしてきたこのライブラリは、HWPファイルの読み書きを完成度高くサポートしていました。 以前なら、このようなライブラリを移植することは、強い使命感と目的意識がなければなかなか手を出せる作業ではありませんでした。しかし、高性能なAIモデルが多く登場し、今なら新しい挑戦ができるのではないかという好奇心がありました。 こうして始まった3週間の旅を共有します。 数字で見るプロジェクト 本格的な話の前に、Javaバージョンのプロジェクトの規模を数字でまとめてみましょう。 項目 内容 元プロジェクト neolord0/hwplib (Java) 移植プロジェクト rkttu/libhwpsharp (C#) ターゲットフレームワーク .NET Standard 2.0, .NET Framework 4.7.2, .NET 8 総コミット数 54個 開発期間 2025-12-16 ~ 2026-01-08(約3週間) 初期移植コード 641ファイル、50,010行 641ファイル、5万行。正直、最初にこの数字を見たときは「これは可能なのか?」という疑問が湧きました。 初日:AIと共に行った大規模コード変換 5万行を1日で? 2025年12月16日、プロジェクトを開始しました。通常の状況であれば、5万行のJavaコードをC#に変換するには数ヶ月かかったでしょう。しかし、AIコーディングアシスタントがゲームチェンジャーでした。 AIにJavaファイルを渡し、C#に変換してもらいました。もちろん、機械的な変換だけでは不十分でした。JavaとC#は似ているように見えますが、微妙な違いが多いからです。 // Java public byte getValue() { return value; } public void setValue(byte value) { this.value = value; } // C# public byte Value { get; set; } このようなパターン変換はAIがうまく処理してくれました。しかし、本当の問題は別にありました。 最大の難関:Apache POIからOpenMcdfへ OLE2複合ドキュメントの沼 HWPファイルはMicrosoftのOLE2複合ドキュメント形式(Compound File Binary Format)に基づいています。簡単に言えば、1つのファイルの中に複数の「ストリーム」がフォルダ構造のように格納されている形式です。 JavaではApache POIライブラリがこの形式を扱いますが、.NETには直接対応するものがありません。代わりにOpenMcdfというライブラリを使う必要がありましたが、残念ながらApache POIとはAPIが完全に異なります。 ...

2026年1月8日 · 2 分 ·  rkttu