미들웨어 가이드
Caffeine Engine의 HTTP 미들웨어 파이프라인 구성 및 ExceptionHandlingMiddleware 사용 가이드이다.
개요
Caffeine.Engine은 ASP.NET Core 미들웨어 파이프라인을 사용하여 HTTP 요청을 처리한다. 전역 예외 처리, gRPC-Web 지원, CORS 등의 횡단 관심사(Cross-Cutting Concerns)를 미들웨어로 분리하여 Controller의 책임을 단순화한다.
미들웨어 파이프라인 구성
등록 순서
Engine의 Program.cs에서 미들웨어가 등록되는 순서는 다음과 같다. 요청은 위에서 아래로, 응답은 아래에서 위로 처리된다.
환경별 활성화
| 미들웨어 | Development | Production |
|---|---|---|
| Swagger UI | 활성 | 비활성 |
| HTTPS Redirection | 비활성 | 활성 |
| ExceptionHandlingMiddleware | 활성 | 활성 |
| gRPC-Web | 활성 | 활성 |
| WebSocket | 활성 | 활성 |
| CORS | 활성 | 활성 |
ExceptionHandlingMiddleware
목적
모든 처리되지 않은 예외를 파이프라인 최상단에서 catch하여 다음을 보장한다:
- 보안: 내부 에러 상세(스택 트레이스, DB 쿼리, 연결 문자열 등)를 클라이언트에 노출하지 않음
- 일관성: 모든 에러 응답이 동일한
ApiErrorResponse형식 - 관측성: 모든 예외가 구조화된 로그로 기록
동작 흐름
요청 수신
|
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 준수) |
| TraceId | Activity.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)
| 항목 | 설정 |
|---|---|
| Origins | http://localhost:5200, http://localhost:5233 |
| Headers | Content-Type, Authorization, X-Requested-With |
| Methods | GET, POST, PUT, DELETE |
| Credentials | 허용 (AllowCredentials) |
프로덕션 환경 주의사항
프로덕션 배포 시에는 WithOrigins()에 실제 Admin 도메인을 명시해야 한다. 와일드카드(*) 사용은 보안상 금지된다.
gRPC-Web 미들웨어
gRPC-Web 프로토콜을 지원하여 웹 브라우저에서 직접 gRPC 서비스를 호출할 수 있다.
app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });
DefaultEnabled = true: 모든 gRPC 서비스에 자동 적용EnableGrpcWeb(): 개별 서비스에 명시적 적용 가능
문제 해결
에러 응답에서 상세 정보가 필요한 경우
ExceptionHandlingMiddleware는 보안을 위해 에러 상세를 숨긴다. 디버깅이 필요한 경우:
- TraceId 활용: 응답의
traceId로 서버 로그에서 전체 스택 트레이스 검색 - Serilog SQLite Sink:
logs/log.db파일에서 에러 로그 조회 - OpenTelemetry: 분산 추적 시스템에서 TraceId로 요청 흐름 추적
CORS 에러 발생 시
- 브라우저 개발자 도구 > Network 탭에서
Access-Control-Allow-Origin헤더 확인 - Engine의 CORS 정책에 Admin UI의 Origin이 포함되어 있는지 검증
AllowCredentials와 와일드카드 Origin은 동시 사용 불가
참고 자료
- 시스템 아키텍처 가이드 -- 전체 시스템 구조
- 설정 가이드 -- 환경변수 및 보안 설정
- ASP.NET Core Middleware 공식 문서
작성일: 2026-02-09 버전: 1.0