Skip to content

技術選定の原則

🎯 技術選定フレームワーク:ポケモン「パーティ編成」で理解する技術選択

Section titled “🎯 技術選定フレームワーク:ポケモン「パーティ編成」で理解する技術選択”

📝 ポケモン世界における技術選定の定義

Section titled “📝 ポケモン世界における技術選定の定義”

技術選定とは、**「最強の6匹パーティを組む」**ことです。React vs Vue、PostgreSQL vs MongoDB、AWS vs GCP——それぞれに強み・弱みがある。ポケモンでいえば、ガブリアス(物理アタッカー)、サンダー(特殊アタッカー)、ハピナス(受け)——役割分担とシナジーでパーティを組むのがプロの選び方です。


技術選定では、機能要件・非機能要件・コスト・学習コストなどを総合的に評価する必要がある。

【ポケモン版・マサカリ的実務視点】

Section titled “【ポケモン版・マサカリ的実務視点】”
評価軸ポケモン的解釈実務での重要度失敗パターン
1. 機能適合性「タイプ相性」——やりたいことに合っているか⭐⭐⭐⭐⭐Node.jsで機械学習しようとする(Pythonが適材)
2. 成熟度「進化済みか」——枯れた技術か実験的か⭐⭐⭐⭐新興フレームワークで大規模システム構築
3. コミュニティ「育て屋の数」——情報・サポートの豊富さ⭐⭐⭐⭐⭐マイナー言語で詰まり、Stack Overflowに回答ゼロ
4. 採用コスト「個体値厳選の手間」——習得難易度とエンジニア確保⭐⭐⭐⭐Haskellで開発→人材が見つからず炎上
5. 運用コスト「わざマシン代」——インフラ・保守費用⭐⭐⭐⭐⭐自前Kubernetesで運用地獄
6. 脱出コスト「ボールから逃げられない」——乗り換えの難易度⭐⭐⭐ベンダーロックイン(AWS専用機能に依存)

2. 🎮 技術選定の4ステップ:パーティ編成手順

Section titled “2. 🎮 技術選定の4ステップ:パーティ編成手順”

Step 1: 要件定義(「対戦ルール確認」)

Section titled “Step 1: 要件定義(「対戦ルール確認」)”

ポケモンでいえば: シングルかダブルか、伝説禁止か——ルールを知らずにパーティは組めない

実務でやること:

  1. 機能要件: 何を作るのか?(ECサイト、リアルタイムチャット、機械学習API)
  2. 非機能要件: どれくらいのスケールか?(100人、10万人、1億人)
  3. 制約条件: 予算、納期、既存システムとの連携
// 要件定義テンプレート
interface TechRequirements {
// 機能要件
features: {
realtime: boolean; // WebSocket必要?
auth: "simple" | "oauth" | "saml";
fileUpload: boolean; // 画像・動画扱う?
search: "basic" | "fulltext" | "vector"; // 検索機能
};
// 非機能要件
scale: {
users: number; // 想定ユーザー数
requests: number; // 秒間リクエスト数
dataSize: string; // データ量("10GB", "1TB"等)
};
// 制約条件
constraints: {
budget: number; // 月額予算(円)
deadline: string; // 納期
teamSize: number; // チーム人数
existingStack: string[]; // 既存技術スタック
};
}
// 例:スタートアップのMVP
const mvpRequirements: TechRequirements = {
features: {
realtime: false,
auth: "oauth",
fileUpload: true,
search: "basic"
},
scale: {
users: 1000, // 初期ユーザー1000人
requests: 10, // 秒間10リクエスト
dataSize: "10GB"
},
constraints: {
budget: 50000, // 月5万円
deadline: "2026-10-01", // 3ヶ月後
teamSize: 3, // 開発者3人
existingStack: ["TypeScript", "React"]
}
};

Step 2: 候補技術の洗い出し(「図鑑を開く」)

Section titled “Step 2: 候補技術の洗い出し(「図鑑を開く」)”

ポケモンでいえば: 全ポケモン900種から、候補を3~5匹に絞る

実務でやること: 各レイヤーで候補を2~3個に絞る。

レイヤー候補例
フロントエンドReact, Vue, Svelte
バックエンドNode.js, Go, Python
データベースPostgreSQL, MongoDB, MySQL
インフラAWS, GCP, Vercel
CI/CDGitHub Actions, GitLab CI, CircleCI

