Skip to content
← Back to blog
NestJSAngularSaaSJapaneseエンタープライズガイド

NestJSとAngularでSaaSを構築する:完全ガイド2026

Firas Sayah·July 18, 2026·8 min read

なぜNestJS + AngularでSaaSを構築するのか?

去年、私はクライアントのSaaSプロジェクトで認証、課金、マルチテナント対応をゼロから実装しました。結果は?4ヶ月かかって、やっとユーザーがログインして請求書を見られる段階まで到達。プロダクト固有の機能にはまだ一行もコードを書いていませんでした。その経験から学んだのは、SaaS開発で最も重要なのは「何を自分で書くか」ではなく「何を書かないか」を決めることです。

コードが表示されたモニター画面

2026年、SaaS市場は急速に成長を続けています。日本のエンタープライズ市場でも、クラウドベースのソリューションへの需要が高まっています。NestJSとAngularの組み合わせは、エンタープライズグレードのSaaSアプリケーションを構築するための最も強力なスタックの一つです。

NestJSはTypeScriptベースのバックエンドフレームワークで、Angularにインスパイアされたモジュラーアーキテクチャを採用しています。AngularはGoogleが開発した堅牢なフロントエンドフレームワークで、大規模アプリケーションに最適です。

両フレームワークがTypeScriptを共有していることで、フロントエンドとバックエンド間でインターフェースや型定義を共有でき、開発効率が大幅に向上します。NestJS + Angularと他の技術スタックとの比較については、NestJS + Angular vs Next.jsの詳細比較をご覧ください。

アーキテクチャ設計

エンタープライズSaaSのアーキテクチャは、スケーラビリティと保守性を重視して設計する必要があります。

プロジェクト構造

saas-project/
├── apps/
│   ├── api/              # NestJS バックエンド
│   │   ├── src/
│   │   │   ├── auth/     # 認証モジュール
│   │   │   ├── billing/  # 課金モジュール
│   │   │   ├── tenants/  # テナント管理
│   │   │   └── users/    # ユーザー管理
│   ├── web/              # Angular フロントエンド
│   │   ├── src/
│   │   │   ├── app/
│   │   │   │   ├── auth/
│   │   │   │   ├── dashboard/
│   │   │   │   └── shared/
├── libs/                 # 共有ライブラリ
│   ├── shared-types/     # 共有型定義
│   └── shared-utils/     # 共有ユーティリティ

マルチテナントアーキテクチャ

SaaSアプリケーションにおいて、マルチテナント対応は必須です。NestJSでは以下のようにテナント分離を実装します:

// tenant.middleware.ts
@Injectable()
export class TenantMiddleware implements NestMiddleware {
  constructor(private readonly tenantService: TenantService) {}

  async use(req: Request, res: Response, next: NextFunction) {
    const tenantId = req.headers['x-tenant-id'] as string;

    if (!tenantId) {
      throw new UnauthorizedException('テナントIDが必要です');
    }

    const tenant = await this.tenantService.findById(tenantId);
    if (!tenant || !tenant.isActive) {
      throw new UnauthorizedException('無効なテナントです');
    }

    req['tenant'] = tenant;
    next();
  }
}

Cloudrix SaaS Starter ships with this pre-configured and tested.

Skip weeks of boilerplate — auth, payments, multi-tenancy, and deployment included out of the box.

Try the live demo →

認証システムの構築

JWTベースの認証は、SaaSアプリケーションの基盤です。認証システムの詳細については、認証機能の概要もご参照ください。

バックエンド(NestJS)

// auth.service.ts
@Injectable()
export class AuthService {
  constructor(
    private readonly usersService: UsersService,
    private readonly jwtService: JwtService,
    private readonly configService: ConfigService,
  ) {}

  async login(loginDto: LoginDto) {
    const user = await this.usersService.validateUser(
      loginDto.email,
      loginDto.password,
    );

    if (!user) {
      throw new UnauthorizedException('メールアドレスまたはパスワードが正しくありません');
    }

    const payload = {
      sub: user.id,
      email: user.email,
      tenantId: user.tenantId,
      role: user.role,
    };

    return {
      accessToken: this.jwtService.sign(payload),
      refreshToken: this.jwtService.sign(payload, {
        expiresIn: '7d',
      }),
      user: {
        id: user.id,
        email: user.email,
        name: user.name,
      },
    };
  }
}

フロントエンド(Angular)

// auth.service.ts
@Injectable({ providedIn: 'root' })
export class AuthService {
  private readonly http = inject(HttpClient);
  private readonly router = inject(Router);
  private currentUser = signal<User | null>(null);

  readonly isAuthenticated = computed(() => !!this.currentUser());
  readonly user = this.currentUser.asReadonly();

  login(credentials: LoginCredentials): Observable<AuthResponse> {
    return this.http.post<AuthResponse>('/api/auth/login', credentials).pipe(
      tap(response => {
        localStorage.setItem('accessToken', response.accessToken);
        this.currentUser.set(response.user);
        this.router.navigate(['/dashboard']);
      }),
    );
  }
}

サブスクリプション課金の実装

Stripe連携による課金システムを構築します。詳細なStripe実装ガイドはStripe Subscriptions完全ガイドをご覧ください。

このコードを手動で書く必要はありません。 SaaS Starterには、この認証・課金システムが55以上のテスト付きで含まれています。無料のLite版を試す →

ラップトップでのコーディング風景

Stripe連携による課金システムを構築します:

// billing.service.ts
@Injectable()
export class BillingService {
  private stripe: Stripe;

  constructor(private readonly configService: ConfigService) {
    this.stripe = new Stripe(
      this.configService.get('STRIPE_SECRET_KEY'),
      { apiVersion: '2025-12-18.acacia' },
    );
  }

