404 Not Found

404 Not Found


nginx

プロジェクト設計

これでフェーズ1〜4の全内容が完了しました。Charlieはこの知識を統合して, 完全なMegaShop eコマースプラットフォームを設計します。要件分析からアーキテクチャ設計, データモデルからAPI仕様まで, これが実践プロジェクトの第一歩です。

1. 学ぶ内容


2. アーキテクトのリアルストーリー

(1) ペインポイント:設計なしの開発

Charlieは以前, 設計ドキュメントなしでチームにすぐコードを書かせました。その結果, Aliceのショッピングカートのデータ構造がBobの注文データと合わず, APIの命名は混沌とし, データベースにはインデックスがなく, クエリは遅く, 後からの変更コストは膨大でした。

(2) システム設計ソリューション

設計先行, その後に開発 - ER図でデータモデルを定義し, RESTful仕様でAPIを定義し, アーキテクチャ図でシステム境界を定義します。設計フェーズに1週間多く費やせば, 開発中に3週間節約できます。

(3) 利点:明確なロードマップ

すべての開発者が同じ設計ドキュメントを参照し - 一貫したデータ構造, 統一されたAPI仕様, 明確なアーキテクチャ境界 - があれば, 協調効率は3倍に向上します。


3. 要件分析

(1) ユーザーロールとコアニーズ

ロール アイデンティティ コアニーズ 主要指標
Alice 消費者 閲覧/検索/カート追加/購入/レビュー 初回画面 < 2s, 検索 < 500ms
Bob 管理者 商品管理/注文処理/ユーザー管理 CRUD応答 < 200ms
Charlie アーキテクト システム安定性/高性能/スケーラビリティ 99.9%可用性, 100万商品対応

(2) 機能モジュール分割

