スタック選定

Python / Go / Next.js など言語・FW の選定観点と具体例。

開発スタック(例)

付録的な技術スタック例。既存プロジェクトでは選定し直さない。

技術スタック選定の観点

スタックは「流行」ではなく、制約・チーム・運用・AI 開発のしやすさから逆算して決める。新規プロジェクトでは Phase 1 の前後で確定し、機能単位の理由は docs/<feature>/04_tech_decisions.md、組織横断の大きな判断は ADR に残す。

選定の原則

  • 既存プロジェクトでは選定し直さない — 既存スタック・lint・CI・rules に合わせる。逸脱は ADR + 明示的承認
  • レイヤごとに決める — 「全部 TypeScript」など一括決定より、言語 / FW / DB / 認証 / 観測を分けて判断する
  • 候補はレイヤあたり最大 2 つ — 比較不能なほど選択肢を増やさない。第三候補が必要なら ADR 化
  • デフォルトはチーム標準 — 新規でも「理由なく別 FW」は避ける。変更するなら trade-off を文章で残す
  • AI 向けに型・テスト・rules を先に決める — スタック確定と同時に .cursor/rules/ の globs と検証コマンド(tsc / pytest / go test)を揃える

7 つの観点軸

各候補を次の軸で 1〜5 段階または「高/中/低」で揃え、弱い軸が許容できるかで絞る。表は Phase 1 や ADR のたたき台にそのまま貼れる。

