目次
Clojureの流儀
ClojureのWeb開発は、単体の「巨大なフレームワーク」を使うというより、Ringをベースとして複数のライブラリを組み合わせていくスタイルが主流である。
用途や好みに応じて、CompojureやReititをルーティングに使い、テンプレートエンジンやDB接続ライブラリを自由に組み合わせることができる。また、LuminusやDuctのようにあらかじめ統合されたテンプレート/フレームワークを利用することで、開発の初期セットアップを手早く進めるやり方も選択できる。
これらを状況に応じて選択し、Clojure本来の関数合成やデータ駆動設計のメリットを生かしながらWebアプリを構築するのが一般的なアプローチとなっている。
ライブラリの分類
1. Webサーバ(ポートを開いてHTTPリクエストを受け付ける)
役割:
主なライブラリ(Ringアダプタ):
- Jetty (ring-jetty-adapter)
- http-kit
- Undertow (ring-undertow-adapter)
- Aleph (Nettyベース)
- Immutant (JBoss/WildFlyベース)
2. HTTPリクエスト/レスポンスの基盤(Ring)
役割:
- HTTPリクエストとレスポンスをClojureのマップで表現し、各種ミドルウェアをチェーンしながら処理する仕組み(Clojure版Rack/WSGI)。
- 「Webサーバ(Jettyなど)」と「アプリケーション(ルーティング含む)」の橋渡し役。
主なライブラリ:
- Ring(本体・標準的なミドルウェア群)
- Ringアダプタ(Jetty/http-kitなどと連携するための追加ライブラリ)
3. ルーティング(URLのパスやHTTPメソッドに応じて処理を振り分ける)
役割:
- GET /users -> users-handler のように、URLと処理関数を対応づける。
- 複雑なURLパラメータやSwagger/OpenAPIの定義サポートなども提供。
主なライブラリ:
- Compojure:宣言的にルートを書くためのマクロ *1
- Reitit:データ駆動のルーティング、Swagger/OpenAPI連携も強力
- Bidi:双方向(URL生成・パース)に対応するデータ駆動型ルーティング
- Pedestal:インターセプターベースのフレームワークだが、ルーティング機能も内包
4. テンプレートエンジン(サーバーサイドHTMLレンダリング)
役割:
主なライブラリ:
- Selmer:Mustache系テンプレートエンジン。{{変数}} の書式
- Hiccup:Clojureのデータ構造でHTMLを直接表現(S式でHTMLタグを書く)
- Enlive:HTMLをパースし、CSSセレクタで変数注入するテンプレートエンジン
5. RESTフレームワーク(REST API用の高レベル抽象)
役割:
主なライブラリ:
- Liberator:REST原則(条件付きGET、レスポンスコードなど)を支援
- Yada:Liberatorに近いコンセプトを持ち、非同期処理やWebSocketにも対応
6. 統合フレームワーク/テンプレート(アプリケーション全体構成)
役割:
- ルーティング、DB接続、認証、テンプレートなど複数の機能をひと通り揃え、一括でセットアップできるようにする。
- プロジェクトテンプレートや設定駆動の仕組みを用いて、大規模プロジェクトや中〜長期開発の基盤として利用。
主なライブラリ:
- Luminus:RingやCompojure、Reitit、Selmerなどを統合したプロジェクトテンプレート
- Duct:設定駆動 (Integrant) でアプリケーションを構築するフレームワーク
- Pedestal:インターセプターによる高度なリクエスト処理が特徴(サーバ側機能全般を包含)
- Biff:リアルタイム機能(WebSocket系)や小規模向けの開発を簡略化
7. フロントエンド向けライブラリ/フレームワーク(ClojureScript)
役割:
- ReactなどのJavaScriptフレームワークをClojureScriptでラップし、宣言的なUI開発を可能にする。
- サーバとフロントエンドの両面をClojureで統一する際によく利用される。
主なライブラリ:
- Reagent:ReactをClojureScriptで扱うための軽量ラッパ
- Re-frame:Reagent上に構築されたFluxアーキテクチャ(状態管理フレームワーク)
- Fulcro:フロント/バックエンドを一貫してGraphQL風のクエリで扱うフルスタック
- Hoplon:リアクティブプログラミングを活用したHTML生成フレームワーク
- Macchiato:Node.js上でClojureScriptを使うサーバサイドJSフレームワーク(Webサーバも実装可能)
8. データベースアクセス
役割:
- RDBMS(PostgreSQL, MySQLなど)への接続やクエリ発行を行い、結果をClojureのデータ構造で扱いやすくする。
- DB接続プールやマイグレーションとの統合などをサポートすることも。
主なライブラリ:
- clojure.java.jdbc:古典的な標準ライブラリ的存在 (メンテは縮小傾向)
- next.jdbc:より新しく、軽量でシンプルなAPIを持つRDB接続ライブラリ
- HugSQL:SQLファイルをそのままClojureから呼び出すスタイル
- Datomic / XTDB:NoSQL/Document的なDBだがClojureとの親和性が高い
構成パターン
他にもあるんだろう。そうだろう。
1. シンプル&ミニマル構成
- Ring(HTTP基盤)
- Compojure(ルーティング)
- Hiccup(HTMLテンプレートマクロ)
特徴
- もっともミニマルな構成のひとつ。
- リクエストのルーティングやHTML生成を手早く行える。
- DBアクセスなどが必要な場合は、個別にclojure.java.jdbcやnext.jdbcを導入するイメージ。
用途の例
- 小規模なプロトタイプや学習目的のプロジェクト。
- シングルページではなく、クラシックなサーバーサイドレンダリングをするWebサイト。
2. REST API + サーバーレンダリング併用
特徴
- ルーティングをReititでデータ駆動的に行う。
- 部分的にテンプレートエンジン(Selmer)でページをレンダリングしつつ、一部エンドポイントはJSONを返却してクライアントがJavaScriptで処理するような構成。
- 必要に応じてreitit.swaggerを使ってAPIドキュメントを自動生成できる。
用途の例
3. フルスタック・テンプレートで統合
- Luminusテンプレート(内部的にRing/Compojure/Reitit/テンプレートエンジンなどを組み合わせ)
- Shadow CLJS(フロントエンドのClojureScriptビルド)
- Reagent / Re-frame(フロントエンドUI)
特徴
- Luminusはプロジェクト作成時に数多くのライブラリを一括でセットアップしてくれる。
- フロントエンドはReagent/Reactベースで作りつつ、サーバー側はCompojureやReititを活用。
- ルーティング・テンプレート・認証・DB接続・REST APIなど、ひと通りの機能を初期段階から統合。
- メンテナンスが行き届いており、最新のClojure/ライブラリと相性が良い。
用途の例
- 中〜大規模で、最初からある程度整ったプロジェクト構成がほしい場合。
- Clojureに入門してすぐWeb開発したいが、多数の依存ライブラリを一手ずつ組み合わせるのは大変…というケース。
4. Duct + Integrant で設定駆動開発
- Duct(設定駆動アプリケーションフレームワーク)
- Integrant(ライフサイクル管理ライブラリ)
- Ring / Reitit / Compojureのいずれかを組み合わせる
- Hiccup / Selmerなど、テンプレートエンジンを好みで追加
特徴
- 設定ファイル(EDN形式)でコンポーネント(DB, Webサーバ, ルーティングなど)を宣言し、duct.coreによってそれらを起動・停止する仕組み。
- コンポーネント間の依存関係やライフサイクルをIntegrantが管理するため、大規模システムでも明確に分割可能。
- ルーティングやViewの部分は自分で好きなライブラリを導入する形。
用途の例
- プロダクションレベルでコンポーネントを明確に分割したい中〜大規模アプリ。
- CI/CDパイプラインやステージング/本番環境など、複数の設定を切り替えながら使うケース。
5. Pedestalを核としたアプリケーション
- Pedestal(インターセプターによる柔軟なリクエスト・レスポンス処理)
- io.pedestal.httpモジュールによるWebサーバ機能
- テンプレートエンジンやDBライブラリは好みで追加
特徴
- Cognitect(現NuSphere)製で、Clojureらしい「インターセプター」パイプラインを全面的に採用。
- 入出力の前後処理をきめ細かく定義できるため、認証やロギング、トランザクション管理などの共通処理をまとめやすい。
- ルーティングもデータベース的に管理できる。
- 非同期処理やWebSocketsにも対応しやすい。
用途の例
- 複数の機能をパイプラインでつなぎ、処理の前後関係を明示的に管理したい中規模以上のアプリ。
- WebSocketなどリアルタイム性が絡むサービス。
6. Fulcro + (RingまたはPedestal) のフロント・バック統合
- Fulcro(フロント/バックエンド両面で同じGraphQL的クエリ概念)
- サーバサイド:RingかPedestalと統合
- DBアクセス:pathom + SQL系ライブラリ or Datomic
特徴
- FulcroはOm Nextの流れを汲んでおり、フロントエンドを「データベースを編集する」感覚で構築できるフレームワーク。
- サーバ側では、FulcroのバックエンドとしてPathomを用いてクエリを解決するパターンが多い。
- UI開発とデータロジックをシームレスにつなげられる利点。
用途の例
- シングルページアプリケーション(SPA)でフロントの状態管理を強力かつ宣言的に行いたい場合。
- 大量のUIコンポーネントを一貫したデータ管理で扱いたい大規模プロジェクト。
7. Biff で小〜中規模のリアルタイムアプリ
- Biff(小規模〜中規模向けWebアプリフレームワーク)
- XTDB や Firebaseなどデータストアを選択してリアルタイム連携
- サーバー・フロントエンドがセットになった構成
特徴
- 「サーバーサイドのWebソケットによるリアルタイム更新」などを最初からサポート。
- プロトタイプ作成・スモールビジネスなどでの開発に適しており、少ないコードでライブ更新を実現できる。
- 必要な機能はある程度備わっているが、大規模アプリには向いていない場合も。
用途の例
- 小規模サービスやスタートアップの検証用サービスで、チャットなどのリアルタイム機能をすぐ導入したい場合。
- デプロイ含めてサクッと始めたいが、Clojureのメリットも享受したい場合。
まとめ
ClojureでのWeb開発はプロジェクトの規模・要件・好みに応じて下記のような軸で選んでいくのが典型的です。
- ルーティング: Compojure / Reitit / Pedestal / Bidi など
- フレームワーク/テンプレート: Luminus / Duct / Pedestal / Biff / Fulcro など
- テンプレートエンジン / フロントエンド: Selmer / Hiccup / Reagent / Re-frame / Fulcro など
- データベース接続: clojure.java.jdbc / next.jdbc / HugSQL / Datomic / XTDB など
「最小限の組み合わせ」から始めるのもよし、LuminusやDuctのような統合されたテンプレートを使って必要な機能を一挙に導入するのもよし、開発チームの経験や用途に合わせて最適な形を模索できるのがClojureらしさと言える。
*1:GET "/path" [] ...