フロントとバックエンドで型を共有する方法:モノレポ構成の考え方(Next.js対応)

なぜ「型の共有」が重要なのか:仕様ズレがコストを生む

Webシステム開発では、画面側(フロントエンド)とサーバー側(バックエンド)がデータをやり取りします。たとえば「顧客一覧」を表示するだけでも、サーバーが返す項目(氏名、メール、権限など)と、画面が期待する項目が一致していないと不具合になります。ここで役立つのが「型(かた)」です。型とは、データの設計図のようなもので、どんな項目があり、どんな形式(文字・数値・日付など)かを明確にします。

型をフロントとバックエンドで別々に管理していると、仕様変更のたびに「双方の修正漏れ」が起きやすく、テスト工数や手戻りが増えます。特に情シスや管理部門の立場だと、不具合は“現場の業務停止”に直結し、原因が見えにくいのが痛点になりがちです。型を共有できると、変更点が一箇所に集まり、実装者が気づきやすくなります。

さらに、採用や外注の観点でも効果があります。フロント担当とバックエンド担当が分かれていても「共通の設計図」があるためコミュニケーションが簡単になり、見積もりの精度も上がります。Next.jsのようなTypeScript前提で進めやすい構成を採ると、この型共有の恩恵を受けやすくなります。

この記事では、専門用語はできるだけ噛み砕きつつ、「モノレポ(1つのリポジトリにまとめる)構成」でフロントとバックエンドの型を共有する考え方、導入手順、運用時の注意点までを整理します。技術選定や発注時に「何を確認すべきか」が分かる内容にしています。

3分でできる! 開発費用のカンタン概算見積もりはこちら

前提整理:フロント・バックエンド・型・モノレポをやさしく説明

まず用語をそろえます。フロントエンドは、ブラウザで動く画面部分(入力フォーム、一覧、ボタンなど)。バックエンドは、データベースに保存したり、権限チェックをしたり、外部サービスと連携したりするサーバー側の処理です。両者はAPIという「窓口」を介してデータをやり取りします。

型(Type)は、そのAPIが扱うデータの形を定義します。例として「顧客」を考えると、idは数値、nameは文字列、emailは文字列、statusは「有効/無効」のどちらか、などを決めます。これが決まっていると、画面側で存在しない項目を参照してエラーになる、あるいはサーバー側で受け取ってはいけない値が入る、といった事故を減らせます。

モノレポ(Monorepo)は、フロントとバックエンドを別々のリポジトリにせず、1つのリポジトリ内で複数のアプリや共通ライブラリをまとめて管理する方式です。対になる考え方として、フロントとバックエンドを別リポジトリにする「マルチレポ」があります。モノレポでは、共通の型定義を同じ場所に置けるため、「型の共有」が実現しやすいのが特徴です。

Next.jsはフロントの代表格ですが、API Routes(簡易なサーバー機能)や、最近ではサーバー側での処理(Server Actionsなど)も扱えるため、プロジェクト規模によっては「フロント+一部バックエンド」を同居させやすいです。ただし、企業システムでは認証、権限、バッチ処理、外部連携などが増えるため、バックエンドを別アプリとして設ける構成も一般的です。その場合でもモノレポなら、型だけは共通化できます。

型共有の代表的な方式と、情シス視点の選び方

「型を共有する」といっても、方法は複数あります。選び方を誤ると、逆に運用が複雑になります。ここでは代表的な方式を、情シス・発注側が判断しやすい観点で整理します。

  • TypeScriptの型定義を共通パッケージとして共有:フロントもバックエンドもTypeScriptで書く場合に相性が良い。モノレポに共通フォルダ(例:packages/types)を作り、両方から参照する。
  • OpenAPI(Swagger)などの仕様書から自動生成:API仕様をドキュメントとして管理し、クライアント側の型やコードを生成する。バックエンドが別言語(Java, Goなど)でも適用しやすい。
  • tRPCなど「型安全なAPI」方式:フロントからバックエンドの関数を呼ぶ感覚でAPIを使い、型が自動的に一致する。両方TypeScript前提で、モノレポと相性が非常に良い。
  • GraphQLスキーマ共有:スキーマ(データ定義)を中心に据え、クエリから型生成する。柔軟だが設計・運用の学習コストは上がりやすい。

発注側の観点では、「今後の拡張」「ベンダー変更」「監査・ドキュメント」の要件が重要です。たとえば、複数ベンダーが関わる可能性があるなら、OpenAPIのように仕様が独立している方式は強いです。一方、少人数チームでスピード重視なら、tRPC+モノレポは生産性が高く、仕様変更のたびに“二重修正”が発生しにくいのが魅力です。

