Firebase面接質問2026:Flutterの認証、Firestore、セキュリティルール
Flutter開発者向けのFirebase面接質問とDartによる回答:認証状態ストリーム、Google Sign-In v7、FirestoreのCRUDとモデリング、セキュリティルール、カスタムクレーム、トランザクション、FlutterFire 5の変更点。

Flutter職種で問われるFirebaseの面接質問は、5つのテーマに集中します。3種類の認証状態ストリーム、Firestoreのデータモデリング、セキュリティルール、オフライン時の書き込み、そしてすべての読み取りに付随するコストモデルです。2026年もFirebaseはFlutterアプリの標準的なバックエンドであり、2026年10月以降、FlutterFireプラグインはBoM 5.x(firebase_core 5.1.0、firebase_auth 7.0.1、cloud_firestore 7.1.0)として提供されています。AndroidのminSdkは24に引き上げられ、内部ではFirebase Apple SDK 13が使われています。
現在のFlutterFireリリースはBoM 5.1.0で、firebase_auth 7.0.1、cloud_firestore 7.1.0、firebase_core 5.1.0を含みます。メジャーバージョン5.0.0ではAndroidのminSdk 24が必須となり、Firebase Apple SDK 13.0.0がベースになり、App Checkのactivateのパラメータ名が変更されました。cloud_firestore 6.3.0で追加されたFirestore Pipelinesは、リリースごとに使える式が増えています。
2026年のFirebase面接で問われること
面接官がAPIの細かい暗記を問うことはほとんどありません。確認されるのは、Firebaseがどこでルールを強制するのか、各操作にどれだけのコストがかかるのか、ネットワークが切れたときに何が起きるのかを候補者が理解しているかどうかです。次の表は、繰り返し出題されるテーマと、評価される回答に含まれるべき要素をまとめたものです。各テーマは後半のFlutter開発者向けFirebase面接質問で詳しく回答しています。
| テーマ | 典型的な質問 | 評価される回答の要素 |
|---|---|---|
| 認証ストリーム | authStateChanges()、idTokenChanges()、userChanges()の違い | それぞれが発行するイベントと、画面遷移のガードに使うべきもの |
| セキュリティ | アクセス制御はどこで強制されるか | サーバー側のセキュリティルールであり、クライアント側のチェックではない。App Checkは別の層 |
| ロール | 管理者ロールをどう実装するか | Admin SDKで設定するカスタムクレームをrequest.auth.tokenで読み取る |
| データモデリング | チャットアプリをモデリングする | サブコレクション、最新メッセージの非正規化、1メッセージ1ドキュメント |
| 整合性 | トランザクションかバッチ書き込みか | トランザクションは読み取ってから書き込み、リトライされる。バッチは書き込みのみをアトミックに行う |
| オフライン | オフライン時の書き込みはどうなるか | ローカルキャッシュ、hasPendingWrites、再接続時の同期 |
| コスト | なぜこの画面は高くつくのか | ドキュメント読み取り単位の課金、リスナー、カーソルによるページネーション |
| 比較 | FirestoreかRealtime Databaseか | クエリモデル、スケーリング、課金単位 |
Firebaseプロジェクトのセットアップ
FlutterアプリケーションでFirebaseを使用するためには、まずFirebase CLIとFlutterFire CLIを使用してプロジェクトを初期化する必要があります。flutterfire configureコマンドを実行すると、プラットフォーム固有の設定ファイルが自動生成されます。このプロセスにより、iOS、Android、Web、macOS、Windows向けの設定が一括で管理できるようになります。
設定が完了したら、アプリケーションのエントリーポイントでFirebaseを初期化します。この初期化処理は非同期で行われるため、WidgetsFlutterBinding.ensureInitialized()を事前に呼び出す必要があります。
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Firebase with platform-specific config
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}DefaultFirebaseOptions.currentPlatformは、FlutterFire CLIによって自動生成されるfirebase_options.dartファイルから読み込まれます。この仕組みにより、開発者はプラットフォームごとの設定を意識することなく、統一されたコードベースでマルチプラットフォーム対応を実現できます。
Firebase Authentication:メール認証とソーシャルログイン
Firebase Authenticationは、メール・パスワード認証、OAuthプロバイダ(Google、Apple、GitHub)、電話番号によるSMS認証、多要素認証(MFA)をサポートしています。TOTPによる多要素認証は、firebase_auth 6.1.0以降macOSでも利用できます。
以下は、メール・パスワード認証を実装するサービスクラスの例です。エラーハンドリングでは、FirebaseAuthExceptionのエラーコードに基づいて適切なメッセージを返すことで、ユーザーに分かりやすいフィードバックを提供します。
import 'package:firebase_auth/firebase_auth.dart';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
// Register with email and password
Future<User?> register(String email, String password) async {
try {
final credential = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
return credential.user;
} on FirebaseAuthException catch (e) {
// Handle specific error codes
switch (e.code) {
case 'email-already-in-use':
throw Exception('This email is already registered');
case 'weak-password':
throw Exception('Password must be at least 6 characters');
default:
throw Exception('Registration failed: ${e.message}');
}
}
}
// Sign in with existing credentials
Future<User?> signIn(String email, String password) async {
final credential = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
return credential.user;
}
// Reactive auth state stream
Stream<User?> get authStateChanges => _auth.authStateChanges();
}authStateChangesストリームを使用することで、認証状態の変化をリアクティブに監視できます。これにより、ログイン・ログアウト時のUI更新を自動的に行うことが可能です。StreamBuilderやRiverpodなどの状態管理ライブラリと組み合わせることで、宣言的なUIを構築できます。
パスワードのルールをクライアント側だけに置く必要はもうありません。validatePassword API(firebase_auth 6.0.0以降)は、Firebaseコンソールで設定したポリシーに照らしてパスワードを検証します。ポリシーでは最小文字数、大文字、小文字、数字、特殊文字を必須にできます。
Googleサインインの実装
OAuthプロバイダには追加のパッケージが必要です。google_sign_in 7.0以降、プラグインはGoogleSignIn.instanceで取得するシングルトンになり、初期化は一度だけ行う必要があり、認証(authentication)と認可(authorization)が分離されました。古いチュートリアルにあるGoogleSignIn().signIn()の呼び出しは、もうコンパイルが通りません。
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
// Call once at startup, before any other GoogleSignIn method
Future<void> initGoogleSignIn() => GoogleSignIn.instance.initialize();
Future<UserCredential> signInWithGoogle() async {
try {
// Shows the native account picker; throws if the user cancels
final googleUser = await GoogleSignIn.instance.authenticate();
// Synchronous getter since v7: only the ID token is exposed here
final googleAuth = googleUser.authentication;
// Firebase only needs the ID token to create the credential
final credential = GoogleAuthProvider.credential(
idToken: googleAuth.idToken,
);
return FirebaseAuth.instance.signInWithCredential(credential);
} on GoogleSignInException catch (e) {
if (e.code == GoogleSignInExceptionCode.canceled) {
throw Exception('Sign-in cancelled');
}
rethrow;
}
}このパターンはすべてのOAuthプロバイダに共通です。プロバイダのトークンを取得し、Firebaseの認証情報に包み、signInWithCredentialを呼び出します。アプリがGoogle API(Drive、Calendarなど)も呼び出す場合、アクセストークンは別のステップであるauthorizationClient.authorizeScopesから取得します。詳細はgoogle_sign_inの移行ガイドに記載されています。
GoogleSignIn().signIn()と書き、authenticationからaccessTokenを読み取る候補者は、7.0より前のAPIを答えています。v7ではauthenticate()がアカウントを返し、authenticationが持つのはidTokenのみで、追加スコープのアクセストークンには明示的な認可呼び出しが必要です。
Firestoreのデータ操作とモデリング
Cloud Firestoreは、FlexibleでスケーラブルなNoSQLドキュメントデータベースです。コレクションとドキュメントの階層構造により、直感的なデータモデリングが可能です。以下は、タスク管理アプリケーションのCRUD操作を実装したサービスクラスの例です。
import 'package:cloud_firestore/cloud_firestore.dart';
class TaskService {
final _db = FirebaseFirestore.instance;
final String _collection = 'tasks';
// Create a new document with auto-generated ID
Future<String> createTask(String userId, String title) async {
final doc = await _db.collection(_collection).add({
'userId': userId,
'title': title,
'completed': false,
'createdAt': FieldValue.serverTimestamp(),
});
return doc.id;
}
// Read a single document by ID
Future<Map<String, dynamic>?> getTask(String taskId) async {
final snapshot = await _db.collection(_collection).doc(taskId).get();
return snapshot.data();
}
// Update specific fields without overwriting the entire document
Future<void> toggleComplete(String taskId, bool completed) async {
await _db.collection(_collection).doc(taskId).update({
'completed': completed,
'updatedAt': FieldValue.serverTimestamp(),
});
}
// Delete a document
Future<void> deleteTask(String taskId) async {
await _db.collection(_collection).doc(taskId).delete();
}
}FieldValue.serverTimestamp()を使用することで、クライアントの時刻ではなくFirebaseサーバーの時刻がタイムスタンプとして記録されます。これにより、クライアント間での時刻の不整合を防ぎ、データの一貫性を保つことができます。cloud_firestore 7.1.0からは、サーバー側の変換としてFieldValue.minimumとFieldValue.maximumも使えます。読み取りなしで、保存済みの値と送信された値のうち小さい方または大きい方を保持するため、ベストスコアのようなカウンターに向いています。
リアルタイムデータ同期
Firestoreの強力な機能の一つが、リアルタイムリスナーです。snapshots()メソッドを使用することで、データの変更を即座にUIに反映できます。
import 'package:cloud_firestore/cloud_firestore.dart';
class TaskStream {
final _db = FirebaseFirestore.instance;
// Stream all tasks for a specific user, ordered by creation date
Stream<List<Map<String, dynamic>>> userTasks(String userId) {
return _db
.collection('tasks')
.where('userId', isEqualTo: userId)
.orderBy('createdAt', descending: true)
.snapshots()
.map((snapshot) => snapshot.docs.map((doc) {
final data = doc.data();
data['id'] = doc.id; // Include document ID
return data;
}).toList());
}
}このストリームをStreamBuilderと組み合わせることで、データベースの変更がリアルタイムでUIに反映される、リアクティブなアプリケーションを構築できます。複合インデックスが必要な場合は、Firestoreコンソールまたはfirestore.indexes.jsonで設定します。
Flutterの面接対策はできていますか?
インタラクティブなシミュレーター、flashcards、技術テストで練習しましょう。
Firestoreセキュリティルール
Firestoreのセキュリティルールは、データベースへのアクセスを制御する最も重要な防御層です。クライアントサイドのコードは簡単に改ざんできるため、サーバーサイドでのルール設定が不可欠です。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Users can only access their own profile
match /users/{userId} {
allow read, update: if request.auth != null
&& request.auth.uid == userId;
allow create: if request.auth != null;
allow delete: if false; // Prevent self-deletion
}
// Tasks belong to the user who created them
match /tasks/{taskId} {
allow read, write: if request.auth != null
&& resource.data.userId == request.auth.uid;
allow create: if request.auth != null
&& request.resource.data.userId == request.auth.uid;
}
}
}このルール設定では、認証済みユーザーのみがデータにアクセスでき、さらに自分が所有するデータのみを読み書きできるように制限しています。resource.dataは既存のドキュメントデータを、request.resource.dataは書き込み対象のデータを参照します。
本番環境では、allow read, write: if trueのようなオープンなルールは絶対に使用しないでください。これはデータベース全体を公開することを意味し、重大なセキュリティリスクとなります。Firebase App Checkと組み合わせて、不正なクライアントからのアクセスも防止することを推奨します。
オフライン対応とキャッシュ戦略
Firestoreは、デフォルトでオフライン永続化をサポートしています。ネットワーク接続が失われた場合でも、ローカルキャッシュからデータを読み取り、オンラインに復帰した際に自動的に同期されます。これにより、ユーザーは常にアプリケーションを使用できる状態が維持されます。
以下は、書き込みがまだサーバーに同期されていない状態を検出し、UIで表示する例です。
StreamBuilder<DocumentSnapshot>(
stream: FirebaseFirestore.instance
.collection('tasks')
.doc(taskId)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return const CircularProgressIndicator();
final data = snapshot.data!;
final isPending = data.metadata.hasPendingWrites;
return Row(
children: [
Text(data['title']),
if (isPending) const Icon(Icons.cloud_upload, size: 16),
],
);
},
)metadata.hasPendingWritesプロパティを確認することで、ローカルの変更がサーバーに同期されているかどうかを判定できます。これにより、ユーザーにデータの同期状態を視覚的にフィードバックすることが可能です。
本番アーキテクチャ:Repositoryパターン
大規模なアプリケーションでは、データアクセス層を抽象化するRepositoryパターンの採用が推奨されます。これにより、Firebaseへの依存を隔離し、テストの容易性と将来の変更への柔軟性を確保できます。
abstract class TaskRepository {
Future<String> create(String userId, String title);
Stream<List<Task>> watchAll(String userId);
Future<void> update(String id, Map<String, dynamic> fields);
Future<void> delete(String id);
}
// firebase_task_repository.dart
class FirebaseTaskRepository implements TaskRepository {
final _db = FirebaseFirestore.instance;
Future<String> create(String userId, String title) async {
final doc = await _db.collection('tasks').add({
'userId': userId,
'title': title,
'completed': false,
'createdAt': FieldValue.serverTimestamp(),
});
return doc.id;
}
Stream<List<Task>> watchAll(String userId) {
return _db
.collection('tasks')
.where('userId', isEqualTo: userId)
.orderBy('createdAt', descending: true)
.snapshots()
.map((s) => s.docs.map(Task.fromFirestore).toList());
}
// ... update and delete implementations
}抽象クラスTaskRepositoryを定義し、FirebaseTaskRepositoryで具体的な実装を提供することで、依存性注入を通じてモックリポジトリに差し替えることができます。これにより、ユニットテストでFirebaseに接続することなくビジネスロジックをテストできます。RiverpodやBLoCなどの状態管理も、Firestoreを意識せずにこのインターフェースだけを利用します。
FlutterFire 5へのアップグレードで壊れるもの
2026年10月のメジャーリリース(BoM 5.0.0、firebase_auth 7.0.0、cloud_firestore 7.0.0、firebase_core 5.0.0)は、DartのAPIよりもビルド要件を大きく変えています。ビルドやコードレビューで引っかかるのは次の点です。
- Android
minSdk24:プラグインはFirebase Android BoM 35をベースにしています。minSdkが21や23のままのプロジェクトはコンパイルできなくなります。 - Apple SDK 13:Firebase Apple SDKはSwift Package Managerで13.0.0(CocoaPodsでは12.19.0)に上がり、SwiftパッケージにはmacOS 11が必要です。
- App Check:
activateのパラメータ名がproviderWeb、providerAndroid、providerAppleに変更されました。 - 非推奨化:
cloud_firestore7.0.0でsetIndexConfigurationFromJSONが非推奨になり、firebase_ml_model_downloaderは公開が終了しました。 - 6.x系ですでに削除済み:
fetchSignInMethodsForEmail()とUser.updateEmail()。サインイン前にメールアドレスがどのプロバイダを使っているかを確認するコードは設計し直す必要があります。メール列挙保護によって、その情報は返されなくなっているためです。
パッケージごとの変更点の全体は、FlutterFireリリースノートとcloud_firestoreの変更履歴に掲載されています。
Flutter開発者向けFirebase面接質問
面接では、Firebaseサービスの概念的な理解と実装の両方が問われます。以下は、2026年のFlutter開発者面接で繰り返し出題される質問です。フレームワーク側の質問はFlutter面接質問のガイドで扱っています。
authStateChanges()はidTokenChanges()やuserChanges()と何が違いますか?
authStateChanges()はサインインとサインアウトのイベントでのみ発火します。idTokenChanges()はそれに加えて、IDトークンの更新時(およそ1時間ごと)にも発火します。userChanges()はそのすべてに加え、updateDisplayName()のようなプロフィール更新も捕捉します。画面遷移のガードには、ほとんどの場合authStateChanges()で足ります。
デバイスがオフラインのときにFirestoreへの書き込みを行うと、何が起きますか?
書き込みはローカルキャッシュと保留中の書き込みキューに保存されます。snapshots()のリスナーは、metadata.hasPendingWrites == trueの状態で更新後のデータを即座に受け取ります。接続が戻るとFirestoreは保留中の書き込みを自動的に同期し、最後にサーバーに届いた書き込みが優先されます。
チャットアプリのデータはFirestoreでどうモデリングすべきですか?
各ドキュメントにメタデータ(参加者、最新メッセージのタイムスタンプ)を持つchatsコレクションを用意し、各チャットドキュメントの下にmessagesサブコレクションを置きます。この構造により、ユーザーのチャット一覧を効率よく取得しつつ、会話ごとにメッセージをページネーションできます。一覧画面でサブコレクションを読まずに済むよう、最新メッセージは親ドキュメントに非正規化して保持します。
DateTime.now()よりFieldValue.serverTimestamp()を使うべき理由は何ですか?
DateTime.now()はデバイスの時計を使うため、不正確だったり改ざんされていたりする可能性があります。FieldValue.serverTimestamp()はFirestoreサーバーの時計を使うので、すべてのクライアントで一貫した順序が保証されます。メッセージの並び順、アクティビティフィード、監査ログなどで重要になります。
Firestoreで複合クエリはどう扱われ、インデックスの要件は何ですか?
whereとorderByで複数のフィールドを組み合わせるクエリには、複合インデックスが必要です。単一フィールドのインデックスは自動で作成されますが、複合インデックスはfirestore.indexes.jsonまたはFirebaseコンソールで手動で定義する必要があります。クエリが失敗すると、Firestoreは不足しているインデックスを作成するための直接リンクをログに出力します。
バッチ書き込みではなくトランザクションを使うべきなのはどんなときですか?
同じ操作の中で読み取ったデータに書き込みが依存する場合はトランザクションが必要です。たとえば、在庫が0より多いときだけ在庫を減らすケースです。読み取ったドキュメントがコミット前に変更されるとSDKはコールバックをリトライするため、コールバックに副作用を持たせてはいけません。バッチ書き込みは読み取りなしで複数の書き込みをアトミックに実行します。ドキュメントを作成しつつ別の場所のカウンターを更新する、といった用途です。オフライン時の挙動も異なり、バッチはキューに積まれますが、トランザクションは接続がなければ失敗します。
final db = FirebaseFirestore.instance;
// Transaction: read then write, retried on contention
await db.runTransaction((tx) async {
final ref = db.collection('products').doc(id);
final snap = await tx.get(ref);
final stock = snap.get('stock') as int;
if (stock <= 0) throw Exception('Out of stock');
tx.update(ref, {'stock': stock - 1});
});
// Batched write: atomic writes, no reads
final batch = db.batch();
batch.set(db.collection('orders').doc(), {'productId': id});
batch.update(db.collection('stats').doc('orders'), {
'count': FieldValue.increment(1),
});
await batch.commit();Firebaseで管理者ロールはどう実装しますか?
Admin SDKを通じて信頼できる環境からカスタムクレームを設定します。Flutterクライアントから設定することはありません。クレームはIDトークンの中に含まれるため、ルールは追加のドキュメント参照なしにrequest.auth.token.admin == trueとして読み取れます。カスタムクレームのドキュメントによるとペイロードの上限は1000バイトで、クライアントが新しいクレームを認識するのはトークン更新後です。更新はcurrentUser.getIdToken(true)で強制できます。
セキュリティルールとApp Checkの違いは何ですか?
セキュリティルールは、特定のユーザーが特定のドキュメントを読み書きできるかどうかを判断します。App Checkは、リクエストが正規のデバイス上の正規のアプリから来ていることを証明し、公開APIキーを使い回すスクリプトを遮断します。答えている問いが異なるため、本番アプリには両方が必要です。FlutterFire 5以降、App CheckはproviderAndroid、providerApple、providerWebで有効化します。
Firestoreの画面が高コストになる理由と、ページネーションの方法は?
Firestoreはドキュメントの読み取り、書き込み、削除の単位で課金されます。上限のないコレクションに対するリスナーは、初回ロードで条件に合うすべてのドキュメントを読み取り、その後は変更されたドキュメントごとに1回の読み取りが発生します。ページネーションにはオフセットではなくクエリカーソルを使います。最初のページはlimit(20)、次のページはstartAfterDocument(lastDoc)とすることで、各ページのコストは返されるドキュメント分だけになります。
FirestoreとRealtime Database、どちらをなぜ選びますか?
Firestoreはドキュメントをコレクションに格納し、インデックスによる複合クエリをサポートし、操作単位で課金されます。Realtime Databaseは単一のJSONツリーにデータを保存し、1つの子キーに対する浅いクエリのみを提供し、主に帯域幅とストレージで課金されます。そのため、プレゼンス表示のような小さく非常に頻繁な更新に向いています。新規のFlutterアプリの多くはFirestoreから始め、プレゼンス用途に限ってRealtime Databaseを追加します。
さらにFlutterの面接対策を進めるなら、専用の練習モジュールでこれらのテーマをインタラクティブなクイズと時間制限付きの課題で確認できます。
今すぐ練習を始めましょう!
面接シミュレーターと技術テストで知識をテストしましょう。
参考資料
- Firebase release notes for Flutter:BoM 5.0.0と5.1.0の内容、minSdk 24、App Checkのパラメータ名変更
- cloud_firestore changelog:6.3.0のPipelines、7.1.0の
FieldValue.minimum/maximumとfindNearestの距離 - firebase_auth changelog:6.0.0の
validatePassword、6.1.0のmacOSでのTOTP、fetchSignInMethodsForEmailの削除 - google_sign_in migration guide:7.0でのシングルトン化、
initialize、authenticate、認可の分離 - Firebase custom claims:1000バイトの上限とトークン更新
面接に向けたFlutter×Firebaseの要点
- FlutterFire BoM 5.1.0は
firebase_auth7.0.1とcloud_firestore7.1.0を含み、AndroidのminSdk24を必要とします google_sign_in7ではGoogleSignIn().signIn()がGoogleSignIn.instance.initialize()とauthenticate()に置き換わり、Firebaseに必要なのはidTokenだけですauthStateChanges()はリアクティブなストリームを提供し、手動チェックなしでアプリ全体のログイン状態を管理できますsnapshots()によるリアルタイム同期はポーリングを不要にし、StreamBuilderと直接組み合わせてUIを自動更新できます- 本番環境ではセキュリティルールが必須です。
request.auth.uidをドキュメントの所有者フィールドと必ず照合し、ロールにはカスタムクレームを使います - トランザクションはリトライ付きで読み取ってから書き込み、バッチ書き込みは書き込みのみを行います。ドキュメントの読み取りはすべて課金されるため、ページネーションにはカーソルを使います
- モバイルではオフライン永続化が追加コードなしで動作します。同期状態をユーザーに伝えるには
hasPendingWritesを使います - RepositoryパターンはFirebaseをビジネスロジックから切り離し、テストや将来の移行を容易にします
Flutter のバグを見つけられますか
実際のコード、隠れたバグ、1日1回。アカウントなしで試せます。

執筆
Anthony Fillion-MailletSharpSkill 創業者
10 年以上フルスタック開発に携わっています。SharpSkill を運営し、ここで公開される内容に責任を負っています。
2026年11月9日 更新
共有
関連記事

2026年フリーランスFlutterデベロッパー求人ガイド:案件の探し方、単価相場、面接準備
2026年にフリーランスFlutterデベロッパーとして活躍するための実践ガイド。案件の探し方、国別の日当相場、クライアントが求めるスキル、技術面接への準備方法を解説。

Flutter開発者の求人2026年版:求人の探し方、給与相場、面接対策
2026年のFlutter開発者向け求人市場を解説。求人サイトの活用法、地域別給与レンジ、リモートワーク事情、技術面接の準備方法まで網羅。

Flutter Impeller 2026年完全ガイド:新レンダリングエンジンの仕組み、パフォーマンス、面接対策
Flutter ImpellerはSkiaに代わる新しいレンダリングエンジンです。AOT(事前コンパイル)によるシェーダージャンクの解消、アーキテクチャ、プラットフォーム対応状況、パフォーマンスベンチマーク、面接でよく聞かれる質問を解説します。