𝕏 f B! L
案件・求人数 12,345
案件を探す(準備中) エージェントを探す(準備中) お役立ち情報 ログイン
案件・求人数 12,345
Antigravityでモバイル開発を加速|Flutter/React Nativeのコード生成・UI設計・テスト自動化

Antigravityでモバイル開発を加速|Flutter/React Nativeのコード生成・UI設計・テスト自動化

Antigravityモバイル開発FlutterReact Native
目次
⚡ 3秒でわかる!この記事のポイント
  • AntigravityでFlutter/React Nativeのコンポーネント生成・画面レイアウトを自動化できる
  • APIクライアント生成・状態管理・ナビゲーション設計をプロンプト一発で実装
  • モバイル開発案件はSES市場で需要急増中、月単価70〜95万円が目安

「Flutterの画面レイアウトを書くのが面倒」「React Nativeのネイティブモジュール連携が難しい」「クロスプラットフォーム開発で品質を担保できない」——モバイル開発に携わるSESエンジニアが日常的に感じている悩みです。

2026年のSES市場では、モバイルアプリ開発の案件が前年比35%増と急成長しています。特にFlutterとReact Nativeによるクロスプラットフォーム開発は、ネイティブ開発に比べてコストを50〜60%削減できるため、多くの企業が導入を進めています。

Google Antigravity(旧Gemini CLI / Project Jules)は、Geminiモデルの高度な推論能力を活かして、モバイル開発のあらゆるフェーズを効率化できる強力なツールです。本記事では、UIコンポーネントの自動生成からAPI連携、テスト自動化まで、SES現場で即戦力になるモバイル開発テクニックを体系的に解説します。

モバイル開発におけるAntigravityの強み

なぜAntigravityがモバイル開発に最適なのか

Antigravityがモバイル開発で特に威力を発揮する理由は3つあります:

1. マルチファイル対応のコンテキスト理解

モバイルアプリは画面・コンポーネント・モデル・サービスなど多数のファイルで構成されます。Antigravityはプロジェクト全体のコンテキストを理解した上でコード生成を行うため、ファイル間の整合性が保たれます。

2. プラットフォーム固有のベストプラクティス

Geminiモデルはios/Androidのプラットフォームガイドラインを熟知しており、Human Interface Guidelines(iOS)やMaterial Design(Android)に準拠したUIを生成できます。

3. リアルタイムのデバッグ支援

ビルドエラーやランタイムエラーのスタックトレースを入力するだけで、根本原因の特定と修正コードの提案を行います。

SES案件で求められるモバイル開発スキル

2026年のSES市場におけるモバイル開発案件の主要な技術スタック:

フレームワーク案件比率月単価目安主な業界
Flutter45%75〜95万円EC・金融・ヘルスケア
React Native35%70〜90万円メディア・SNS・SaaS
Swift/Kotlin (ネイティブ)15%80〜100万円金融・ゲーム
Kotlin Multiplatform5%80〜95万円エンタープライズ

実践①:Flutterアプリのスキャフォールディング

プロジェクト構造の自動生成

新規Flutterプロジェクトの骨格を、クリーンアーキテクチャに基づいて自動生成します:

antigravity "Flutterプロジェクトの初期構造を生成してください。
要件:
- クリーンアーキテクチャ(domain / data / presentation の3層)
- Riverpod による状態管理
- go_router によるルーティング
- freezed + json_serializable によるモデル生成
- dio によるHTTPクライアント
- フォルダ構成の雛形を作成
- main.dart, app.dart, router.dart の基本実装"

Antigravityが生成する典型的なプロジェクト構成:

