導入:なぜ「ブリッジ」が必要だったのか

「AI テスト設計ツール」の開発において、最大の課題は PDF や Excel の「正確な構造化」でした。GPT-4o などの LLM であっても、複雑な表構造を素のバイナリやテキストから読み解くのは限界があります。 そこで白羽の矢が立ったのが、Microsoft の「MarkItDown」です。しかし、これは Python 製。Next.js (Node.js) をベースとする本プロジェクトでこの恩恵を受けるには、言語の壁を越える「ブリッジ」が必要でした。

導入:なぜ「ブリッジ」が必要だったのか

設計:child_process.spawn による軽量連携

安易に Flask や FastAPI で外部 API 化するのではなく、今回は「Child Process」による直接実行を選択しました。 その理由は、オーバーヘッドの最小化と、外部サーバー不要のプロプライエタリな動作環境の維持です。`child_process.spawn` を使い、Node.js から Python インタープリタを直接叩き、`stdin` / `stdout` を通じて JSON データをやり取りするアーキテクチャを確立しました。

Source Code
// Node.js 側の呼び出しイメージ
const pythonProcess = spawn('python', ['-u', 'parse.py']);

pythonProcess.stdin.write(JSON.stringify(inputData));
pythonProcess.stdin.end();

pythonProcess.stdout.on('data', (data) => {
  const result = JSON.parse(data.toString());
  // 解析結果の処理
});

最大の敵:Windows 環境の「文字化け」との決戦

開発中に直面した最大の壁は、日本語文字コードの問題でした。Windows 環境のデフォルト(CP932)と Python/Node.js のデフォルト(UTF-8)が衝突し、日本語の仕様書を渡すと `UnicodeDecodeError` や文字化けが発生。 これを解決するため、Python 側で標準入出力を強制的に UTF-8 に再定義し、さらに Node.js 側でもバッファのデコードを厳密に管理。この「地味ながら不可欠な」調整が、実用的なツールの鍵となりました。

Source Code
# Python 側の文字コード対策
import sys
import io

# 標準入出力を UTF-8 に固定
sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8')
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

# MarkItDown での解析
md = MarkItDown()
result = md.convert(file_path)

結論:ハイブリッド構成がもたらす開発スピード

「JavaScript ですべてを完結させる」という制約を捨て、適材適所で Python の強力なエコシステムを取り入れたことで、開発スピードと解析精度は飛躍的に向上しました。 このブリッジは、単なる一時しのぎではありません。「言語の壁」を「疎結合な設計」によって解決する、モダンな Web 開発における一つの解答だと確信しています。