落とし穴(死の谷):

  • 全技術を検討→時間切れ
  • 流行りに飛びつく→Bun、Denoで詰まる
  • メジャー3択に絞る→情報豊富で安全

Step 3: 比較評価(「種族値・技範囲チェック」)

Section titled “Step 3: 比較評価(「種族値・技範囲チェック」)”

ポケモンでいえば: ガブリアス(攻撃130、素早102)vs ボーマンダ(攻撃135、素早100)——数値で比較

実務でやること: スコアリングシートで定量評価。

// スコアリングシート例
interface TechScoreCard {
technology: string;
scores: {
functionality: number; // 機能適合性(1-5)
maturity: number; // 成熟度(1-5)
community: number; // コミュニティ(1-5)
hiring: number; // 採用しやすさ(1-5)
operationalCost: number; // 運用コスト(1-5、高いほど安い)
vendorLock: number; // ベンダーロックイン回避(1-5)
};
totalScore: number; // 合計点
notes: string; // 備考
}
// 例:フロントエンドフレームワーク比較
const frameworkComparison: TechScoreCard[] = [
{
technology: "React",
scores: {
functionality: 5, // 何でもできる
maturity: 5, // 10年の実績
community: 5, // 最大のコミュニティ
hiring: 5, // 人材豊富
operationalCost: 4, // CDN配信で安価
vendorLock: 5 // Meta製だがOSS
},
totalScore: 29,
notes: "鉄板。迷ったらReact。"
},
{
technology: "Vue",
scores: {
functionality: 5,
maturity: 4, // Reactより新しい
community: 4, // Reactより小さい
hiring: 3, // 日本では人材少なめ
operationalCost: 4,
vendorLock: 5
},
totalScore: 25,
notes: "学習コストが低い。中国で人気。"
},
{
technology: "Svelte",
scores: {
functionality: 4, // エコシステム小さめ
maturity: 3, // まだ若い
community: 3, // 成長中
hiring: 2, // 人材確保困難
operationalCost: 5, // 超軽量
vendorLock: 5
},
totalScore: 22,
notes: "パフォーマンス最高だが、採用リスク。"
}
];
// スコアリング関数
function calculateScore(card: TechScoreCard): number {
const { scores } = card;
return Object.values(scores).reduce((sum, score) => sum + score, 0);
}
// 重み付けバージョン
function calculateWeightedScore(
card: TechScoreCard,
weights: Record<keyof TechScoreCard["scores"], number>
): number {
const { scores } = card;
return Object.entries(scores).reduce((sum, [key, score]) => {
return sum + score * weights[key as keyof typeof scores];
}, 0);
}
// 例:スタートアップは「採用しやすさ」と「コミュニティ」重視
const startupWeights = {
functionality: 1.0,
maturity: 0.8,
community: 1.5, // 情報多い方が良い
hiring: 2.0, // 人材確保が最優先
operationalCost: 1.0,
vendorLock: 0.5 // 初期は気にしない
};
// 例:大企業は「成熟度」と「ベンダーロックイン回避」重視
const enterpriseWeights = {
functionality: 1.5,
maturity: 2.0, // 枯れた技術優先
community: 1.0,
hiring: 1.5,
operationalCost: 1.0,
vendorLock: 2.0 // ロックイン回避必須
};

Step 4: 意思決定(「パーティ確定」)

Section titled “Step 4: 意思決定(「パーティ確定」)”

ポケモンでいえば: 種族値だけでなく、**「環境(メタ)」**も考慮。カイリュー強いけど、フェアリー環境なら厳しい。

実務でやること: スコアだけでなく、チームの経験・文化・戦略も考慮。