lib/
├── app.dart
├── main.dart
├── core/
│   ├── constants/
│   ├── extensions/
│   ├── theme/
│   └── utils/
├── features/
│   ├── auth/
│   │   ├── data/
│   │   │   ├── datasources/
│   │   │   ├── models/
│   │   │   └── repositories/
│   │   ├── domain/
│   │   │   ├── entities/
│   │   │   ├── repositories/
│   │   │   └── usecases/
│   │   └── presentation/
│   │       ├── providers/
│   │       ├── screens/
│   │       └── widgets/
│   └── home/
│       └── ...
└── router/
    └── app_router.dart

レスポンシブUIコンポーネントの生成

実際のSES案件では、タブレット対応が求められることが増えています:

antigravity "Flutterでレスポンシブ対応のダッシュボード画面を作成してください。
要件:
- スマホ: 1カラムレイアウト
- タブレット: 2カラムレイアウト(サイドバー + メイン)
- LayoutBuilder と MediaQuery を使用
- カスタムBreakpointクラスの定義
- ダッシュボードカード(売上、ユーザー数、注文数、レビュー)
- Riverpodでデータフェッチ
- ローディング状態とエラーハンドリング"

Antigravityは以下のようなレスポンシブウィジェットを生成します:

class DashboardScreen extends ConsumerWidget {
  const DashboardScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final dashboardAsync = ref.watch(dashboardProvider);

    return Scaffold(
      appBar: AppBar(title: const Text('Dashboard')),
      body: dashboardAsync.when(
        data: (data) => LayoutBuilder(
          builder: (context, constraints) {
            if (constraints.maxWidth >= Breakpoints.tablet) {
              return _TabletLayout(data: data);
            }
            return _MobileLayout(data: data);
          },
        ),
        loading: () => const Center(child: CircularProgressIndicator()),
        error: (error, stack) => ErrorView(
          message: error.toString(),
          onRetry: () => ref.invalidate(dashboardProvider),
        ),
      ),
    );
  }
}

Antigravityによるモバイル開発ワークフローを示すインフォグラフィック

実践②:React Nativeコンポーネント設計

型安全なコンポーネントライブラリ

React Native案件では、再利用可能なコンポーネントライブラリの構築が重要です:

antigravity "React Native + TypeScriptで再利用可能なUIコンポーネントライブラリを作成してください。
要件:
- Button(Primary / Secondary / Outline / Ghost バリアント)
- TextInput(バリデーション・エラー表示付き)
- Card(画像・タイトル・説明のスロット)
- Modal(BottomSheet スタイル)
- 全コンポーネントにStorybookストーリー付き
- アクセシビリティ対応(accessibilityLabel, accessibilityRole)
- テーマ対応(ダークモード)"

Antigravityが生成する型安全なButtonコンポーネントの例:

interface ButtonProps {
  variant?: 'primary' | 'secondary' | 'outline' | 'ghost';
  size?: 'sm' | 'md' | 'lg';
  loading?: boolean;
  disabled?: boolean;
  icon?: React.ReactNode;
  iconPosition?: 'left' | 'right';
  onPress: () => void;
  children: React.ReactNode;
  testID?: string;
}

export const Button: React.FC<ButtonProps> = ({
  variant = 'primary',
  size = 'md',
  loading = false,
  disabled = false,
  icon,
  iconPosition = 'left',
  onPress,
  children,
  testID,
}) => {
  const theme = useTheme();
  const styles = useMemo(
    () => createStyles(theme, variant, size),
    [theme, variant, size]
  );

  return (
    <Pressable
      style={({ pressed }) => [
        styles.container,
        pressed && styles.pressed,
        disabled && styles.disabled,
      ]}
      onPress={onPress}
      disabled={disabled || loading}
      accessibilityRole="button"
      accessibilityState={{ disabled, busy: loading }}
      testID={testID}
    >
      {loading ? (
        <ActivityIndicator color={styles.text.color} size="small" />
      ) : (
        <View style={styles.content}>
          {icon && iconPosition === 'left' && icon}
          <Text style={styles.text}>{children}</Text>
          {icon && iconPosition === 'right' && icon}
        </View>
      )}
    </Pressable>
  );
};

