시스템 로그를 데이터베이스에 저장하는 ASP.NET Core 구현 가이드
이 가이드는 Blazor Web App 프로젝트인 Azunt.Web
에서 시스템 예외를 ErrorLogs
테이블에 저장하기 위한 전 과정을 설명합니다. MVC 또는 Blazor 환경 모두에서 사용할 수 있습니다.
1. 데이터베이스 테이블 생성
SQL Server에서 다음 스크립트를 실행하여 로그 테이블을 생성합니다.
CREATE TABLE ErrorLogs (
Id INT PRIMARY KEY IDENTITY,
LogLevel NVARCHAR(50),
Message NVARCHAR(MAX),
StackTrace NVARCHAR(MAX),
Source NVARCHAR(255),
CreatedAt DATETIME DEFAULT GETDATE()
);
2. EF Core 모델 정의
Models/ErrorLog.cs
:
public class ErrorLog
{
public int Id { get; set; }
public string LogLevel { get; set; } = "Error";
public string Message { get; set; } = string.Empty;
public string? StackTrace { get; set; }
public string? Source { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}
3. DbContext에 포함
ApplicationDbContext.cs
:
public class ApplicationDbContext : IdentityDbContext
{
public DbSet<ErrorLog> ErrorLogs { get; set; }
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
}
4. 로그 저장 서비스 구현
Services/ErrorLogService.cs
:
public class ErrorLogService
{
private readonly ApplicationDbContext _db;
public ErrorLogService(ApplicationDbContext db)
{
_db = db;
}
public async Task LogErrorAsync(Exception ex, string? source = null)
{
var log = new ErrorLog
{
Message = ex.Message,
StackTrace = ex.StackTrace,
Source = source,
LogLevel = "Error"
};
_db.ErrorLogs.Add(log);
await _db.SaveChangesAsync();
}
}
5. DI 등록
Program.cs
:
builder.Services.AddScoped<ErrorLogService>();
6. 마이그레이션 적용
패키지 관리자 콘솔 또는 CLI에서 실행:
dotnet ef migrations add AddErrorLogs
dotnet ef database update
7. 로그 테스트 예제
Blazor Web App에서는 서버 측 예외를 구성 요소 내부에서 try-catch로 잡아 처리할 수 있습니다. 아래는 MVC 컨트롤러와 Blazor Server 페이지에서 로그를 저장하는 예제입니다.
(1) MVC Controller에서 사용 예시
public class DemoController : Controller
{
private readonly ErrorLogService _errorLogService;
public DemoController(ErrorLogService errorLogService)
{
_errorLogService = errorLogService;
}
public async Task<IActionResult> Index()
{
try
{
throw new InvalidOperationException("MVC 테스트 예외입니다.");
}
catch (Exception ex)
{
await _errorLogService.LogErrorAsync(ex, nameof(DemoController));
return Json(new { error = "문제가 발생했습니다.", details = ex.Message });
}
}
}
(2) Blazor Server 구성 요소에서 사용 예시
Pages/TestError.razor
:
@page "/test-error"
@inject ErrorLogService ErrorLogService
<h3>Blazor 테스트</h3>
<button class="btn btn-danger" @onclick="TriggerError">예외 발생</button>
@code {
private async Task TriggerError()
{
try
{
throw new NullReferenceException("Blazor 테스트 예외입니다.");
}
catch (Exception ex)
{
await ErrorLogService.LogErrorAsync(ex, nameof(TestError));
}
}
}
8. 관리자 로그 리스트 페이지 (QuickGrid 및 페이징 UI 포함)
Blazor Server 프로젝트의 Pages
폴더에 ErrorLogList.razor
파일을 생성합니다. 이 페이지는 QuickGrid 컴포넌트를 사용하여 로그를 페이징 처리해 보여주며, 페이지 이동을 위한 간단한 UI도 포함합니다.
Pages/ErrorLogList.razor
:
@page "/admin/error-logs"
@inject ApplicationDbContext DbContext
@using Microsoft.AspNetCore.Components.QuickGrid
@using System.Linq
<PageTitle>Error Logs</PageTitle>
<h3>Error Log List</h3>
<QuickGrid Items="pagedLogs">
<PropertyColumn Property="@nameof(ErrorLog.Id)" Title="ID" />
<PropertyColumn Property="@nameof(ErrorLog.LogLevel)" Title="Level" />
<PropertyColumn Property="@nameof(ErrorLog.Message)" Title="Message" />
<PropertyColumn Property="@nameof(ErrorLog.Source)" Title="Source" />
<PropertyColumn Property="@nameof(ErrorLog.CreatedAt)" Title="Created" />
</QuickGrid>
<div class="mt-3">
<button class="btn btn-secondary" @onclick="PrevPage" disabled="@(!HasPrev)">이전</button>
<span class="mx-2">페이지 @currentPage / @totalPages</span>
<button class="btn btn-secondary" @onclick="NextPage" disabled="@(!HasNext)">다음</button>
</div>
@code {
private List<ErrorLog> pagedLogs = new();
private int currentPage = 1;
private int pageSize = 10;
private int totalCount = 0;
private int totalPages => (int)Math.Ceiling((double)totalCount / pageSize);
private bool HasPrev => currentPage > 1;
private bool HasNext => currentPage < totalPages;
protected override async Task OnInitializedAsync()
{
await LoadLogs();
}
private async Task LoadLogs()
{
totalCount = await DbContext.ErrorLogs.CountAsync();
pagedLogs = await DbContext.ErrorLogs
.OrderByDescending(e => e.CreatedAt)
.Skip((currentPage - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
}
private async Task PrevPage()
{
if (HasPrev)
{
currentPage--;
await LoadLogs();
}
}
private async Task NextPage()
{
if (HasNext)
{
currentPage++;
await LoadLogs();
}
}
}
결론
이제 Azunt.Web
프로젝트에서 MVC와 Blazor Server 모두에서 발생한 예외를 ErrorLogs
테이블에 기록하고, 관리자 페이지에서 QuickGrid
와 수동 페이저 UI를 통해 페이징된 로그 리스트를 실시간으로 조회할 수 있습니다. 이 구조는 유지보수와 장애 대응에 실질적인 도움을 줄 수 있습니다.
추천 자료: ASP.NET Core 인증 및 권한 부여
추천 자료: .NET Blazor에 대해 알아보시겠어요? .NET Blazor 알아보기를 확인해보세요!