エラーハンドリング設計の実践ガイド
適切なエラーハンドリングにより、弊社ではユーザーからの問い合わせが58%減少、開発者のデバッグ時間が62%短縮、エラー復旧率が34%から87%へ向上しました。
エラーは必ず発生します。重要なのは、ユーザーには分かりやすく、開発者には詳細な情報を提供する設計です。
原則1: ユーザー向けメッセージは具体的に
❌ 悪い例
「エラーが発生しました」
→ ユーザーは何をすべきか分からず、問い合わせ急増
✅ 良い例
「メールアドレスの形式が正しくありません。@を含む形式で入力してください。」
→ ユーザーが自分で解決できる
✅ 良い例(外部API障害)
「決済サービスが一時的に利用できません。5分後に再度お試しいただくか、別の決済方法をお選びください。」
→ 代替手段を提示
原則2: エラーコードによる分類
エラーを体系的に分類することで、ログ検索とアラート設定が容易になります。
エラーコード体系例:
4xxx: クライアントエラー(ユーザー起因)
- • 4001: 必須項目未入力
- • 4002: メールアドレス形式不正
- • 4003: パスワード条件不一致
5xxx: サーバーエラー(システム起因)
- • 5001: DB接続エラー
- • 5002: 外部API タイムアウト
- • 5003: ファイル書き込み失敗
6xxx: ビジネスロジックエラー
- • 6001: 在庫不足
- • 6002: クーポン有効期限切れ
- • 6003: 購入上限超過
原則3: リトライ戦略
一時的なエラーは指数バックオフでリトライすることで、成功率が大幅に向上。
指数バックオフの実装例(TypeScript):
async function fetchWithRetry(
url: string,
maxRetries = 3
): Promise<Response> {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url);
if (response.ok) return response;
// 5xx エラーはリトライ
if (response.status >= 500 && i < maxRetries - 1) {
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw new Error(`HTTP ${response.status}`);
} catch (error) {
if (i === maxRetries - 1) throw error;
const delay = Math.pow(2, i) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw new Error('Max retries reached');
}効果: 一時的なネットワークエラーでの成功率が34%から87%に向上(弊社実績)
原則4: グローバルエラーハンドラー
予期しないエラーも必ずキャッチして記録する。
React Error Boundary:
class ErrorBoundary extends React.Component {
componentDidCatch(error, errorInfo) {
// エラーをログに記録
logger.error({
message: error.message,
stack: error.stack,
componentStack: errorInfo.componentStack,
url: window.location.href,
userAgent: navigator.userAgent
});
}
render() {
if (this.state.hasError) {
return (
<div>
<h1>予期しないエラーが発生しました</h1>
<p>お手数ですが、ページを再読み込みしてください。</p>
<button onClick={() => window.location.reload()}>
再読み込み
</button>
</div>
);
}
return this.props.children;
}
}まとめ
エラーは必ず発生します。ユーザーには具体的で分かりやすく、開発者には詳細なエラー情報を提供することで、問い合わせ減少とデバッグ時間短縮を実現できます。エラーコードによる分類、指数バックオフリトライ、グローバルエラーハンドラー。これらを実装することで、システムの堅牢性が大幅に向上します。
弊社では、適切なエラーハンドリングにより、ユーザーからの問い合わせが58%減少、デバッグ時間が62%短縮しました。