ナビゲーション設計

React Navigationを使った型安全なナビゲーション構造を生成します:

antigravity "React Navigation v7で型安全なナビゲーション構造を設計してください。
要件:
- BottomTab: Home / Search / Cart / Profile
- Stack: 各タブにネストされたスタックナビゲーション
- Auth Flow: Login / Register / ForgotPassword(認証前のみ)
- Deep Link対応
- TypeScriptの型定義で画面パラメータを型安全に
- ナビゲーションガード(認証チェック)"

実践③:API連携とデータ層の構築

RESTful APIクライアント生成

OpenAPIスキーマからモバイル用のAPIクライアントを自動生成します:

antigravity "以下のOpenAPIスキーマからFlutter用のAPIクライアントを生成してください。
- dioベースのHTTPクライアント
- リクエスト/レスポンスのモデルクラス(freezed使用)
- 認証トークンの自動付与(Interceptor)
- リフレッシュトークンの自動更新
- リトライロジック(exponential backoff)
- オフライン時のキューイング
スキーマ: $(cat openapi.yaml)"

生成されるInterceptorの例:

class AuthInterceptor extends Interceptor {
  final TokenStorage _tokenStorage;
  final Dio _dio;

  AuthInterceptor(this._tokenStorage, this._dio);

  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
    final token = await _tokenStorage.getAccessToken();
    if (token != null) {
      options.headers['Authorization'] = 'Bearer $token';
    }
    handler.next(options);
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) async {
    if (err.response?.statusCode == 401) {
      try {
        final newToken = await _refreshToken();
        err.requestOptions.headers['Authorization'] = 'Bearer $newToken';
        final response = await _dio.fetch(err.requestOptions);
        handler.resolve(response);
        return;
      } catch (e) {
        await _tokenStorage.clearTokens();
        handler.reject(err);
        return;
      }
    }
    handler.next(err);
  }

  Future<String> _refreshToken() async {
    final refreshToken = await _tokenStorage.getRefreshToken();
    final response = await _dio.post('/auth/refresh', data: {
      'refresh_token': refreshToken,
    });
    final newAccessToken = response.data['access_token'];
    final newRefreshToken = response.data['refresh_token'];
    await _tokenStorage.saveTokens(newAccessToken, newRefreshToken);
    return newAccessToken;
  }
}

GraphQL連携(Flutter + ferry)

GraphQLを使用するモバイルアプリも増加しています:

antigravity "Flutter + ferryでGraphQLクライアントを設定してください。
要件:
- ferry + gql_exec + gql_http_link
- コード生成(build_runner)の設定
- 認証ヘッダー付きのHTTP Link
- キャッシュ設定(Cache + optimistic updates)
- Subscription対応(WebSocket Link)
- ユーザー一覧取得と詳細表示のクエリ・ミューテーション"

実践④:状態管理パターン

Riverpod + freezed によるイミュータブル状態管理

SES案件で最も需要が高い状態管理パターンを自動生成します:

antigravity "Riverpod + freezedで認証状態管理を実装してください。
要件:
- AuthState: authenticated / unauthenticated / loading / error
- AuthNotifier: login / logout / checkAuthStatus / refreshToken
- SecureStorage によるトークン永続化
- 自動ログイン(アプリ起動時にトークン確認)
- バイオメトリクス認証オプション
- ログアウト時のキャッシュクリア"

Antigravityが生成する状態管理コード:

@freezed
class AuthState with _$AuthState {
  const factory AuthState.initial() = _Initial;
  const factory AuthState.loading() = _Loading;
  const factory AuthState.authenticated({
    required User user,
    required String accessToken,
  }) = _Authenticated;
  const factory AuthState.unauthenticated({String? message}) = _Unauthenticated;
  const factory AuthState.error({required String message}) = _Error;
}