// 意思決定フレームワーク
interface DecisionFactors {
// 定量評価
technicalScore: number; // スコアリングシート結果
// 定性評価
teamExperience: {
technology: string;
experiencedMembers: number;
totalMembers: number;
}[];
// 戦略的判断
strategic: {
futureProofing: boolean; // 5年後も使えるか
competitiveAdvantage: boolean; // 差別化できるか
riskTolerance: "low" | "medium" | "high"; // リスク許容度
};
}
// 例:スタートアップの意思決定
const decision: DecisionFactors = {
technicalScore: 29, // Reactが最高点
teamExperience: [
{ technology: "React", experiencedMembers: 3, totalMembers: 3 },
{ technology: "Vue", experiencedMembers: 1, totalMembers: 3 },
{ technology: "Svelte", experiencedMembers: 0, totalMembers: 3 }
],
strategic: {
futureProofing: true, // Reactは10年実績
competitiveAdvantage: false, // Reactは差別化にならない
riskTolerance: "low" // スタートアップだがMVPなので堅実に
}
};
// 結論: React採用(全員経験あり、リスク低)

3. 🚨 技術選定の5大失敗パターン

Section titled “3. 🚨 技術選定の5大失敗パターン”

失敗1: 「流行りに飛びつく」(新技術症候群)

Section titled “失敗1: 「流行りに飛びつく」(新技術症候群)”

ポケモンでいえば: 新ポケモン強そう→育成不足で対戦で負ける。

症状実例処方箋
HackerNewsの最新技術を即採用Bun、Deno、Fresh等を本番投入2年以上実績のある技術を選ぶ
GitHub Starだけで判断Star数多いが、メンテナンス停止最終コミット日・Issue対応率を確認
「○○キラー」に惹かれる”Webpack Killer”で導入→結局Webpack併用移行コストを試算する
// 技術成熟度チェックリスト
interface MaturityChecklist {
firstRelease: string; // 初回リリース日
latestRelease: string; // 最新リリース日
majorVersions: number; // メジャーバージョン数
githubStars: number; // GitHub Star数
weeklyDownloads: number; // npm週間DL数
openIssues: number; // 未解決Issue数
issueResponseTime: number; // Issue平均応答時間(日)
productionUsers: string[]; // 本番採用企業例
}
// 成熟度判定関数
function assessMaturity(tech: MaturityChecklist): "mature" | "growing" | "experimental" {
const age = new Date().getFullYear() - new Date(tech.firstRelease).getFullYear();
// 成熟技術の条件
if (
age >= 3 &&
tech.majorVersions >= 1 &&
tech.weeklyDownloads > 100000 &&
tech.productionUsers.length > 10
) {
return "mature";
}
// 成長技術の条件
if (
age >= 1 &&
tech.weeklyDownloads > 10000 &&
tech.issueResponseTime < 7
) {
return "growing";
}
// それ以外は実験的
return "experimental";
}
// 例:Next.js(成熟)
const nextjs: MaturityChecklist = {
firstRelease: "2016-10-25",
latestRelease: "2026-07-01",
majorVersions: 15,
githubStars: 120000,
weeklyDownloads: 5000000,
openIssues: 500,
issueResponseTime: 2,
productionUsers: ["Netflix", "TikTok", "Twitch"]
};
// → "mature"
// 例:Qwik(成長中)
const qwik: MaturityChecklist = {
firstRelease: "2021-07-01",
latestRelease: "2026-06-15",
majorVersions: 1,
githubStars: 20000,
weeklyDownloads: 50000,
openIssues: 150,
issueResponseTime: 5,
productionUsers: ["Builder.io"]
};
// → "growing"

失敗2: 「オーバーエンジニアリング」(無駄な強さ)

Section titled “失敗2: 「オーバーエンジニアリング」(無駄な強さ)”

ポケモンでいえば: ストーリー攻略にレベル100ミュウツー6匹——オーバーキル

症状実例処方箋
小規模サービスにKubernetes月間1000PVのブログをK8sでデプロイVercel/Netlifyで十分
マイクロサービス地獄3人チームで20個のサービス分割モノリスから始める
GraphQL導入REST APIで十分な単純CRUD必要になってから
// 適切な技術レベルの選択
interface ServiceScale {
monthlyUsers: number;
teamSize: number;
complexity: "low" | "medium" | "high";
}
function recommendArchitecture(scale: ServiceScale): string {
// 小規模(月1万PV以下、チーム5人以下)
if (scale.monthlyUsers < 10000 && scale.teamSize <= 5) {
return "Vercel/Netlify + Supabase(サーバーレス)";
}
// 中規模(月100万PV以下、チーム20人以下)
if (scale.monthlyUsers < 1000000 && scale.teamSize <= 20) {
return "Heroku/Cloud Run(コンテナ)+ Managed DB";
}
// 大規模(月100万PV以上、チーム20人以上)
if (scale.complexity === "high") {
return "Kubernetes + マイクロサービス";
} else {
return "モノリス(Rails/Django) + CDN";
}
}
// 例:スタートアップMVP
console.log(recommendArchitecture({
monthlyUsers: 5000,
teamSize: 3,
complexity: "low"
}));
// → "Vercel/Netlify + Supabase(サーバーレス)"
// 例:成長企業
console.log(recommendArchitecture({
monthlyUsers: 500000,
teamSize: 15,
complexity: "medium"
}));
// → "Heroku/Cloud Run(コンテナ)+ Managed DB"