また、Next.jsで画面を作るプロジェクトでは、フロントはTypeScript採用が一般的です。バックエンドもTypeScript(Node.js)に寄せられるなら、共通型共有はシンプルになります。逆にバックエンドが別言語の基幹システム連携(例:Javaの既存API)なら、OpenAPIなどを軸にする方が安定します。

3分でできる! 開発費用のカンタン概算見積もりはこちら

モノレポでの基本設計:どこに何を置くと管理しやすいか

モノレポ導入で大事なのは「置き場所のルール」です。闇雲に同居させると、依存関係が絡まり、アップデートやビルドが遅くなります。基本は、アプリと共通部品を分けて配置します。

よくある構成例(概念)としては次のようになります。

repo/
  apps/
    web/        (Next.js: フロント)
    api/        (バックエンドAPI)
  packages/
    types/      (フロント/バックエンド共通の型)
    ui/         (共通UIコンポーネント: 必要なら)
    config/     (lint, tsconfigなどの共通設定)

ここでのポイントは、共通のtypesパッケージは「純粋な型定義」に寄せることです。バックエンドのDBアクセスや、フロントの画面ロジックまで入れると、依存が増えて壊れやすくなります。たとえば、共通に置くのは以下のようなものが適しています。

  • APIの入出力(Request/Response)の型
  • 画面で扱うドメインモデル(顧客、注文、権限など)
  • 共通のバリデーションルール(後述のZodなど)

一方で「認証トークンの発行」や「DBのテーブル定義」など、バックエンド固有の処理はapps/api側に残す方が安全です。共通化の範囲を広げすぎると、変更の影響範囲が読めず、運用事故の原因になり得ます。

運用面では、モノレポ用のツール(例:Turborepo、Nx、pnpm workspacesなど)を使うことで、変更があった部分だけビルド・テストし、CI(自動テスト)の時間を短縮できます。情シス視点では、「ビルドが遅くて開発が止まる」ことは生産性低下の典型なので、モノレポ採用時はこの仕組みもセットで確認すると安心です。

Next.jsで型共有を実現する実装パターン:現場で失敗しにくい手順

Next.jsをフロントに採用し、バックエンドが別アプリ(Node.js/TypeScript想定)としてあるケースで、型共有を進める現実的な手順を紹介します。ポイントは「型定義」だけでなく、「入力チェック(バリデーション)」まで揃えることです。型だけ共有しても、実行時に想定外の値が入ればエラーになります。

共通の型と、共通の入力チェックをセットで持つ

TypeScriptの型はコンパイル時の安全性を上げますが、外部から来るデータ(ブラウザや他システム)は実行時に壊れている可能性があります。そこで、Zodなどのスキーマ定義(入力チェック)を共通パッケージに置き、そこから型も生成する形が実務で扱いやすいです。

// packages/types/src/customer.ts(例)
import { z } from "zod";

export const CustomerSchema = z.object({
  id: z.string().uuid(),
  name: z.string().min(1),
  email: z.string().email(),
  status: z.enum(["active", "inactive"]),
});

export type Customer = z.infer<typeof CustomerSchema>;

この方式だと、バックエンドは受け取ったデータをCustomerSchemaで検証でき、フロントは同じ定義から導かれたCustomer型で安心して画面を作れます。「定義は1つ、使い回しは両側」になり、変更漏れが減るのが利点です。

APIレスポンスを「共通型」で固定する

APIの戻り値が曖昧だと、画面側の表示ロジックが増えます。そこで、レスポンスの“包み”も共通化します。例えば成功時・失敗時の形式を統一します。

// packages/types/src/api.ts(例)
import { z } from "zod";

export const ApiErrorSchema = z.object({
  code: z.string(),
  message: z.string(),
});
export type ApiError = z.infer<typeof ApiErrorSchema>;

export const ApiOkSchema = <T extends z.ZodTypeAny>(data: T) =>
  z.object({ ok: z.literal(true), data });

export const ApiNgSchema = z.object({ ok: z.literal(false), error: ApiErrorSchema });

こうしておくと、フロントは「okなら表示、ngならエラーメッセージ」という共通パターンで実装でき、運用時の問い合わせ対応(“何が起きたか”)も整理されます。

tRPCを使う場合:API仕様と型のズレを根本的に減らす

もしバックエンドもTypeScriptで、モノレポにできるなら、tRPCは有力です。APIを「エンドポイントの文字列」ではなく「関数」として扱うイメージで、フロントはバックエンドの型を自動的に参照できます。結果として、API変更時にフロント側がコンパイルエラーで気づけます。

ただし、tRPCは「社内外の別チームがAPIを利用する」「外部公開APIにする」場合には、OpenAPIのような独立した仕様書も併用した方が管理しやすいことがあります。情シスとしては、将来の拡張(他部署・外部連携)を見越して、どこまで閉じたAPIかを整理すると選びやすくなります。