@riverpod
class AuthNotifier extends _$AuthNotifier {
  late final AuthRepository _authRepository;
  late final TokenStorage _tokenStorage;

  @override
  AuthState build() {
    _authRepository = ref.read(authRepositoryProvider);
    _tokenStorage = ref.read(tokenStorageProvider);
    _checkAuthStatus();
    return const AuthState.initial();
  }

  Future<void> _checkAuthStatus() async {
    state = const AuthState.loading();
    try {
      final token = await _tokenStorage.getAccessToken();
      if (token != null) {
        final user = await _authRepository.getCurrentUser(token);
        state = AuthState.authenticated(user: user, accessToken: token);
      } else {
        state = const AuthState.unauthenticated();
      }
    } catch (e) {
      state = const AuthState.unauthenticated();
    }
  }

  Future<void> login(String email, String password) async {
    state = const AuthState.loading();
    try {
      final result = await _authRepository.login(email, password);
      await _tokenStorage.saveTokens(
        result.accessToken,
        result.refreshToken,
      );
      state = AuthState.authenticated(
        user: result.user,
        accessToken: result.accessToken,
      );
    } catch (e) {
      state = AuthState.error(message: e.toString());
    }
  }

  Future<void> logout() async {
    await _tokenStorage.clearTokens();
    await _authRepository.logout();
    state = const AuthState.unauthenticated();
  }
}

Zustand(React Native)での軽量状態管理

React Native案件では、ReduxよりもZustandの採用が増えています:

antigravity "React Native + ZustandでECアプリのカート状態管理を実装してください。
要件:
- カートアイテムの追加・削除・数量変更
- 小計・税額・合計の自動計算
- AsyncStorageによる永続化(zustand/middleware)
- 在庫チェック連携
- TypeScript完全対応"

実践⑤:テスト自動化

ウィジェットテスト(Flutter)

Antigravityを使えば、UIコンポーネントのテストを網羅的に生成できます:

antigravity "先ほど生成したDashboardScreenのウィジェットテストを作成してください。
テスト要件:
- ローディング状態の表示テスト
- データ表示テスト(モックデータ使用)
- エラー状態のテスト
- リトライボタンのタップテスト
- レスポンシブレイアウトのテスト(スマホ/タブレット)
- Golden Test(スナップショットテスト)
- mockitoでのモック生成"

E2Eテスト(Detox / Flutter Integration Test)

antigravity "FlutterのIntegration Testでログインフローのテストを作成してください。
テストシナリオ:
1. アプリ起動 → ログイン画面表示
2. メール・パスワード入力 → ログインボタンタップ
3. ホーム画面遷移確認
4. 不正な認証情報でエラーメッセージ表示
5. パスワードリセットフロー
テスト環境: MockサーバーまたはFake実装を使用"

生成されるIntegration Testの例:

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  group('Login Flow', () {
    testWidgets('successful login navigates to home', (tester) async {
      await tester.pumpWidget(
        ProviderScope(
          overrides: [
            authRepositoryProvider.overrideWithValue(FakeAuthRepository()),
          ],
          child: const MyApp(),
        ),
      );
      await tester.pumpAndSettle();

      // ログイン画面の表示確認
      expect(find.text('Login'), findsOneWidget);

      // 認証情報入力
      await tester.enterText(
        find.byKey(const Key('email_input')),
        '[email protected]',
      );
      await tester.enterText(
        find.byKey(const Key('password_input')),
        'password123',
      );

      // ログインボタンタップ
      await tester.tap(find.byKey(const Key('login_button')));
      await tester.pumpAndSettle();

      // ホーム画面遷移確認
      expect(find.text('Dashboard'), findsOneWidget);
    });

    testWidgets('invalid credentials show error', (tester) async {
      await tester.pumpWidget(
        ProviderScope(
          overrides: [
            authRepositoryProvider.overrideWithValue(
              FakeAuthRepository(shouldFail: true),
            ),
          ],
          child: const MyApp(),
        ),
      );
      await tester.pumpAndSettle();

      await tester.enterText(
        find.byKey(const Key('email_input')),
        '[email protected]',
      );
      await tester.enterText(
        find.byKey(const Key('password_input')),
        'wrongpassword',
      );
      await tester.tap(find.byKey(const Key('login_button')));
      await tester.pumpAndSettle();

      expect(find.text('Invalid credentials'), findsOneWidget);
    });
  });
}

