Advanced

Error Handling Design Patterns: Claude Code 활용 가이드

error handling design patterns: Claude Code 활용. 실용적인 팁과 코드 예시를 포함합니다.

에러 핸들링の설계をClaude Code로改善する

적절한에러 핸들링は애플리케이션の堅牢性に直結します。Claude Code를 활용하면 타입安全で一貫性のある에러 핸들링パターンを효율적으로구현할 수 있습니다。

カスタム에러클래스の설계

> 애플리케이션全体で使うカスタム에러클래스を설계して。
> HTTPステータスコードとの대응、에러コード、
> 사용자向けメッセージを含めて。
// errors/base.ts
export abstract class AppError extends Error {
  abstract readonly statusCode: number;
  abstract readonly code: string;
  readonly isOperational: boolean;

  constructor(message: string, isOperational = true) {
    super(message);
    this.name = this.constructor.name;
    this.isOperational = isOperational;
    Error.captureStackTrace(this, this.constructor);
  }

  toJSON() {
    return {
      error: {
        code: this.code,
        message: this.message,
        ...(process.env.NODE_ENV === "development" && { stack: this.stack }),
      },
    };
  }
}

// errors/http.ts
export class NotFoundError extends AppError {
  readonly statusCode = 404;
  readonly code = "NOT_FOUND";

  constructor(resource: string, id?: string) {
    super(id ? `${resource}(${id})が見つかりません` : `${resource}が見つかりません`);
  }
}

export class ValidationError extends AppError {
  readonly statusCode = 400;
  readonly code = "VALIDATION_ERROR";
  readonly fields: Record<string, string[]>;

  constructor(fields: Record<string, string[]>) {
    super("バリデーションエラーがあります");
    this.fields = fields;
  }

  toJSON() {
    return {
      error: {
        code: this.code,
        message: this.message,
        fields: this.fields,
      },
    };
  }
}

export class UnauthorizedError extends AppError {
  readonly statusCode = 401;
  readonly code = "UNAUTHORIZED";
  constructor(message = "Authentication required") {
    super(message);
  }
}

export class ForbiddenError extends AppError {
  readonly statusCode = 403;
  readonly code = "FORBIDDEN";
  constructor(message = "権限がありません") {
    super(message);
  }
}

Result타입パターン

예외を使わずに에러を타입安全に扱うResult타입パターンです。

> Result타입パターン를 구현해줘。
> 성공と실패を타입レベルで区別できるように。
// types/result.ts
type Result<T, E = Error> =
  | { success: true; data: T }
  | { success: false; error: E };

function ok<T>(data: T): Result<T, never> {
  return { success: true, data };
}

function err<E>(error: E): Result<never, E> {
  return { success: false, error };
}

// Usage example
async function findUser(id: string): Promise<Result<User, NotFoundError>> {
  const user = await db.user.findUnique({ where: { id } });
  if (!user) {
    return err(new NotFoundError("User", id));
  }
  return ok(user);
}

// 呼び出し側
const result = await findUser("123");
if (result.success) {
  console.log(result.data.name); // 타입安全にアクセス
} else {
  console.log(result.error.message); // 에러타입も타입安全
}

グローバル에러핸들러ー

Express用のグローバル에러핸들러ーを구현します。

> Expressのグローバル에러핸들러ー미들웨어를 생성해줘。
> AppErrorは적절한응답に変換、予期しない에러は500に。
> 프로덕션 환경では스택トレースを隠す。
import { Request, Response, NextFunction } from "express";
import { AppError } from "../errors/base";

export function globalErrorHandler(
  err: Error,
  req: Request,
  res: Response,
  _next: NextFunction
) {
  // 로그출력
  if (err instanceof AppError && err.isOperational) {
    console.warn(`[${err.code}] ${err.message}`);
  } else {
    console.error("Unexpected error:", err);
  }

  // AppError의 경우は定義された응답を返す
  if (err instanceof AppError) {
    return res.status(err.statusCode).json(err.toJSON());
  }

  // 予期しない에러
  res.status(500).json({
    error: {
      code: "INTERNAL_ERROR",
      message: process.env.NODE_ENV === "production"
        ? "サーバーエラーが発生しました"
        : err.message,
    },
  });
}

비동기에러のキャッチ

> Express のasync route handlerの에러を
> 自動キャッチするラッパー를 생성해줘。
import { Request, Response, NextFunction, RequestHandler } from "express";

function asyncHandler(
  fn: (req: Request, res: Response, next: NextFunction) => Promise<void>
): RequestHandler {
  return (req, res, next) => {
    fn(req, res, next).catch(next);
  };
}

// Usage example:try-catchが不要に
router.get("/users/:id", asyncHandler(async (req, res) => {
  const user = await userService.findById(req.params.id);
  if (!user) {
    throw new NotFoundError("User", req.params.id);
  }
  res.json({ data: user });
}));

프론트엔드の에러バウンダリ

> React Error Boundary 를 생성해줘。
> 에러の種類に応じて異なるUIを표시して。
import { Component, ReactNode } from "react";

interface Props {
  children: ReactNode;
  fallback?: (error: Error, retry: () => void) => ReactNode;
}

interface State {
  error: Error | null;
}

class ErrorBoundary extends Component<Props, State> {
  state: State = { error: null };

  static getDerivedStateFromError(error: Error) {
    return { error };
  }

  handleRetry = () => {
    this.setState({ error: null });
  };

  render() {
    if (this.state.error) {
      if (this.props.fallback) {
        return this.props.fallback(this.state.error, this.handleRetry);
      }
      return (
        <div className="p-8 text-center">
          <h2 className="text-xl font-bold text-red-600">エラーが発生しました</h2>
          <p className="mt-2 text-gray-600">{this.state.error.message}</p>
          <button
            onClick={this.handleRetry}
            className="mt-4 rounded bg-blue-500 px-4 py-2 text-white"
          >
            再試行
          </button>
        </div>
      );
    }
    return this.props.children;
  }
}

디버깅と에러調査の구체적인方法は디버깅テクニック完全가이드を、TypeScriptでの타입설계はTypeScript개발での활용法를 참고하세요.보안の観点からの에러情報の扱い方は보안監査の자동화도 함께 확인하세요.

정리

一貫した에러 핸들링설계により、애플리케이션の堅牢性と유지보수성が大幅に向上します。Claude Code를 활용하면 カスタム에러클래스、Result타입、グローバル핸들러ーを효율적으로구현할 수 있습니다。

에러 핸들링の모범 사례はNode.js公式가이드、Claude Code에ついてはAnthropic공식 문서를 참고하세요.

#Claude Code #error handling #design patterns #TypeScript #robustness