観点見ること判断の例
1. プロジェクト制約 期限・予算・リリース頻度・規制(金融・医療・個人情報) 2 週間 MVP なら BaaS + マネージド DB。規制業界なら監査ログ・データ residency が先
2. チーム熟練度 言語・FW・クラウドの経験、オンボーディング人数 Go 未経験チーム 3 人なら Python/FastAPI を標準に。学習コストは ADR に明記
3. ドメイン要件 リアルタイム、バッチ、モバイル、AI/RAG、ファイル処理、多言語 WebSocket 多め → 長寿命接続に強いランタイム / インフラ。RAG → pgvector 等(RAG 参考
4. 非機能要件 可用性、レイテンシ p99、同時接続、データ量、RPO/RTO p99 < 100ms が必須なら DB 近接 + キャッシュ設計を先に固定。Serverless のコールドスタートもここ
5. 運用・観測 既存 CI/CD、Secret 管理、ログ基盤、オンコール体制 Datadog 既契約なら OpenTelemetry exporter を統一。trace_id 貫通はフロント/バック共通
6. エコシステム・保守 LTS、CVE 対応、採用実績、ライセンス、ベンダーロックイン Pages Router 廃止方向など「新規非推奨」は採らない。ORM は FW 公式寄りを優先
7. AI 開発適性 型の強さ、テスト速度、rules で縛れるか、ドキュメント量 TypeScript strict + Zod、Go interface + table test は AI 修正のレビューがしやすい

レイヤ別の判断ポイント

「何を使うか」の前に、そのレイヤで何を満たす必要があるかを書く。

レイヤ先に決めることよくある分岐
フロントエンド SEO / SSR 要否、オフライン、管理画面のみか公開サイトか コンポーネント SPA 中心 → React。routing / SSR / Server Actions 一体 → Next.js
バックエンド API 同期 REST 中心か、gRPC/GraphQL か、長時間ジョブの有無 CRUD + OpenAPI 型生成 → Go / Python。Django 管理画面込み → Django
データ トランザクション、全文検索、ベクトル、イベントソーシング PostgreSQL をデフォルト。ベクトルは pgvector または 専用 Vector DB
認証・認可 IdP 連携、B2B SSO、端末種別、セッション vs JWT Next.js なら Auth.js / Clerk。API のみなら OIDC + API Gateway
非同期・ジョブ キュー、スケジュール、再試行、冪等性 AWS なら SQS + Lambda/ECS(Lambda ガイド)。軽量なら DB ベースキュー
ホスティング トラフィック形状、デプロイ頻度、プレビュー環境 Next.js → Vercel。既存 AWS 標準 → Lambda / ECS(クラウド比較
観測 ログ・メトリクス・トレース・エラー監視の一本化 OpenTelemetry を共通。Sentry(FE)+ 構造化ログ(BE)が一般的

選定手順(新規プロジェクト)

  1. 制約と非機能を列挙する要件すり合わせ の成果物から、期限・SLA・データ分類・既存システム連携を抜き出す
  2. チーム標準を確認する — 既存リポジトリ、社内テンプレ、契約中 SaaS。あればそれがデフォルト候補
  3. レイヤごとに候補を 2 つまで絞る — 上記 7 軸でスコアリング。引き分けは「運用コストが低い方」「rules 化しやすい方」
  4. API 契約の方式を決める — OpenAPI / GraphQL / tRPC のいずれか。モノレポなら型生成パイプラインまでセットで決める
  5. Phase 1 で rules と CI を生成する — スタック確定後、AGENTS.md / .cursor/rules/*.mdc に globs・検証コマンド・禁止事項を書く(Phase 1
  6. 理由を docs に残す — 機能単位は 04_tech_decisions.md、組織に効く判断は ADR。採らなかった案と理由を 3 行以上

言語・FW の trade-off 早見

「正解」は 1 つではない。よくある対比と、こういうときに寄せるの目安。

分岐寄せる先(目安)トレードオフ
Python vs Go(API) Python: プロトタイプ・ML 連携・Django 一体 / Go: 高スループット・単一バイナリ・厳格な型 Python は GIL・型の弱さ。Go は ORM エコシステムが薄い分、sqlc 等で補う
FastAPI vs Django FastAPI: 小さな API・OpenAPI 自動生成 / Django: 管理画面・認証・ORM 一体 Django は API のみプロジェクトでは重い。FastAPI は admin が別途必要
React vs Next.js React: 既存 Vite/SPA・埋め込み UI / Next.js: 新規 Web アプリ・SSR・Vercel デプロイ Next.js はフレームワーク opinion が強い。React のみなら routing 等を自前選定
REST vs GraphQL vs tRPC REST+OpenAPI: 多言語クライアント / GraphQL: クライアント主導の取得 / tRPC: TS モノレポ GraphQL は N+1・キャッシュ複雑。tRPC は TS 以外と相性が悪い
Monolith vs マイクロサービス 初期はモノリス(または modular monolith) 分割はデプロイ独立・チーム分割が本当に必要になってから ADR

フロントを早めに絞るなら、コンポーネント中心の SPA が主なら React、routing / SSR / Server Actions まで一体なら Next.js を初期候補にする。Next.js 内で React を使う構成なら両方を前提にしてよい。

記録テンプレ(04_tech_decisions)

Phase 3 プロンプトや手動追記で、次の項目を埋める。AI に書かせるときも同じ見出しを指定する。

## 技術選定: <レイヤ名>

### 背景
- 何を満たす必要があるか(非機能・制約)

### 決定
- 採用: <具体名とバージョン目安>

### 検討した代替案
- 案 A: 不採用理由
- 案 B: 不採用理由

### 影響
- CI / rules / デプロイ / セキュリティ / コスト

### 見直し条件
- 例: 月間リクエスト 10x、チーム +5 人、p99 が SLA 超過

例: Python バックエンドの場合

レイヤ 選択 備考
言語 Python 3.12+ 既存プロジェクトに合わせる
FW FastAPI / Django / Flask プロジェクト方針
DB PostgreSQL / MySQL チーム標準
ORM SQLAlchemy 2.0 / Django ORM FWに揃える
マイグレーション Alembic / Django migrations
テスト pytest + pytest-cov + testcontainers
ログ structlog / 標準logging チーム標準
メトリクス OpenTelemetry + Datadog/Grafana 既存基盤に従う
CI GitHub Actions / GitLab CI 既存基盤

例: Go (Golang) バックエンドの場合

レイヤ 選択 備考
言語 Go 1.22+ log/slog 標準採用のため 1.21+ 推奨
FW Echo / Gin / Chi / 標準 net/http 軽量FW派が主流。小規模なら標準ライブラリのみでも可
DB PostgreSQL / MySQL チーム標準
DB ドライバ pgx (PostgreSQL) / go-sql-driver/mysql 公式 database/sql 経由
クエリ層 sqlc / sqlx / GORM / ent sqlc は SQL→型安全コード生成で実務で人気
マイグレーション golang-migrate / goose / atlas
バリデーション go-playground/validator 構造体タグでルール定義
DI 手書きコンストラクタ注入 / wire (Google) 重いDIフレームワークは少数派
テスト 標準 testing + testify + testcontainers-go テーブル駆動テストが慣習
モック gomock / mockery / 手書き Protocol(interface) を手書きで差し替えるパターンが多い
ログ log/slog (標準, Go 1.21+) / zap / zerolog 新規なら slog 推奨
メトリクス OpenTelemetry + Prometheus / Datadog 標準的
CI GitHub Actions / GitLab CI go test ./... / golangci-lint 必須
Lint golangci-lint 複数linter統合の事実上標準
パッケージ管理 Go Modules (go.mod) 標準

Go 特有の .cursor/rules/20-coding-style.mdc 差分例

---
description: Go コーディング規約
globs: **/*.go
---

# Go Coding Style

## 命名
- 公開: PascalCase, 非公開: camelCase
- パッケージ名: 短く小文字 (例: user, order)
- インタフェース名: 通常は -er サフィックス (Reader, Writer, UserRepository)

## エラーハンドリング
- error は早期 return。ネストを深くしない
- 業務エラーは独自型 (`var ErrInsufficientStock = errors.New("...")` または独自struct + `errors.Is/As`)
- パニックは原則使わない (recoverもライブラリ境界のみ)
- ラップは `fmt.Errorf("doing X: %w", err)`

## 並行性
- goroutine の起動箇所には必ず終了条件 (context.Context / chan close) を用意
- channel の close は送信側のみ
- 共有メモリより通信 (channel) を優先、ただし sync.Mutex を恐れない

## context
- 公開関数の第1引数は context.Context
- context は構造体に保持しない

## テスト
- t.Run でサブテスト + テーブル駆動
- t.Parallel() でレース検出
- ヘルパは t.Helper() を呼ぶ

例: Next.js + React フロントエンドの場合

レイヤ 選択 備考
言語 TypeScript 5+ strict: true 必須
FW Next.js 15+ (App Router) Pages Routerは新規採用しない
UI ライブラリ React 19 Server Components + Server Actions 活用
スタイリング Tailwind CSS + shadcn/ui カスタムCSSは最小限
状態管理 (Server) React Server Components + Server Actions デフォルトはサーバー側で完結
状態管理 (Client) Zustand / Jotai / TanStack Query グローバル/サーバー状態の使い分け
フォーム React Hook Form + Zod サーバー側でも Zod で再検証
スキーマ検証 Zod API境界・フォーム・環境変数すべてに使う
認証 Auth.js (NextAuth) / Clerk プロバイダ対応で選ぶ
API クライアント TanStack Query / SWR / fetch RSC優先、必要時のみ
テスト (ユニット) Vitest + React Testing Library Jest互換だが高速
テスト (E2E) Playwright Cypressより推奨派が増えている
ログ pino (サーバー) / 標準 console (ブラウザ) クライアント側はSentry等で集約
観測 OpenTelemetry + Vercel Analytics / Sentry エラー監視は Sentry が一般的
パッケージ管理 pnpm 高速・ディスク効率
Lint / Format ESLint + Prettier / Biome Biomeは新興だが高速
型生成 OpenAPI Generator / GraphQL Codegen / tRPC バックエンドAPIから型を引く
CI GitHub Actions tsc --noEmit / lint / test / build
ホスティング Vercel / Cloud Run / 自前Node Next.js は Vercel が最適化されている

Next.js 特有の .cursor/rules/20-coding-style.mdc 差分例

---
description: Next.js / React コーディング規約
globs: **/*.{ts,tsx}
---

# Next.js / React Coding Style

## ファイル配置 (App Router)
- ルーティング: app/<segment>/page.tsx
- レイアウト: app/<segment>/layout.tsx
- API: app/api/<endpoint>/route.ts
- 共通コンポーネント: components/
- 業務ロジック: lib/ または domain/
- 型: types/ または同居の types.ts

## サーバー / クライアントの境界
- デフォルトは Server Component
- "use client" は必要最小限のリーフコンポーネントのみ
- Server Action は app/actions/ または同居の actions.ts に集約
- フォームは Server Action 経由を優先

## TypeScript
- any 禁止 (どうしても必要なら unknown + 型ガード)
- 公開関数には引数/戻り値の型を明示
- API境界は Zod で実行時検証
- 環境変数も Zod でパース (process.env.* を直接使わない)

## コンポーネント設計
- Props は interface ではなく type
- children は ReactNode
- 副作用は useEffect 最小化、Server Component で済むなら使わない
- イベントハンドラは on* 命名

## アクセシビリティ
- セマンティックHTML優先 (div の濫用禁止)
- 画像は next/image、alt 必須
- フォームは label + input の関連付け
- キーボード操作可能を維持

## パフォーマンス
- 動的import (`next/dynamic`) で初期バンドル削減
- 画像最適化は next/image 必須
- Suspense + Streaming を活用
- "use client" を上位に置きすぎない (バンドルが膨らむ)

## テスト
- ユニット: Vitest + React Testing Library (`screen.getByRole` 優先、`getByTestId` は最終手段)
- E2E: Playwright で主要動線
- アクセシビリティ: axe / @testing-library/jest-dom

フロント / バックエンド共通の留意点

  • モノレポ運用: フロントとバックが同居するなら pnpm workspaces / Turborepo / Nx を検討。Cursor では .cursor/rules/、Claude Code では CLAUDE.md / .claude/skills/、Codex では AGENTS.md / .agents/skills/ をサブパッケージ単位で重ねられる
  • API 契約: OpenAPI / GraphQL / tRPC のいずれかで型を一元化。Go backend + Next.js なら OpenAPI からの自動生成が現実的
  • エラー連携: フロント・バック・ログ基盤で trace_id を貫通させる (OpenTelemetry)
  • 環境変数: 12-factor app に従い .env で分離、本番は基盤側のSecret Manager

既存プロジェクトでは選定し直さない。既存スタックに合わせるのが原則。新規導入が必要なら docs/04_tech_decisions.md に理由を残す。