実践⑥:パフォーマンス最適化

画像最適化

モバイルアプリのパフォーマンスで最も影響が大きいのが画像処理です:

antigravity "Flutterアプリの画像最適化を実装してください。
要件:
- cached_network_image によるキャッシュ戦略
- プレースホルダー・エラーウィジェット
- プログレッシブ画像ロード
- WebP形式への自動変換(サーバーサイド連携)
- メモリ使用量の制限(cacheMaxMemory設定)
- リスト表示時の遅延読み込み"

リスト表示の最適化

大量データのリスト表示は、SES案件で頻繁に遭遇するパフォーマンス課題です:

antigravity "Flutterで無限スクロールの商品一覧を最適化してください。
要件:
- ListView.builder による仮想化
- Riverpodのページネーション(cursor-based)
- スクロール位置の復元
- プルトゥリフレッシュ
- Shimmerローディング
- アイテムの高さキャッシュ"

実践⑦:CI/CDパイプライン構築

GitHub Actionsでのモバイルビルド自動化

antigravity "Flutter + GitHub Actionsのモバイルビルドパイプラインを作成してください。
要件:
- Android: AABビルド → Google Play Internal Track アップロード
- iOS: IPAビルド → TestFlight アップロード
- ビルド番号の自動インクリメント
- 環境変数による本番/ステージング切り替え(--dart-define-from-file)
- テスト実行(Unit + Widget)
- コード署名(Android: keystore / iOS: Provisioning Profile)
- Fastlane連携"

SES面談でのモバイル開発スキルアピール

アーキテクチャ面

  • クリーンアーキテクチャの設計経験(domain / data / presentation)
  • 状態管理の選定理由を説明できる(Riverpod vs BLoC vs Redux)
  • オフラインファーストのデータ同期戦略
  • CI/CDパイプラインの構築・運用経験

技術面

  • Flutter/React Nativeのバージョンアップ対応経験
  • ネイティブモジュールの実装・連携スキル
  • パフォーマンス最適化の知見(FPSチューニング、メモリ管理)
  • E2Eテストの導入・運用経験

ビジネス面

  • ストアガイドライン準拠のリジェクト対応経験
  • アクセシビリティ対応(JIS X 8341-3 / WCAG 2.1)
  • アナリティクスの計装設計(Firebase Analytics / Mixpanel)

まとめ

Antigravityを活用することで、モバイル開発の全工程——プロジェクト構築からUI設計、API連携、テスト自動化、CI/CDパイプライン構築まで——を大幅に効率化できます。

特にFlutterとReact Nativeのクロスプラットフォーム開発では、Antigravityのコンテキスト理解能力が真価を発揮します。プラットフォーム固有のベストプラクティスに準拠しながら、型安全で保守性の高いコードを自動生成できるため、SES案件での生産性が飛躍的に向上します。

モバイル開発スキルは2026年のSES市場で確実にキャリアアップにつながる分野です。Antigravityで効率的に開発しながら、実践的なスキルを積み重ねていきましょう。

関連記事

SES案件をお探しですか?

SES記事をもっと読む →
🏗️

SES BASE 編集長

SES業界歴10年以上のメンバーが在籍する編集チーム。SES企業での営業・エンジニア経験、フリーランス独立経験を持つメンバーが、業界のリアルな情報をお届けします。

📊 業界データに基づく記事制作 🔍 IPA・経済産業省データ参照 💼 SES実務経験者が執筆・監修