<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Plumber on Rindrics Mumbles</title>
    <link>https://rindrics.com/tags/plumber/</link>
    <description>Plumber</description>    
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Tue, 16 Jun 2026 00:00:00 +0900</lastBuildDate>
    <atom:link href="https://rindrics.com/tags/plumber/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>plumber を使ってみた</title>
      <link>https://rindrics.com/posts/stock-assess-plumber/</link>
      <pubDate>Tue, 16 Jun 2026 00:00:00 +0900</pubDate>
      
      <guid>https://rindrics.com/posts/stock-assess-plumber/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;../stock-assess-restart&#34;&gt;前回記事&lt;/a&gt;でリファクタリングの方針を立てたので、モノリスアプリケーションを作るところから始めてみる。&lt;/p&gt;
&lt;p&gt;とりあえず&lt;a href=&#34;https://github.com/Rindrics/yoshimoto-samonji&#34;&gt;リポジトリ&lt;/a&gt;を作った。
開発コードは &lt;a href=&#34;https://ja.wikipedia.org/wiki/%E7%BE%A9%E5%85%83%E5%B7%A6%E6%96%87%E5%AD%97&#34;&gt;yoshimoto-samonji&lt;/a&gt;（義元左文字）。&lt;/p&gt;
&lt;h2 id=&#34;技術選定&#34;&gt;技術選定&lt;/h2&gt;
&lt;p&gt;計算エンジンを Web UI から利用するモノリスアプリがゴールなら Shiny App 化すればいいのだが、
&lt;a href=&#34;../stock-assess-state-change&#34;&gt;評価ステータス管理の実験&lt;/a&gt;をしていた当時のように、最終的には評価「事業」全体をアプリ化したい。
丁寧なドメインモデリングが必要になるので、フロントは始めから型を扱える TypeScript で実装しておきたい。&lt;/p&gt;
&lt;p&gt;これを踏まえて、モノリスのバックエンドは &lt;a href=&#34;https://github.com/rstudio/plumber&#34;&gt;plumber&lt;/a&gt; を使って構築することにした。
&lt;a href=&#34;https://www.rplumber.io/&#34;&gt;ドキュメント&lt;/a&gt;をざっと見てみたが、OpenAPI ドキュメントを生成してくれるようなので、フロント&amp;ndash;バック境界は HTTP になる見込み。
ということは、フロントエンドに Next.js を使っておけば、Route handler を BFF に使える。
そうすると認証やセッション管理、画面向けのレスポンス整形を Next.js 側に寄せられるので、BFF を独立サービスとして立てる手間を抑えられそう。&lt;/p&gt;
&lt;p&gt;ここまでを &lt;a href=&#34;https://github.com/Rindrics/yoshimoto-samonji/commit/802416b2453da6f1a72ff54a4a8e13d0396a73aa&#34;&gt;ADR にした&lt;/a&gt;。&lt;/p&gt;
&lt;h2 id=&#34;plumber-を使ってみる&#34;&gt;plumber を使ってみる&lt;/h2&gt;
&lt;h3 id=&#34;hello-plumber&#34;&gt;hello, plumber&lt;/h3&gt;
&lt;p&gt;始めて触るので、plumber を使った最低限の実装を書いてみる。&lt;/p&gt;
&lt;p&gt;とりあえず&lt;a href=&#34;https://github.com/Rindrics/yoshimoto-samonji/commit/f854c38dd48a75bdabf3aaa51f387c3a513edada&#34;&gt;パッケージをセットアップ&lt;/a&gt;し、
&lt;a href=&#34;https://www.rplumber.io/reference/index.html&#34;&gt;reference&lt;/a&gt;を&lt;a href=&#34;https://github.com/Rindrics/yoshimoto-samonji/commit/93bd9d1f70e2e300c00cffc1bc0b2aac34a0b2a7&#34;&gt;参考に実装してみた&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Plumber&lt;/code&gt; オブジェクトの &lt;code&gt;$run()&lt;/code&gt; を実行する関数を作り、&lt;code&gt;devtools::load_all()&lt;/code&gt; してから呼び出すと、指定したポートでサーバーが起動した:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;&amp;gt;&lt;/span&gt; devtools::load_all(); start_server()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ℹ Loading legacy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Running plumber API at http:&lt;span style=&#34;color:#719e07&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;127.0&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;0.1&lt;/span&gt;:&lt;span style=&#34;color:#2aa198&#34;&gt;31501&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Running swagger Docs at http:&lt;span style=&#34;color:#719e07&#34;&gt;//&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;127.0&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;0.1&lt;/span&gt;:&lt;span style=&#34;color:#2aa198&#34;&gt;31501&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;/&lt;/span&gt;__docs__&lt;span style=&#34;color:#719e07&#34;&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;クエリパラメータ &lt;code&gt;msg&lt;/code&gt; に渡した文字列を利用したレスポンスを返す API ができた:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ curl &lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;http://127.0.0.1:31501/vpa/echo?msg=hello&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;{&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;msg&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#719e07&#34;&gt;[&lt;/span&gt;&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;The message is: &amp;#39;hello&amp;#39;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#719e07&#34;&gt;]}&lt;/span&gt;%
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、&lt;code&gt;/__docs__&lt;/code&gt; にアクセスすることで Swagger UI も利用できた:
&lt;figure&gt;&lt;img src=&#34;https://rindrics.com/images/2026-06-16-plumber/swagger.webp&#34;
    alt=&#34;生成された API ドキュメント。UI から動作確認できる&#34;&gt;&lt;figcaption&gt;
      &lt;p&gt;生成された API ドキュメント。UI から動作確認できる&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;せっかく OpenAPI を利用できているので、将来的にはクライアントコードを生成するなどして契約駆動開発していきたい。