失敗3: 「Not Invented Here症候群」(車輪の再発明)

Section titled “失敗3: 「Not Invented Here症候群」(車輪の再発明)”

ポケモンでいえば: 既存の強ポケモンを使わず、マイナーポケモンで無理やり戦う。

症状実例処方箋
認証を自作JWT実装をゼロから書く→脆弱性だらけAuth0/Clerk使う
ORMを使わない生SQLで全部書く→SQLインジェクションPrisma/Drizzle使う
ログ基盤を自作fluentd + Elasticsearch自前構築→運用地獄Datadog/CloudWatch使う
// Buy vs Build判断基準
interface BuyVsBuildDecision {
feature: string;
isCoreCompetency: boolean; // コア競争力か?
implementationCost: number; // 開発工数(人日)
maintenanceCost: number; // 年間保守工数(人日)
buyOption: {
product: string;
monthlyCost: number; // 月額費用(円)
setupCost: number; // 初期費用(円)
} | null;
}
function decideBuyOrBuild(decision: BuyVsBuildDecision): "buy" | "build" {
// コア競争力なら自作
if (decision.isCoreCompetency) {
return "build";
}
// Buy optionがない場合は自作
if (!decision.buyOption) {
return "build";
}
// 3年間のコスト比較
const buildCost3Years =
decision.implementationCost * 800000 + // 実装(人日80万円)
decision.maintenanceCost * 800000 * 3; // 保守3年分
const buyCost3Years =
decision.buyOption.setupCost +
decision.buyOption.monthlyCost * 36; // 3年分
// Buyの方が安ければBuy
return buyCost3Years < buildCost3Years ? "buy" : "build";
}
// 例:認証機能
const authDecision: BuyVsBuildDecision = {
feature: "認証(OAuth、MFA)",
isCoreCompetency: false, // 認証は差別化にならない
implementationCost: 30, // 実装30人日
maintenanceCost: 10, // 年間保守10人日
buyOption: {
product: "Auth0",
monthlyCost: 30000, // 月3万円
setupCost: 0
}
};
console.log(decideBuyOrBuild(authDecision));
// → "buy"(3年で1080万円 vs 3000万円)
// 例:推薦エンジン(EC独自ロジック)
const recommendationDecision: BuyVsBuildDecision = {
feature: "推薦エンジン",
isCoreCompetency: true, // ビジネスのコア
implementationCost: 100,
maintenanceCost: 20,
buyOption: null // 独自ロジックなのでBuy不可
};
console.log(decideBuyOrBuild(recommendationDecision));
// → "build"

失敗4: 「ベンダーロックイン」(ボールから逃げられない)

Section titled “失敗4: 「ベンダーロックイン」(ボールから逃げられない)”

ポケモンでいえば: マスターボールで捕獲→逃げられない。