  async createCheckoutSession(
    tenantId: string,
    priceId: string,
  ): Promise<Stripe.Checkout.Session> {
    return this.stripe.checkout.sessions.create({
      mode: 'subscription',
      payment_method_types: ['card'],
      line_items: [{ price: priceId, quantity: 1 }],
      success_url: `${this.configService.get('APP_URL')}/billing/success`,
      cancel_url: `${this.configService.get('APP_URL')}/billing/cancel`,
      metadata: { tenantId },
    });
  }

  async handleWebhook(event: Stripe.Event): Promise<void> {
    switch (event.type) {
      case 'customer.subscription.created':
        await this.activateSubscription(event.data.object);
        break;
      case 'customer.subscription.deleted':
        await this.deactivateSubscription(event.data.object);
        break;
      case 'invoice.payment_failed':
        await this.handlePaymentFailure(event.data.object);
        break;
    }
  }
}

ロールベースアクセス制御(RBAC)

エンタープライズアプリケーションには細かなアクセス制御が必要です。マルチテナントアーキテクチャとRBACの詳細な実装パターンについては、NestJSマルチテナントアーキテクチャガイドをご参照ください。

// roles.guard.ts
@Injectable()
export class RolesGuard implements CanActivate {
  constructor(private readonly reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const requiredRoles = this.reflector.getAllAndOverride<Role[]>(
      ROLES_KEY,
      [context.getHandler(), context.getClass()],
    );

    if (!requiredRoles) return true;

    const { user } = context.switchToHttp().getRequest();
    return requiredRoles.some(role => user.role === role);
  }
}

// 使用例
@Controller('admin')
@UseGuards(JwtAuthGuard, RolesGuard)
export class AdminController {
  @Get('users')
  @Roles(Role.ADMIN, Role.SUPER_ADMIN)
  async getUsers() {
    return this.usersService.findAll();
  }
}

Angularダッシュボードの構築

管理ダッシュボードはSaaSの中核です。Angular Signalsを使った最新のアプローチで実装します:

// dashboard.component.ts
@Component({
  selector: 'app-dashboard',
  template: `
    <div class="dashboard-grid">
      <app-stats-card
        title="月間収益"
        [value]="stats()?.monthlyRevenue | currency:'JPY'"
        [trend]="stats()?.revenueTrend"
      />
      <app-stats-card
        title="アクティブユーザー"
        [value]="stats()?.activeUsers"
        [trend]="stats()?.userTrend"
      />
      <app-stats-card
        title="解約率"
        [value]="stats()?.churnRate + '%'"
        [trend]="stats()?.churnTrend"
        [invertTrend]="true"
      />
    </div>
  `,
})
export class DashboardComponent {
  private readonly analyticsService = inject(AnalyticsService);
  stats = toSignal(this.analyticsService.getDashboardStats());
}

デプロイメント

Docker Composeを使用した本番環境のデプロイ構成:

# docker-compose.prod.yml
services:
  api:
    build:
      context: .
      dockerfile: apps/api/Dockerfile
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/saas
      - REDIS_URL=redis://redis:6379
    depends_on:
      - db
      - redis

  web:
    build:
      context: .
      dockerfile: apps/web/Dockerfile
    ports:
      - "443:443"

  db:
    image: postgres:16-alpine
    volumes:
      - pgdata:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine

パフォーマンス最適化のヒント

  1. データベースインデックス: テナントIDに対するインデックスを必ず設定
  2. キャッシング: Redis を使用して頻繁にアクセスされるデータをキャッシュ
  3. 遅延読み込み: Angular のルートレベルで遅延読み込みを活用
  4. 接続プーリング: TypeORMの接続プール設定を最適化
  5. CDN: 静的アセットにCloudFrontなどのCDNを使用

ゼロから構築する vs ボイラープレートを使う

SaaSアプリケーションをゼロから構築する場合、認証、課金、マルチテナント対応、管理ダッシュボードなどの基盤機能だけで3〜6ヶ月かかることがあります。

SaaS Starterは、これらの機能をすべて含んだNestJS + Angularボイラープレートです。無料のLite版で基本機能を試すことができ、Pro版($149)、Business版($249)、Enterprise版($399)で完全な機能セットを利用できます。

主な特徴:

  • JWT認証 + OAuth2連携
  • Stripeサブスクリプション管理
  • マルチテナントアーキテクチャ
  • ロールベースアクセス制御
  • Angular管理ダッシュボード
  • Docker本番環境構成
  • CI/CDパイプライン

まとめ:今すぐ始めましょう

NestJSとAngularの組み合わせは、エンタープライズグレードのSaaSアプリケーションに最適な技術スタックです。TypeScriptの型安全性、モジュラーアーキテクチャ、豊富なエコシステムにより、保守性の高い大規模アプリケーションを効率的に構築できます。

ダッシュボードUI画面

開発を加速させたい方は、SaaS Starterのライブデモをぜひお試しください。無料のLite版から始めて、プロジェクトの成長に合わせてアップグレードできます。

料金プラン:

  • Lite(無料) — 基本アーキテクチャを体験
  • Pro($149) — 認証 + 課金 + ダッシュボード
  • Business($249) — マルチテナント + RBAC + 高度な機能
  • Enterprise($399) — 全機能 + 優先サポート

料金プランの詳細を見る | ライブデモを試す | 無料Lite版を入手

関連記事: Angular管理ダッシュボードガイド | NestJS REST APIチュートリアル | AWSへのデプロイガイド

F

Firas Sayah

Senior Software Engineer

Full-stack developer with 5+ years building production SaaS applications with NestJS and Angular.