본문으로 건너뛰기

미들웨어 가이드

Caffeine Engine의 HTTP 미들웨어 파이프라인 구성 및 ExceptionHandlingMiddleware 사용 가이드이다.

개요

Caffeine.Engine은 ASP.NET Core 미들웨어 파이프라인을 사용하여 HTTP 요청을 처리한다. 전역 예외 처리, gRPC-Web 지원, CORS 등의 횡단 관심사(Cross-Cutting Concerns)를 미들웨어로 분리하여 Controller의 책임을 단순화한다.

미들웨어 파이프라인 구성

등록 순서

Engine의 Program.cs에서 미들웨어가 등록되는 순서는 다음과 같다. 요청은 위에서 아래로, 응답은 아래에서 위로 처리된다.

환경별 활성화

미들웨어DevelopmentProduction
Swagger UI활성비활성
HTTPS Redirection비활성활성
ExceptionHandlingMiddleware활성활성
gRPC-Web활성활성
WebSocket활성활성
CORS활성활성

ExceptionHandlingMiddleware

목적

모든 처리되지 않은 예외를 파이프라인 최상단에서 catch하여 다음을 보장한다:

  1. 보안: 내부 에러 상세(스택 트레이스, DB 쿼리, 연결 문자열 등)를 클라이언트에 노출하지 않음
  2. 일관성: 모든 에러 응답이 동일한 ApiErrorResponse 형식
  3. 관측성: 모든 예외가 구조화된 로그로 기록

동작 흐름

요청 수신
|
v
ExceptionHandlingMiddleware.InvokeAsync()
|
+-- try: await _next(context) → 정상 처리 시 응답 반환
|
+-- catch(Exception ex):
|
+-- Logger.LogError(ex, "처리되지 않은 예외 발생: {Path}")
|
+-- HandleExceptionAsync(context, ex)
|
+-- Status: 500
+-- Content-Type: application/json
+-- Body: ApiErrorResponse (camelCase)

ApiErrorResponse 모델

위치: src/Caffeine.Core/Models/ApiErrorResponse.cs

public record ApiErrorResponse
{
public required string Code { get; init; } // 에러 코드
public required string Message { get; init; } // 사용자 메시지
public string? TraceId { get; init; } // 추적 ID
}

응답 예시:

{
"code": "INTERNAL_SERVER_ERROR",
"message": "서버 내부 오류가 발생했습니다.",
"traceId": "00-abc123def456-789ghi-01"
}

설계 결정 사항

항목결정이유
위치파이프라인 최상단Controller, gRPC, SignalR 이전에 모든 예외 포착
상태 코드항상 500예외 유형별 분류는 Controller 책임
메시지고정 문자열내부 정보 노출 방지 (OWASP 준수)
TraceIdActivity.Current?.Id 우선OpenTelemetry 분산 추적과 연계
JSON 직렬화camelCase프론트엔드 JavaScript 관례 준수

Core 계층에 ApiErrorResponse를 배치한 이유

ApiErrorResponse는 Engine의 Controller뿐만 아니라 향후 Admin, Bridge 등 여러 프로젝트에서 공유할 수 있는 공통 에러 모델이다. Clean Architecture 원칙에 따라 공유 모델은 최하위 계층인 Caffeine.Core에 배치한다.

CORS 설정

Admin UI(Blazor Server)와 Engine API 간 Cross-Origin 통신을 위해 CORS 정책을 구성한다.

허용 정책 (AllowAdminUI)

항목설정
Originshttp://localhost:5200, http://localhost:5233
HeadersContent-Type, Authorization, X-Requested-With
MethodsGET, POST, PUT, DELETE
Credentials허용 (AllowCredentials)

프로덕션 환경 주의사항

프로덕션 배포 시에는 WithOrigins()에 실제 Admin 도메인을 명시해야 한다. 와일드카드(*) 사용은 보안상 금지된다.

gRPC-Web 미들웨어

gRPC-Web 프로토콜을 지원하여 웹 브라우저에서 직접 gRPC 서비스를 호출할 수 있다.

app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });
  • DefaultEnabled = true: 모든 gRPC 서비스에 자동 적용
  • EnableGrpcWeb(): 개별 서비스에 명시적 적용 가능

문제 해결

에러 응답에서 상세 정보가 필요한 경우

ExceptionHandlingMiddleware는 보안을 위해 에러 상세를 숨긴다. 디버깅이 필요한 경우:

  1. TraceId 활용: 응답의 traceId로 서버 로그에서 전체 스택 트레이스 검색
  2. Serilog SQLite Sink: logs/log.db 파일에서 에러 로그 조회
  3. OpenTelemetry: 분산 추적 시스템에서 TraceId로 요청 흐름 추적

CORS 에러 발생 시

  • 브라우저 개발자 도구 > Network 탭에서 Access-Control-Allow-Origin 헤더 확인
  • Engine의 CORS 정책에 Admin UI의 Origin이 포함되어 있는지 검증
  • AllowCredentials와 와일드카드 Origin은 동시 사용 불가

참고 자료


작성일: 2026-02-09 버전: 1.0