症状実例処方箋
AWS専用機能に依存Lambda + DynamoDB + API Gateway全結合抽象化レイヤー作成
Firebase全依存Firestore + Functions + Auth全部使用段階的移行計画
ノーコードツールで構築Bubble.ioで全システム→移行不可コード資産化
// ベンダーロックイン度チェック
interface VendorLockInAssessment {
service: string;
proprietary: string[]; // ベンダー独自機能
standard: string[]; // 標準仕様
migrationCost: number; // 移行工数(人日)
}
function assessLockIn(assessment: VendorLockInAssessment): "low" | "medium" | "high" {
const proprietaryRatio =
assessment.proprietary.length /
(assessment.proprietary.length + assessment.standard.length);
if (proprietaryRatio > 0.7 || assessment.migrationCost > 100) {
return "high";
}
if (proprietaryRatio > 0.4 || assessment.migrationCost > 50) {
return "medium";
}
return "low";
}
// 例:AWS Lambda(中程度)
const lambdaLockIn: VendorLockInAssessment = {
service: "AWS Lambda",
proprietary: [
"Lambda固有のハンドラー",
"EventBridge統合",
"IAMロール"
],
standard: [
"Node.js/Python実行環境",
"HTTPリクエスト処理",
"環境変数"
],
migrationCost: 30 // 他クラウドへ移行30人日
};
// → "medium"
// 例:Firestore(高)
const firestoreLockIn: VendorLockInAssessment = {
service: "Firestore",
proprietary: [
"Firestore固有クエリ",
"セキュリティルール",
"リアルタイム同期",
"オフラインサポート"
],
standard: [
"JSONドキュメント"
],
migrationCost: 150 // PostgreSQLへ移行150人日
};
// → "high"
// ロックイン回避戦略
interface LockInMitigation {
strategy: string;
implementation: string;
}
const mitigationStrategies: LockInMitigation[] = [
{
strategy: "抽象化レイヤー",
implementation: `
// リポジトリパターンでDB抽象化
interface UserRepository {
findById(id: string): Promise<User | null>;
save(user: User): Promise<void>;
}
// Firestore実装
class FirestoreUserRepository implements UserRepository {
async findById(id: string) { /* Firestore固有処理 */ }
async save(user: User) { /* Firestore固有処理 */ }
}
// PostgreSQL実装(移行時に作成)
class PostgresUserRepository implements UserRepository {
async findById(id: string) { /* PostgreSQL固有処理 */ }
async save(user: User) { /* PostgreSQL固有処理 */ }
}
`
},
{
strategy: "標準プロトコル優先",
implementation: `
// ❌ ベンダー固有
const queue = new AWS.SQS();
// ✅ 標準プロトコル(AMQP)
import amqp from 'amqplib';
const queue = await amqp.connect('amqp://rabbitmq'); // RabbitMQ、AWS MQ両対応
`
}
];

失敗5: 「人材不足で詰む」(育て屋がいない)

Section titled “失敗5: 「人材不足で詰む」(育て屋がいない)”

ポケモンでいえば: レアポケモン捕獲→育成方法が分からず放置。

症状実例処方箋
Haskell採用→誰も書けない関数型言語に憧れ→チーム全滅TypeScriptにする
Rust採用→学習コスト高パフォーマンス重視→納期遅延GoかJavaにする
マイナーフレームワークElm、PureScript等→採用困難React/Vueにする
// 人材確保しやすさスコア
interface TalentAvailability {
technology: string;
jobPostings: number; // 求人数
averageSalary: number; // 平均年収(万円)
learningCurve: "easy" | "medium" | "hard"; // 学習難易度
bootcampSupport: boolean; // スクール対応
}
const talentData: TalentAvailability[] = [
{
technology: "JavaScript/TypeScript",
jobPostings: 10000,
averageSalary: 600,
learningCurve: "easy",
bootcampSupport: true
},
{
technology: "Python",
jobPostings: 8000,
averageSalary: 650,
learningCurve: "easy",
bootcampSupport: true
},
{
technology: "Go",
jobPostings: 3000,
averageSalary: 700,
learningCurve: "medium",
bootcampSupport: false
},
{
technology: "Rust",
jobPostings: 500,
averageSalary: 800,
learningCurve: "hard",
bootcampSupport: false
},
{
technology: "Haskell",
jobPostings: 50,
averageSalary: 900,
learningCurve: "hard",
bootcampSupport: false
}
];
// 採用しやすさスコア
function talentScore(tech: TalentAvailability): number {
let score = 0;
// 求人数(多いほど高得点)
if (tech.jobPostings > 5000) score += 5;
else if (tech.jobPostings > 1000) score += 3;
else score += 1;
// 学習難易度(簡単ほど高得点)
if (tech.learningCurve === "easy") score += 5;
else if (tech.learningCurve === "medium") score += 3;
else score += 1;
// スクール対応(あれば+3点)
if (tech.bootcampSupport) score += 3;
return score;
}
// 結果
talentData.forEach(tech => {
console.log(`${tech.technology}: ${talentScore(tech)}`);
});
// JavaScript/TypeScript: 13点(最高)
// Python: 13点
// Go: 6点
// Rust: 4点
// Haskell: 1点(最低)

