ASP.NET Core MVC 및 Blazor Server 프로젝트에서 Serilog를 이용하여 SQL Server에 로그 저장하기

  • 9 minutes to read

1. 개요

이 문서는 ASP.NET Core MVCBlazor 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 + File Sink를 병행해 사용하시는 것이 좋습니다.
  • 환경별 필터링: restrictedToMinimumLevel 옵션을 조정해, 운영 시에는 Information 이하 로그를 제외할 수 있습니다.
  • 구성 분리: appsettings.Production.json 등에 Serilog 구성을 옮겨 코드 의존도를 낮추실 수 있습니다.
  • 성능 최적화: 대량 트래픽 환경에서는 Async Sink를 사용하여 로그 저장 시 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 뷰어 만들기

더 깊이 공부하고 싶다면
DevLec에서는 실무 중심의 C#, .NET, ASP.NET Core, Blazor, 데이터 액세스 강좌를 단계별로 제공합니다. 현재 수강 가능한 강좌 외에도 더 많은 과정이 준비되어 있습니다.
DevLec.com에서 자세한 커리큘럼을 확인해 보세요.
DevLec 공식 강의
C# Programming
C# 프로그래밍 입문
프로그래밍을 처음 시작하는 입문자를 위한 C# 기본기 완성 과정입니다.
ASP.NET Core 10.0
ASP.NET Core 10.0 시작하기 MVC Fundamentals Part 1 MVC Fundamentals Part 2
웹 애플리케이션의 구조와 MVC 패턴을 ASP.NET Core로 실습하며 익힐 수 있습니다.
Blazor Server
풀스택 웹개발자 과정 Part 1 풀스택 웹개발자 과정 Part 2 풀스택 웹개발자 과정 Part 3
실무에서 바로 활용 가능한 Blazor Server 기반 관리자·포털 프로젝트를 만들어 봅니다.
Data & APIs
Entity Framework Core 시작하기 ADO.NET Fundamentals Blazor Server Fundamentals Minimal APIs
데이터 액세스와 Web API를 함께 이해하면 실무 .NET 백엔드 개발에 큰 도움이 됩니다.
VisualAcademy Docs의 모든 콘텐츠, 이미지, 동영상의 저작권은 박용준에게 있습니다. 저작권법에 의해 보호를 받는 저작물이므로 무단 전재와 복제를 금합니다. 사이트의 콘텐츠를 복제하여 블로그, 웹사이트 등에 게시할 수 없습니다. 단, 링크와 SNS 공유, Youtube 동영상 공유는 허용합니다. www.VisualAcademy.com
박용준 강사의 모든 동영상 강의는 데브렉에서 독점으로 제공됩니다. www.devlec.com