feat: DI 컨테이너 및 서비스 등록 구조화 (#26)
All checks were successful
SPMS_API/pipeline/head This commit looks good
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:
commit
0070ae58b9
80
SPMS.API/Extensions/ApplicationBuilderExtensions.cs
Normal file
80
SPMS.API/Extensions/ApplicationBuilderExtensions.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,7 @@
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using SPMS.API.Extensions;
|
using SPMS.API.Extensions;
|
||||||
using SPMS.API.Middlewares;
|
using SPMS.Application;
|
||||||
using SPMS.Application.Interfaces;
|
|
||||||
using SPMS.Domain.Interfaces;
|
|
||||||
using SPMS.Infrastructure;
|
using SPMS.Infrastructure;
|
||||||
using SPMS.Infrastructure.Auth;
|
|
||||||
using SPMS.Infrastructure.Persistence;
|
|
||||||
using SPMS.Infrastructure.Persistence.Repositories;
|
|
||||||
|
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
|
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
|
||||||
{
|
{
|
||||||
|
|
@ -20,74 +13,19 @@ var builder = WebApplication.CreateBuilder(new WebApplicationOptions
|
||||||
builder.Host.UseSerilog((context, config) =>
|
builder.Host.UseSerilog((context, config) =>
|
||||||
config.ReadFrom.Configuration(context.Configuration));
|
config.ReadFrom.Configuration(context.Configuration));
|
||||||
|
|
||||||
|
// ===== 2. Services (DI) =====
|
||||||
|
builder.Services.AddApplication();
|
||||||
|
builder.Services.AddInfrastructure(builder.Configuration);
|
||||||
|
|
||||||
|
// ===== 3. Presentation =====
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
builder.Services.AddOpenApi();
|
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.AddJwtAuthentication(builder.Configuration);
|
||||||
builder.Services.AddAuthorizationPolicies();
|
builder.Services.AddAuthorizationPolicies();
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// ── 1. 예외 처리 (최외곽 — 이후 모든 미들웨어 예외 포착) ──
|
// ===== 4. Middleware Pipeline =====
|
||||||
app.UseMiddleware<ExceptionMiddleware>();
|
app.UseMiddlewarePipeline();
|
||||||
|
|
||||||
// ── 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");
|
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
|
|
|
||||||
14
SPMS.Application/DependencyInjection.cs
Normal file
14
SPMS.Application/DependencyInjection.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,4 +10,8 @@
|
||||||
<ProjectReference Include="..\SPMS.Domain\SPMS.Domain.csproj" />
|
<ProjectReference Include="..\SPMS.Domain\SPMS.Domain.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
32
SPMS.Infrastructure/DependencyInjection.cs
Normal file
32
SPMS.Infrastructure/DependencyInjection.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user