ASP.NET Core MVC 및 Blazor Server 프로젝트에서 Serilog를 이용하여 SQL Server에 로그 저장하기
1. 개요
이 문서는 ASP.NET Core MVC와 Blazor Server 프로젝트에서 Serilog를 활용하여 SQL Server의 AppLogs 테이블에 로그를 저장하는 방법을 안내드립니다.
본 구성을 통해 Error, Information, Warning 등 다양한 로그 수준(Level)의 정보를 효율적으로 관리하실 수 있습니다.
또한 MVC와 Blazor Server 모두에서 동일한 로깅 구성을 사용할 수 있도록 설계되어 있습니다. 기본적으로 Serilog의 표준 테이블 스키마를 기반으로 하며, 운영 환경에서도 안정적으로 동작하도록 구성합니다.
2. Serilog 관련 NuGet 패키지 설치
먼저 터미널이나 패키지 관리자 콘솔에서 다음 명령어를 실행해 패키지를 설치하세요.
dotnet add package Serilog
dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Sinks.MSSqlServer
Serilog.AspNetCore는 ASP.NET Core 프레임워크와의 통합을,
Serilog.Sinks.MSSqlServer는 SQL Server로의 로그 저장 기능을 제공합니다.
3. SQL Server 로그 테이블 생성
다음은 AppLogs 테이블을 수동으로 생성하기 위한 SQL 스크립트입니다.
Serilog의 기본 스키마를 따르고 있으며, 운영 환경에서도 그대로 사용하실 수 있습니다.
CREATE TABLE AppLogs (
Id INT IDENTITY(1,1) PRIMARY KEY,
Message NVARCHAR(MAX),
MessageTemplate NVARCHAR(MAX),
Level NVARCHAR(128),
TimeStamp DATETIMEOFFSET,
Exception NVARCHAR(MAX),
Properties NVARCHAR(MAX)
);
참고로,
AutoCreateSqlTable = true옵션을 사용하시면 Serilog가 테이블을 자동으로 생성할 수도 있습니다. 그러나 운영 환경에서는 명시적으로 테이블을 직접 생성해 두시는 것을 권장드립니다.
4. Program.cs 또는 Startup.cs에 Serilog 구성 추가
다음은 Program.cs 기준의 구성 예시입니다. (ASP.NET Core 6 이상 버전 기준)
using Serilog;
using Serilog.Sinks.MSSqlServer;
using System.Data;
var builder = WebApplication.CreateBuilder(args);
#region Serilog
// 1. Serilog 컬럼 옵션 정의
var columnOptions = new ColumnOptions
{
Store = new List<StandardColumn>
{
StandardColumn.Message,
StandardColumn.MessageTemplate,
StandardColumn.Level,
StandardColumn.TimeStamp,
StandardColumn.Exception,
StandardColumn.Properties
}
};
// 2. Serilog 로거 구성
Serilog.Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.MSSqlServer(
connectionString: builder.Configuration.GetConnectionString("DefaultConnection"),
sinkOptions: new MSSqlServerSinkOptions
{
TableName = "AppLogs",
AutoCreateSqlTable = false
},
restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Error,
columnOptions: columnOptions
)
.Enrich.FromLogContext()
.CreateLogger();
// 3. ASP.NET Core 로깅 시스템에 Serilog를 등록
builder.Host.UseSerilog();
#endregion
var app = builder.Build();
app.UseRouting();
app.UseAuthorization();
app.MapControllers(); // MVC 라우팅
app.MapBlazorHub(); // Blazor Server 라우팅
app.MapFallbackToPage("/_Host");
app.Run();
위 설정은 Error 수준 이상의 로그를 SQL Server에 저장하며,
개발 중에는 콘솔에서도 로그를 동시에 확인하실 수 있습니다.
5. appsettings.json에 연결 문자열 추가
프로젝트의 appsettings.json 파일에 다음 내용을 추가해 주세요.
{
"ConnectionStrings": {
"DefaultConnection": "Server=.;Database=MyAppDb;Trusted_Connection=True;"
}
}
보안을 위해 운영 환경에서는 환경 변수나 Azure Key Vault를 통해 연결 문자열을 관리하시는 것을 권장드립니다.
6. 로그 사용 예시
(1) ILogger<T>를 주입받아 사용하기
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
_logger.LogInformation("HomeController의 Index 메서드가 호출되었습니다.");
return View();
}
}
(2) 예외 처리 구문에서 로그 기록하기
try
{
throw new Exception("의도적으로 발생시킨 테스트 예외입니다.");
}
catch (Exception ex)
{
_logger.LogError(ex, "예외 발생: {Message}", ex.Message);
}
위 예제는 예외 메시지뿐만 아니라 전체 스택 트레이스까지 기록하여 문제 원인을 쉽게 파악할 수 있도록 돕습니다.
7. SQL Server에서 로그 확인
SQL Server Management Studio(SSMS)에서 다음 쿼리를 실행하시면 최근 로그를 확인하실 수 있습니다.
SELECT TOP 100 *
FROM AppLogs
ORDER BY TimeStamp DESC;
운영 환경에서는 Power BI, Grafana, Kibana 등의 시각화 도구와 연동하여 로그 데이터를 실시간으로 모니터링하실 수도 있습니다.
8. 확장 및 운영 시 참고사항
- 테이블 분리:
AppLogs,AuditLogs,RequestLogs등 용도별로 테이블을 구분해 관리하실 수 있습니다. - 다중 Sink 구성: 개발 환경에서는
Console, 운영 환경에서는SQL Server + FileSink를 병행해 사용하시는 것이 좋습니다. - 환경별 필터링:
restrictedToMinimumLevel옵션을 조정해, 운영 시에는Information이하 로그를 제외할 수 있습니다. - 구성 분리:
appsettings.Production.json등에 Serilog 구성을 옮겨 코드 의존도를 낮추실 수 있습니다. - 성능 최적화: 대량 트래픽 환경에서는
AsyncSink를 사용하여 로그 저장 시 I/O 병목을 완화할 수 있습니다.
9. 마무리
이 구성을 적용하시면 ASP.NET Core MVC와 Blazor Server 애플리케이션의 로그를
중앙화된 SQL Server의 AppLogs 테이블에 안전하게 저장하실 수 있습니다.
저장된 로그는 장애 추적, 성능 분석, 사용자 행동 분석 등 다양한 진단 작업에 활용할 수 있으며, 필요 시 ELK Stack(Elasticsearch, Logstash, Kibana) 또는 Azure Application Insights와 같은 외부 분석 도구와 연동하여 더 높은 수준의 모니터링 환경을 구축하실 수도 있습니다.
10. 오래된 Startup.cs 기반 프로젝트에서의 Serilog 설정 (.NET 8 호환 유지용)
.NET 8 이상 환경에서도 Startup.cs 파일을 사용하는 레거시 초기화 방식은 여전히 동작합니다.
단, 이 방식은 ASP.NET Core 2.x~3.x 시절부터 이어져 온 형태로,
부팅 초기 오류는 로깅되지 않으며, 일부 API(IApplicationLifetime)는 최신 인터페이스(IHostApplicationLifetime)로 교체해야 합니다.
(1) Program.cs 설정
Host.CreateDefaultBuilder() 뒤에 .UseSerilog() 한 줄을 추가해 Serilog를 DI에 연결합니다.
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog() // DiagnosticContext 자동 등록
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.UseContentRoot(Directory.GetCurrentDirectory());
webBuilder.UseIISIntegration();
});
(2) Startup.cs 생성자 내부에서 Serilog 초기화
Startup 생성자 안에서 Serilog를 직접 구성합니다. 이때 AutoCreateSqlTable = true 옵션은 개발환경에서만 권장됩니다.
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
var columnOptions = new ColumnOptions
{
Store = new List<StandardColumn>
{
StandardColumn.Message,
StandardColumn.MessageTemplate,
StandardColumn.Level,
StandardColumn.TimeStamp,
StandardColumn.Exception,
StandardColumn.Properties
}
};
Serilog.Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.MSSqlServer(
connectionString: Configuration.GetConnectionString("DefaultConnection"),
sinkOptions: new MSSqlServerSinkOptions
{
TableName = "AppLogs",
AutoCreateSqlTable = env.IsDevelopment()
},
restrictedToMinimumLevel: LogEventLevel.Information,
columnOptions: columnOptions
)
.CreateLogger();
Serilog.Log.Information("Serilog MSSQL sink initialized.");
}
(3) Serilog를 ASP.NET Core 로깅 파이프라인에 연결
ConfigureServices() 내부에서 기본 로깅 공급자를 지우고 Serilog를 추가합니다.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddLogging(b =>
{
b.ClearProviders();
b.AddSerilog(dispose: false);
});
}
(4) 종료 시 Flush 처리 (IHostApplicationLifetime 사용)
.NET 8에서는 IApplicationLifetime 대신 IHostApplicationLifetime을 사용해야 합니다.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseSerilogRequestLogging();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseMvc();
// 종료 시 Serilog Flush (최신 방식)
var lifetime = app.ApplicationServices.GetRequiredService<Microsoft.Extensions.Hosting.IHostApplicationLifetime>();
lifetime.ApplicationStopped.Register(Serilog.Log.CloseAndFlush);
}
(5) 주요 차이점 요약
| 구분 | 오래된 Startup.cs 방식 | 최신 Program.cs 단일 파일 방식 |
|---|---|---|
| 초기화 시점 | Startup 생성자 | Program.cs(Host 빌드 이전) |
| 초기 오류 로깅 | 불가 | 가능 |
| DI 등록 방식 | services.AddLogging().AddSerilog() | builder.Host.UseSerilog() |
| 종료 처리 | IHostApplicationLifetime 수동 등록 | 자동 Flush 지원 |
| 유지보수성 | 낮음 | 높음 |
| .NET 8 호환성 | (가능) | (권장) |
이 구성은 “.NET 8로 업그레이드된 구형 Startup 기반 프로젝트”에서도
문제없이 작동하며, Program.cs 기반의 최신 방식으로 이행하기 전 중간 단계 호환 설정으로 활용할 수 있습니다.
기타
ASP.NET Core MVC Serilog 뷰어 만들기