モジュール 機能 優先度 影響ページ
認証 サインアップ/サインイン/OAuth2/JWT P0 /login, /register
商品 CRUD/検索/カテゴリ/フィルタ P0 /products, /products/[id]
ショッピングカート カート追加/数量変更/削除/クリア P0 /cart
注文 作成/支払い/ステータス確認 P0 /checkout, /orders
ユーザー 個人情報/住所/レビュー P1 /profile
管理 バックエンドCRUD/統計/モデレーション P1 /admin/**
国際化 中国語/英語/日本語 + マルチ通貨 P1 グローバル
SEO 動的meta/Sitemap/JSON-LD P0 商品ページ

4. アーキテクチャ設計

(1) MegaShopシステムアーキテクチャ概要

100%
graph TB
    subgraph Client["クライアント層"]
        Browser[ブラウザ / モバイル]
        Bot[検索エンジンボット]
    end

    subgraph CDN["CDN層"]
        CF[Cloudflare / Vercel Edge]
    end

    subgraph Nuxt["Nuxt 3アプリケーション"]
        SSR[SSRエンジン]
        ISR[ISRキャッシュ]
        API[Nitro APIルート]
        MW[ミドルウェア / 認証]
    end

    subgraph Data["データ層"]
        PG[(PostgreSQL)]
        Redis[(Redisキャッシュ)]
        S3[オブジェクトストレージ / 画像]
    end

    subgraph External["外部サービス"]
        Stripe[Stripe決済]
        Google[Google OAuth2]
        Analytics[アナリティクスサービス]
    end

    Browser --> CDN
    Bot --> CDN
    CDN --> SSR
    CDN --> ISR
    SSR --> API
    API --> MW
    API --> PG
    API --> Redis
    API --> S3
    API --> Stripe
    API --> Google
    API --> Analytics
    ISR --> Redis

(2) レンダリング戦略設計

ページタイプ レンダリングモード swr 理由
ホーム SSG - 安定したコンテンツ
商品一覧 ISR 3600s 毎時更新
商品詳細 ISR 86400s 毎日更新
検索結果 SSR - リアルタイムクエリ
カート/チェックアウト CSR - 会員専用
管理ダッシュボード CSR - SEO不要
APIルーティング 動的 - オンデマンドキャッシュ

(3) 技術スタックの選定

(1) ▶サンプル:nuxt.config.ts技術スタック統合

TYPESCRIPT
// nuxt.config.ts - 完全な技術スタック統合
export default defineNuxtConfig({
  ssr: true,
  modules: [
    '@pinia/nuxt',
    '@nuxtjs/tailwindcss',
    '@nuxtjs/i18n',
    '@nuxtjs/sitemap',
    '@nuxt/image',
    '~/modules/analytics'
  ],
  i18n: {
    locales: [
      { code: 'en', name: 'English', file: 'en.json', currency: 'USD' },
      { code: 'zh', name: 'Chinese', file: 'zh.json', currency: 'CNY' },
      { code: 'ja', name: 'Japanese', file: 'ja.json', currency: 'JPY' }
    ],
    defaultLocale: 'en',
    lazy: true,
    langDir: 'locales/'
  },
  image: { quality: 80, format: ['webp', 'avif'] }
})

出力:

TEXT
// 実行成功

(2) ▶サンプル:Docker Composeサービスオーケストレーション

YAML
# docker-compose.yml - インフラ定義
services:
  web:
    build: .
    ports: ["3000:3000"]
    depends_on: [db, redis]
  db:
    image: postgres:16-alpine
    volumes: [postgres_data:/var/lib/postgresql/data]
  redis:
    image: redis:7-alpine
    volumes: [redis_data:/data]
  nginx:
    image: nginx:alpine
    ports: ["80:80", "443:443"]
    depends_on: [web]

出力:

TEXT
CONTAINER ID   IMAGE          STATUS         PORTS
abc123         nginx:latest   Up 2 hours     0.0.0.0:80->80/tcp
技術 選定理由
フレームワーク Nuxt 3 SSR/ISR/CSRハイブリッドレンダリング
UI Vue 3 + TailwindCSS リアクティブ + 迅速な開発
状態管理 Pinia Vue 3公式ソリューション + SSR対応
データベース PostgreSQL + Prisma 型安全ORM + 数百万クエリ対応
キャッシュ Redis + Nitro KV APIキャッシュ + ISRストレージ
認証 JWT + OAuth2 ステートレス + ソーシャルログイン
国際化 @nuxtjs/i18n 多言語 + SEO hreflang
画像 @nuxt/image WebP/AVIF + レスポンシブ
テスト Vitest + Playwright ユニット + E2E
デプロイ Docker Compose フルスタックサービスオーケストレーション
CI/CD GitHub Actions 自動化パイプライン

5. データモデル設計

(1) ER図

100%
erDiagram
    User ||--o{ Order : "注文する"
    User ||--o{ Review : "レビューする"
    User ||--o{ CartItem : "持つ"
    User ||--o{ Address : "所有する"
    Product ||--o{ OrderItem : "含まれる"
    Product ||--o{ CartItem : "追加される"
    Product ||--o{ Review : "受ける"
    Product ||--o{ ProductImage : "持つ"
    Product }o--|| Category : "属する"
    Category ||--o{ Category : "親子"
    Order ||--o{ OrderItem : "含む"
    Order }o--|| Address : "配送先"

(2) コアテーブル設計

(1) ▶サンプル:コアPrismaスキーマ

PRISMA
// prisma/schema.prismaの主要モデル
model Product {
  id          Int       @id @default(autoincrement())
  name        String
  slug        String    @unique
  price       Decimal   @db.Decimal(10, 2)
  inStock     Boolean   @default(true)
  categoryId  Int
  category    Category  @relation(fields: [categoryId], references: [id])
  orderItems  OrderItem[]
  cartItems   CartItem[]
  @@index([categoryId])
  @@index([price])
}

model Order {
  id        Int       @id @default(autoincrement())
  userId    Int
  user      User      @relation(fields: [userId], references: [id])
  total     Decimal   @db.Decimal(10, 2)
  status    OrderStatus @default(PENDING)
  items     OrderItem[]
  @@index([userId])
  @@index([status])
}

出力:

TEXT
// 実行成功

(2) ▶サンプル:APIエラーコード定義

TYPESCRIPT
// server/utils/errors.ts
export const ErrorCodes = {
  VALIDATION_ERROR: { statusCode: 400, message: 'Validation error' },
  AUTH_REQUIRED: { statusCode: 401, message: 'Authentication required' },
  TOKEN_EXPIRED: { statusCode: 401, message: 'Token expired' },
  FORBIDDEN: { statusCode: 403, message: 'Insufficient permissions' },
  NOT_FOUND: { statusCode: 404, message: 'Resource not found' },
  CONFLICT: { statusCode: 409, message: 'Resource conflict' },
  RATE_LIMITED: { statusCode: 429, message: 'Too many requests' }
} as const

export function throwError(code: keyof typeof ErrorCodes, details?: any) {
  const err = ErrorCodes[code]
  throw createError({ statusCode: err.statusCode, message: err.message, data: { errorCode: code, details } })
}

出力:

TEXT
// 実行成功

(3) ▶サンプル:標準APIレスポンス形式

TYPESCRIPT
// server/utils/response.ts
export function successResponse(data: any, message = 'Success') {
  return { data, message, timestamp: Date.now() }
}

export function listResponse(items: any[], total: number, page: number, limit: number) {
  return { items, total, page, limit, timestamp: Date.now() }
}

export function errorResponse(statusCode: number, errorCode: string, message: string, details?: any) {
  return { statusCode, errorCode, message, details, timestamp: Date.now() }
}

出力:

TEXT
// 実行成功

(4) ▶サンプル:routeRulesレンダリング戦略設定

TYPESCRIPT
// nuxt.config.ts - ルートレベルのレンダリング戦略
routeRules: {
  '/': { prerender: true },
  '/products': { swr: 3600 },
  '/products/**': { swr: 86400 },
  '/admin/**': { ssr: false },
  '/cart': { ssr: false },
  '/api/**': { cors: true },
  '/_nuxt/**': { headers: { 'cache-control': 'public, max-age=31536000, immutable' } }
}

出力:

TEXT
// 実行成功

(5) ▶サンプル:CI/CDパイプライン構造

YAML
# .github/workflows/ci.yml - コアパイプライン
name: CI
on: [push, pull_request]
jobs:
  lint:
    runs-on: ubuntu-latest
    steps: [{ uses: actions/checkout@v4 }, { run: npm ci }, { run: npm run lint }]
  test:
    needs: lint
    steps: [{ run: npm run test:coverage }]
  build:
    needs: test
    steps: [{ run: npm run build }]

出力:

TEXT
CI/CDパイプラインが読み込まれました
パイプラインステータス:合格
テスト:12件合格, 0件不合格
テーブル フィールド数 プライマリインデックス 推定データ量
Product 12 slug, categoryId, price 100万
Category 6 slug, parentId 500
User 10 email, role 50万
Order 8 userId, status, createdAt 100万
OrderItem 6 orderId, productId 500万
CartItem 5 userId+productId (unique) 10万
Review 7 productId, userId 200万
Address 8 userId 50万

6. API仕様

(1) RESTful API設計

メソッド パス 説明 認証
GET /api/products 商品一覧 (ページネーション/フィルタ) なし
GET /api/products/:id 商品詳細 なし
POST /api/products 商品作成 管理者
PUT /api/products/:id 商品更新 管理者
DELETE /api/products/:id 商品削除 管理者
GET /api/categories カテゴリ一覧 なし
POST /api/auth/register 登録 なし
POST /api/auth/login ログイン なし
POST /api/auth/refresh トークン更新 Cookie
GET /api/cart ショッピングカート ユーザー
POST /api/cart/add カート追加 ユーザー
DELETE /api/cart/remove 削除 ユーザー
POST /api/orders 注文作成 ユーザー
GET /api/orders 注文一覧 ユーザー
GET /api/orders/:id 注文詳細 ユーザー

(2) エラーコード仕様

ステータスコード エラーコード 説明
400 VALIDATION_ERROR リクエストパラメータの検証失敗
401 AUTH_REQUIRED 未ログイン
401 TOKEN_EXPIRED トークン期限切れ
403 FORBIDDEN 権限不足
404 NOT_FOUND リソースが存在しない
409 CONFLICT リソースの競合 (例:メールアドレスの重複登録)
429 RATE_LIMITED リクエストレート超過
500 INTERNAL_ERROR サーバー内部エラー

(3) レスポンス形式

TYPESCRIPT
// 成功レスポンス
{
  "data": { ... },
  "message": "操作成功"
}

// 一覧レスポンス
{
  "items": [...],
  "total": 1000000,
  "page": 1,
  "limit": 20
}

// エラーレスポンス
{
  "statusCode": 400,
  "message": "Validation error",
  "errorCode": "VALIDATION_ERROR",
  "details": { "field": "email", "reason": "Invalid format" }
}

7. 総合例:MegaShopプロジェクト構造

TEXT
megashop/
├── nuxt.config.ts
├── prisma/
│   ├── schema.prisma
│   ├── seed.ts
│   └── migrations/
├── pages/
│   ├── index.vue
│   ├── products/
│   │   ├── index.vue
│   │   └── [id].vue
│   ├── categories/
│   │   └── [slug].vue
│   ├── cart.vue
│   ├── checkout.vue
│   ├── login.vue
│   ├── register.vue
│   ├── profile/
│   │   ├── index.vue
│   │   └── orders.vue
│   └── admin/
│       ├── index.vue
│       ├── products/
│       └── orders/
├── components/
│   ├── AppHeader.vue
│   ├── AppFooter.vue
│   ├── product/
│   │   ├── ProductCard.vue
│   │   ├── ProductGrid.vue
│   │   └── ProductReview.vue
│   ├── cart/
│   │   └── CartItem.vue
│   └── common/
│       ├── LanguageSwitcher.vue
│       └── SearchBar.vue
├── composables/
│   ├── useCart.ts
│   ├── useAnalytics.ts
│   ├── useLocalizedPrice.ts
│   └── useProductSearch.ts
├── stores/
│   ├── cart.ts
│   └── user.ts
├── server/
│   ├── utils/
│   │   ├── prisma.ts
│   │   └── jwt.ts
│   ├── middleware/
│   │   └── auth.ts
│   ├── api/
│   │   ├── auth/
│   │   ├── products/
│   │   ├── categories/
│   │   ├── cart/
│   │   └── orders/
│   └── plugins/
│       └── stock.ts
├── middleware/
│   ├── 01-auth.global.ts
│   └── admin.ts
├── plugins/
│   ├── 01-config.ts
│   ├── 02-logger.ts
│   └── 03-stripe.client.ts
├── layouts/
│   ├── default.vue
│   └── sidebar.vue
├── locales/
│   ├── en.json
│   ├── zh.json
│   └── ja.json
├── modules/
│   └── analytics/
├── tests/
│   ├── composables/
│   ├── stores/
│   ├── components/
│   └── api/
├── e2e/
│   ├── cart-flow.spec.ts
│   ├── auth-flow.spec.ts
│   └── admin-flow.spec.ts
├── Dockerfile
├── docker-compose.yml
├── .github/workflows/
│   ├── ci.yml
│   ├── deploy-staging.yml
│   └── deploy-production.yml
└── public/
    ├── favicon.ico
    └── robots.txt

❓よくある質問

Q 設計フェーズにはどのくらいの期間が必要ですか?
A 一般的に1〜2週間です。要件分析:2日, アーキテクチャ設計:2日, データモデリング:2日, API仕様:2日, 技術選定:1日。設計が詳細であるほど, 開発はスムーズに進みます。
Q PostgreSQLとMySQLのどちらを選ぶべきですか?
A PostgreSQLがMegaShopに適しています - JSONフィールド (商品属性), 全文検索 (商品検索), 多様なインデックスタイプをサポートしています。PrismaはPostgreSQLのサポートが最も充実しています。
Q Redisは必須ですか?
A 数百万商品のページでは推奨されます。Redisは商品キャッシュとISRストレージに使用され, 応答時間は5msに対してデータベースは200msです。低トラフィックのシナリオでは, 当面スキップしても構いません。
Q APIのバージョニングはどのように管理しますか?
A URLにバージョンプレフィックス/api/v1/productsを追加し, 重大な変更でバージョン番号を増やしてください。小さな変更は後方互換性のある形でフィールドを拡張してください。
Q モジュール分割の粒度はどのように決めるべきですか?
A ビジネスドメインで分割してください - 認証, 商品, ショッピングカート, 注文それぞれ1つのモジュール。各モジュールに独自のAPI, Store, Composable, ページを持たせてください。技術層で分割しないでください。
Q 設計ドキュメントとコードの一致性はどのように確保しますか?
A Prismaスキーマをデータモデルの唯一の信頼できる情報源とし, TypeScriptインターフェースでAPI仕様を定義してください。設計変更時は, まずスキーマとインターフェースを更新し, 次にコードを更新してください。

📖まとめ


📝練習問題

  1. 基本問題 (難易度:⭐):プロジェクトのユーザーロールと機能モジュールを示す図を作成してください
  2. 応用問題 (難易度:⭐⭐):完全なPrismaスキーマを設計してください (5つ以上のモデルを含む), インデックスと外部キーを考慮してください
  3. チャレンジ (難易度:⭐⭐⭐):完全なAPI仕様ドキュメントを設計してください。すべてのエンドポイント, リクエスト/レスポンス形式, エラーコードを含めてください

---|

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%