API スキーマをファイルに直接書き出すメソッドは無さそうだったが、&lt;a href=&#34;https://www.rplumber.io/reference/Plumber.html?q=getApiSpe#method-getapispec-&#34;&gt;&lt;code&gt;getApiSpec()&lt;/code&gt;&lt;/a&gt; を使うと仕様をリストで取得できそうだったので、これを &lt;a href=&#34;https://github.com/Rindrics/yoshimoto-samonji/commit/2bb09a9ece31f99d20ef471acfa754c8f4518479&#34;&gt;JSON にマッピングして書き出すことにした&lt;/a&gt;。
スキーマはいったん ignore しておいて、クライアントコード生成などは Next.js のセットアップをしてから整えることにした。&lt;/p&gt;
&lt;p&gt;ちなみに生成されたスキーマを見ると、設定した覚えのないメタデータが既に入っていた:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;&amp;#34;openapi&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;3.0.3&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#268bd2&#34;&gt;&amp;#34;info&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#268bd2&#34;&gt;&amp;#34;description&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;API Description&amp;#34;&lt;/span&gt;], &amp;lt;- このへんは設定した覚えがない
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#268bd2&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;API Title&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#268bd2&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#2aa198&#34;&gt;&amp;#34;1.0.0&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&#34;https://www.rplumber.io/articles/annotations.html?q=description#annotations-example&#34;&gt;ドキュメント&lt;/a&gt;を見ると設定方法がちゃんと書いてあって、アノテーションか &lt;code&gt;pr_set_api_spec()&lt;/code&gt; を使って設定できるらしい。
初めドキュメントの通りにアノテーションを足したつもりが、スキーマに反映されなかったが、&lt;a href=&#34;https://github.com/Rindrics/yoshimoto-samonji/commit/091c2d5254d4a7fa7ccb13d25ecb8882508e3d42#diff-5714ab9b3a287e926760b71b0596e65ca649a97e2552d861726619fef0a91ffaL2&#34;&gt;このように&lt;/a&gt; &lt;code&gt;Plumber&lt;/code&gt; オブジェクトを作っているファイル名を &lt;code&gt;rp()&lt;/code&gt; の &lt;code&gt;file&lt;/code&gt; 引数に指定することで反映されるようになった。
ドキュメントでは引数なしで動いているように見えたが、断りがない限り &lt;code&gt;Plumber&lt;/code&gt; を作るファイル名は &lt;code&gt;plumber.R&lt;/code&gt; になっている想定らしい。&lt;/p&gt;
&lt;h3 id=&#34;コンテナ-image-化&#34;&gt;コンテナ image 化&lt;/h3&gt;
&lt;p&gt;R ではライブラリ系の使われ方をする開発しかしたことなかったので、思考停止でパッケージアプローチを取る癖がついてしまっていたけど、
今回コンテナ用イメージを作る段になって、ランタイム系のイメージを作るにはパッケージアプローチは無駄が多すぎることに気づいた。
&lt;code&gt;devtools&lt;/code&gt; のような開発系ツールや、その他パッケージ化に必要なメタデータもランタイムとしては完全に無駄なので、結局シンプルなスクリプト構成に移行した。&lt;/p&gt;
&lt;p&gt;plumber がどうやって動作しているかを理解していなかったせいで、スクリプト形式に移行する過程でだいぶハマった。
それはそれで学ぶこともあったので、時間があったら別記事にする。&lt;/p&gt;
&lt;h2 id=&#34;vpa-を実行する-image-を作る&#34;&gt;VPA を実行する image を作る&lt;/h2&gt;
&lt;p&gt;&lt;a href=&#34;https://ichimomo.github.io/frasyr/articles/vpa.html&#34;&gt;こちらのドキュメント&lt;/a&gt;を参考に
とりあえず &lt;code&gt;vpa()&lt;/code&gt; を実行することにした。
データの保存場所は恐らく分かれると思うので、それぞれのデータは URL で受け取るようにした。
リクエストもレスポンスも、設計余地がけっこうありそうなので、まだ仮の実装にしてある。
将来的に API 仕様を変えることが明らかなので、予めバージョンを切っておいた。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&#34;https://rindrics.com/images/2026-06-16-plumber/post-vpa.webp&#34;
    alt=&#34;バージョンを切った。&#34;&gt;&lt;figcaption&gt;
      &lt;p&gt;バージョンを切った。&lt;/p&gt;
    &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;まず一つ API を作ってみた感じでは、見積もりの 5 倍くらいは時間がかかった気がする。
ただし、内訳としては plumber の使い方自体だったり、ビルドプロセスの調整などに手間取っていた。
API 自体の設計とかは全然していなかったので、今後は別のところに時間がかかるようになるはず。&lt;/p&gt;
&lt;h2 id=&#34;学んだこと&#34;&gt;学んだこと&lt;/h2&gt;
&lt;p&gt;改めて、使われ方に応じた構成をとることが大事。
型がないとスキーマ定義などがめちゃめちゃ面倒。&lt;/p&gt;</description>
    </item>
    
  </channel>
</rss>
