feat: DI 컨테이너 및 서비스 등록 구조화 (#26)
All checks were successful
SPMS_API/pipeline/head This commit looks good

Reviewed-on: https://git.ipstein.myds.me/SPMS/SPMS_API/pulls/27
This commit is contained in:
김선규 2026-02-09 07:28:03 +00:00
commit 0070ae58b9
5 changed files with 138 additions and 70 deletions

View File

@ -0,0 +1,80 @@
using Serilog;
using SPMS.API.Middlewares;
namespace SPMS.API.Extensions;
public static class ApplicationBuilderExtensions
{
public static WebApplication UseMiddlewarePipeline(this WebApplication app)
{
// -- 1. 예외 처리 (최외곽 — 이후 모든 미들웨어 예외 포착) --
app.UseMiddleware<ExceptionMiddleware>();
// -- 2. 보안 헤더 주입 (미구현) --
// app.UseMiddleware<SecurityHeadersMiddleware>();
// -- 3. X-Request-ID 발급/반환 (클라이언트 디버깅용) --
app.UseMiddleware<RequestIdMiddleware>();
// -- 4. Serilog 구조적 로깅 (X-Request-ID 이후에 위치) --
app.UseSerilogRequestLogging(options =>
{
options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
{
if (httpContext.Items.TryGetValue("RequestId", out var requestId))
{
diagnosticContext.Set("RequestId", requestId);
}
};
});
// -- 5. HTTPS 리다이렉션 (Nginx가 HTTPS 처리하므로 Production에서만) --
if (!app.Environment.IsDevelopment())
{
app.UseHttpsRedirection();
}
// -- 6. 정적 파일 서빙 --
var webRoot = app.Environment.WebRootPath;
if (Directory.Exists(webRoot))
{
app.UseStaticFiles();
}
// -- 7. 라우팅 --
app.UseRouting();
// -- 8. CORS (미구현) --
// app.UseCors("DefaultPolicy");
// -- 9. API 속도 제한 (미구현 — Issue #12) --
// app.UseRateLimiter();
// -- 10. JWT 인증 --
app.UseAuthentication();
// -- 11. 역할 인가 --
app.UseAuthorization();
// -- 12. X-Service-Code 서비스 식별 (미구현 — Issue #13) --
// app.UseMiddleware<ServiceCodeMiddleware>();
// -- 13. X-API-KEY 검증 (미구현 — Issue #13) --
// app.UseMiddleware<ApiKeyMiddleware>();
// -- 14. X-SPMS-TEST 샌드박스 모드 (미구현 — Issue #14) --
// app.UseMiddleware<SandboxMiddleware>();
// -- 15. OpenAPI (개발 환경만) --
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
// -- 16. 엔드포인트 매핑 --
app.MapControllers();
app.MapFallbackToFile("index.html");
return app;
}
}

View File

@ -1,14 +1,7 @@
using Microsoft.EntityFrameworkCore;
using Serilog;
using SPMS.API.Extensions;
using SPMS.API.Middlewares;
using SPMS.Application.Interfaces;
using SPMS.Domain.Interfaces;
using SPMS.Application;
using SPMS.Infrastructure;
using SPMS.Infrastructure.Auth;
using SPMS.Infrastructure.Persistence;
using SPMS.Infrastructure.Persistence.Repositories;
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
@ -20,74 +13,19 @@ var builder = WebApplication.CreateBuilder(new WebApplicationOptions
builder.Host.UseSerilog((context, config) =>
config.ReadFrom.Configuration(context.Configuration));
// ===== 2. Services (DI) =====
builder.Services.AddApplication();
builder.Services.AddInfrastructure(builder.Configuration);
// ===== 3. Presentation =====
builder.Services.AddControllers();
builder.Services.AddOpenApi();
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)));
builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
builder.Services.AddScoped<IUnitOfWork, UnitOfWork>();
builder.Services.AddScoped<IJwtService, JwtService>();
// JWT 인증/인가
builder.Services.AddJwtAuthentication(builder.Configuration);
builder.Services.AddAuthorizationPolicies();
var app = builder.Build();
// ── 1. 예외 처리 (최외곽 — 이후 모든 미들웨어 예외 포착) ──
app.UseMiddleware<ExceptionMiddleware>();
// ── 3. X-Request-ID 발급/반환 (클라이언트 디버깅용) ──
app.UseMiddleware<RequestIdMiddleware>();
// ── 4. Serilog 구조적 로깅 (X-Request-ID 이후에 위치) ──
app.UseSerilogRequestLogging(options =>
{
options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
{
if (httpContext.Items.TryGetValue("RequestId", out var requestId))
{
diagnosticContext.Set("RequestId", requestId);
}
};
});
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
var webRoot = app.Environment.WebRootPath;
Console.WriteLine($"[System] Web Root Path: {webRoot}");
if (Directory.Exists(webRoot))
{
app.UseStaticFiles();
}
else
{
Console.WriteLine("[Error] Web root folder not found!");
}
// ── 5. HTTPS 리다이렉션 (Nginx가 HTTPS 처리하므로 Production에서만) ──
if (!app.Environment.IsDevelopment())
{
app.UseHttpsRedirection();
}
app.UseRouting();
// ── 10. JWT 인증 ──
app.UseAuthentication();
// ── 11. 역할 인가 ──
app.UseAuthorization();
// [엔드포인트 매핑]
app.MapControllers();
app.MapFallbackToFile("index.html");
// ===== 4. Middleware Pipeline =====
app.UseMiddlewarePipeline();
app.Run();

View File

@ -0,0 +1,14 @@
using Microsoft.Extensions.DependencyInjection;
namespace SPMS.Application;
public static class DependencyInjection
{
public static IServiceCollection AddApplication(this IServiceCollection services)
{
// Application Services
// services.AddScoped<IAuthService, AuthService>();
return services;
}
}

View File

@ -10,4 +10,8 @@
<ProjectReference Include="..\SPMS.Domain\SPMS.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.2" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,32 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using SPMS.Application.Interfaces;
using SPMS.Domain.Interfaces;
using SPMS.Infrastructure.Auth;
using SPMS.Infrastructure.Persistence;
using SPMS.Infrastructure.Persistence.Repositories;
namespace SPMS.Infrastructure;
public static class DependencyInjection
{
public static IServiceCollection AddInfrastructure(
this IServiceCollection services,
IConfiguration configuration)
{
// DbContext
var connectionString = configuration.GetConnectionString("DefaultConnection");
services.AddDbContext<AppDbContext>(options =>
options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)));
// UnitOfWork & Repositories
services.AddScoped<IUnitOfWork, UnitOfWork>();
services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
// External Services
services.AddScoped<IJwtService, JwtService>();
return services;
}
}