法則1: Boring Technology(退屈な技術を選べ)

Section titled “法則1: Boring Technology(退屈な技術を選べ)”

ポケモンでいえば: ガブリアス、ボーマンダ——昔から強い定番ポケモンを使う。

// Boring Technology Checklist
const boringTechPrinciples = [
"最新ではなく、枯れた技術を選ぶ",
"3年以上の実績がある技術を優先",
"大企業が本番採用している技術",
"Stack Overflowで回答が豊富",
"採用市場で人材が見つかる"
];
// 例:MVPで選ぶべき技術スタック
const mvpStack = {
frontend: "React + TypeScript", // 10年の実績
backend: "Node.js (Express)", // 15年の実績
database: "PostgreSQL", // 30年の実績
hosting: "Vercel", // Next.js最適化
auth: "Auth0 or Clerk" // 既製品
};

法則2: The Right Tool for the Job(適材適所)

Section titled “法則2: The Right Tool for the Job(適材適所)”

ポケモンでいえば: 水ジム攻略に電気ポケモン——タイプ相性

ユースケース最適技術理由
リアルタイムチャットWebSocket (Socket.io)双方向通信必須
静的サイトAstro / Next.js SSGSEO・高速化
大量データ分析Python (Pandas/Polars)ライブラリ豊富
システムプログラミングRust / Goメモリ安全・並行処理
機械学習Python (PyTorch/TensorFlow)デファクトスタンダード

法則3: 段階的導入(いきなり進化させない)

Section titled “法則3: 段階的導入(いきなり進化させない)”

ポケモンでいえば: Lv5から育成——いきなりLv100にしない

// 段階的技術導入計画
interface TechAdoptionPhase {
phase: string;
goal: string;
technologies: string[];
duration: string;
}
const adoptionPlan: TechAdoptionPhase[] = [
{
phase: "Phase 1: MVP(最小構成)",
goal: "3ヶ月で市場投入",
technologies: [
"Next.js(フルスタック)",
"Vercel(ホスティング)",
"Supabase(DB + Auth)"
],
duration: "3ヶ月"
},
{
phase: "Phase 2: スケール対応",
goal: "月10万PV対応",
technologies: [
"CDN(Cloudflare)追加",
"Redis(キャッシュ)追加",
"Datadog(監視)追加"
],
duration: "6ヶ月"
},
{
phase: "Phase 3: マイクロサービス化",
goal: "チーム20人体制",
technologies: [
"Kubernetes(オーケストレーション)",
"gRPC(サービス間通信)",
"Kafka(イベント駆動)"
],
duration: "1年"
}
];

技術選定の意思決定を記録する標準フォーマット。

# ADR-001: フロントエンドフレームワークの選定
## ステータス
採用
## コンテキスト
ECサイトのフロントエンド構築にあたり、React、Vue、Svelteの3つを検討。
チームは3人(全員React経験あり)、納期は3ヶ月。
## 決定
Reactを採用。
## 根拠
- チーム全員がReact経験あり(学習コストゼロ)
- Next.jsでSSR・SSG対応可能
- コミュニティ最大(問題解決容易)
- 採用市場で人材確保容易
## 代替案
- Vue: 学習コスト低いが、チームに経験者少ない
- Svelte: パフォーマンス高いが、エコシステム小さい
## 影響
- 開発速度向上(学習不要)
- 採用コスト低減
- ベンダーロックインリスク低(OSS)
## 関連
- ADR-002: Next.jsの採用
- ADR-003: TypeScriptの導入

鉄則ポケモン的解釈実務適用
1. 枯れた技術を選ぶ定番ポケモン使用React、PostgreSQL、AWS
2. 適材適所タイプ相性リアルタイム→WebSocket
3. チームスキル重視育て屋の数全員経験ある技術
4. 段階的導入Lv5から育成MVP→スケール→最適化
5. ロックイン回避逃げられる準備抽象化レイヤー作成

最重要原則:

「技術は手段であり、目的ではない」——ビジネス価値を最大化する技術を選べ

ポケモンでいえば:

「好きなポケモンではなく、勝てるポケモンを選べ」——対戦環境(ビジネス要件)に合わせる