3分でできる! 開発費用のカンタン概算見積もりはこちら

導入時に押さえるチェックリスト:外注・内製を問わず効くポイント

型共有とモノレポは、導入そのものより「継続運用」で差が出ます。以下は、発注側・管理側が確認しておくと、後から揉めにくいポイントです。

  • 共通パッケージの責務が明確か:typesは型とバリデーション中心、業務ロジックは各アプリ側、などルールがあるか。
  • 変更フローが整備されているか:型変更→バックエンド修正→フロント修正→テストの順がCIで担保されているか。
  • バージョン管理の方針:モノレポ内で一括更新するのか、共通パッケージだけバージョンを切って配布するのか。
  • APIの互換性の考え方:古い画面が残る期間があるなら、互換性(後方互換)をどう扱うか。
  • セキュリティと権限設計:型共有は便利だが、権限チェックはバックエンドで必ず実施する設計になっているか。

特に最後の権限設計は重要です。型が合っている=安全、ではありません。たとえば「請求情報」など機密データは、型としては同じでも、閲覧できるユーザーが限定されます。“見せてよいデータだけを返す”責任はバックエンドにあるため、型共有はあくまで品質向上の一手段と捉えると良いです。

また、社内での説明材料としては「不具合削減」「改修見積もりの安定」「引き継ぎ容易」の3点が伝わりやすいです。Next.js採用のプロジェクトでは、画面改修の頻度が高くなりがちなので、型共有が効いてきます。

よくある失敗と回避策:モノレポは“万能”ではない

モノレポは便利ですが、導入すれば自動的に良くなるわけではありません。失敗例を先に知っておくと、設計と発注で回避できます。

共通化しすぎて変更が怖くなる

「共通だから」と何でも入れると、少しの変更が広範囲に影響し、リリースが遅くなります。回避策は、共通の領域を“薄く”保つことです。型・バリデーション・APIの入出力など、境界(インターフェース)に集中させます。

ビルドやテストが遅くなる

1つのリポジトリにまとめると、CIが全体をビルドしがちです。回避策として、Turborepo等で「変更があったところだけ」回す仕組みを作り、キャッシュを活用します。運用面の改善は開発者任せにせず、“CI時間の目標”を非機能要件として合意しておくと失敗しにくいです。

バックエンドが別言語で、型共有が形骸化する

既存の基幹APIがJava等で、フロントがNext.jsのようなケースでは、TypeScriptの型共有だけでは完結しません。OpenAPIで仕様を一元管理し、フロント側の型生成を自動化するほうが、長期的に安定します。プロジェクトの前提(既存資産、将来の他システム連携)に合わせて方式を選ぶのが大切です。

「型があるから大丈夫」とテストが弱くなる

型は多くのバグを減らしますが、業務ルール(例:締め日、権限、金額の上限)までは保証しません。回避策は、重要な業務フローに対してE2Eテストや結合テストを計画に入れることです。型共有はテストを減らすためではなく、テストの質を重要な領域に集中させるために使うと効果的です。

3分でできる! 開発費用のカンタン概算見積もりはこちら

まとめ

フロントとバックエンドで型を共有できると、仕様変更の手戻りや修正漏れを減らし、開発スピードと品質を両立しやすくなります。特にNext.jsを採用するプロジェクトではTypeScriptとの相性が良く、モノレポ構成にすることで共通の型定義を自然に扱えます。

方式は大きく「共通TypeScript型」「OpenAPIから生成」「tRPC」「GraphQL」などがあり、チーム体制や将来の拡張(外部連携、ベンダー変更)によって最適解が変わります。導入では、共通化の範囲を絞る、バリデーションも共通化する、CIの速度や変更フローを整える、といった運用設計が重要です。

発注・企画の立場では、「型共有ができる設計か」「仕様変更に強いか」「ドキュメントと自動化があるか」を確認するだけで、プロジェクトの安定性が上がります。もし現状の開発で、改修のたびに不具合が出る、見積もりがブレる、引き継ぎが重いと感じているなら、モノレポでの型共有は検討価値があります。

株式会社ソフィエイトのサービス内容

  • システム開発(System Development):スマートフォンアプリ・Webシステム・AIソリューションの受託開発と運用対応
  • コンサルティング(Consulting):業務・ITコンサルからプロンプト設計、導入フロー構築を伴走支援
  • UI/UX・デザイン:アプリ・Webのユーザー体験設計、UI改善により操作性・業務効率を向上
  • 大学発ベンチャーの強み:筑波大学との共同研究実績やAI活用による業務改善プロジェクトに強い

3分でできる! 開発費用のカンタン概算見積もりはこちら

自動見積もり

CONTACT

 

お問い合わせ

 

\まずは15分だけでもお気軽にご相談ください!/

    コメント

    この記事へのコメントはありません。

    関連記事