본문 바로가기
카테고리 없음

.NET CORE 백엔드 개발 (2) - 로그 시스템 만들기

by 아마도개발자 2025. 10. 3.
반응형

로그 시스템 만들기

 

백엔드 개발에서 로그(logging)는 단순한 기록이 아니라, 시스템을 운영하고 개선하는 핵심 도구이다. 로그를 통해 얻을 수 있는 효과는 다음과 같다.

1. 문제 진단 및 디버깅

운영 환경에서 발생하는 버그나 장애는 재현하기 어렵다. 이때 로그는 발생 시점의 맥락을 알려주는 단서가 된다.

  • 어떤 요청에서 오류가 발생했는지
  • 어떤 입력 값이 들어왔는지
  • 어느 지점에서 예외가 던져졌는지

이러한 기록을 통해 빠르게 원인을 파악하고 문제를 해결할 수 있다.

2. 성능 모니터링

로그는 단순히 에러 추적용으로만 쓰이지 않고 다음의 역할도 할 수 있다.

  • 요청 처리 시간
  • DB 쿼리 실행 시간
  • API 호출 빈도

이 같은 데이터를 통해 병목 구간을 찾고 성능 최적화 포인트를 식별할 수 있다.

 

3. 운영 효율성 및 간접업무 지원

서비스를 운영하다 보면 다른 부서나 팀에서 운영중인 서비스와 관련된 데이터를 요청하는 경우가 많다. 

 

  • 로그인 시도, 접근 권한 요청 기록
  • 사용자 액티비티

이런 정보를 수집, 통계처리하여 서비스를 개선하는 역할 혹은 간접업무를 지원하는 역할도 수행한다.

 


 

 

2025.09.29 - [분류 전체보기] - .NET CORE 백엔드 개발 (1) - 프로젝트 구조 만들기

 

.NET CORE 백엔드 개발 (1) - 프로젝트 구조 만들기

.NET CORE 백엔드 개발하기신입 시절 .NET CORE 2.1로 만든 백엔드 프로젝트가 있었다. 당시 백엔드 개발을 한번도 해본적이 없는 상태에서 혼자 개발을 해야 했었는데, 슬프게도 도움을 주거나 방향

maybe-developer.tistory.com

 

지금부터 이전 글에서 만든 프로젝트에 로그기능을 추가해보자.

 

로깅은 Application → Infrastructure → API 전반에 걸쳐 사용되지만, 의존성을 깨지 않기 위해 인터페이스를 Application 레이어에 두고, 구현은 Infrastructure에서 하는 것이 정석이다.

 

Application/Common/Logging/IAppLLogger.cs

namespace TodoList.Application.Common.Logging;

public interface IAppLogger<T>
{
    void LogInformation(string message, params object[] args);
    void LogWarning(string messagem, params object[] args);
    void LogError(string message, Exception ex);
}

 

이 IAppLogger인터페이스는 ILogger(내장된 로그기능)의 기능을 단순히 감싼 형태이다. 이렇게 하면 Application 레이어는 구체적인 로깅 기술(예: Serilog, NLog, Console)에 의존하지 않고, 추상화된 인터페이스만 알게 된다. 즉 로그 패키지가 교체되거나 추가되어도 Application Layer에서의 수정이 필요치 않다.

 

Infrastructure/Common/Logging/LoggerAdapter.cs

namespace TodoList.Infrastructure.Common.Logging;

using Microsoft.Extensions.Logging;
using TodoList.Application.Common.Logging;

public class LoggerAdapter<T> : IAppLogger<T>
{
    private readonly ILogger<T> _logger;

    public LoggerAdapter(ILogger<T> logger)
    {
        _logger = logger;
    }

    public void LogInformation(string message, params object[] args)
    {
        _logger.LogInformation(message, args);
    }

    public void LogWarning(string message, params object[] args)
    {
        _logger.LogWarning(message, args);
    }

    public void LogError(string message, Exception ex)
    {
        _logger.LogError(ex, message);
    }
}

 

LoggerAdapter는 애플리케이션 레이어에서 로깅 구현체(Serilog, NLog, Microsoft.Extensions.Logging 등)에 직접 의존하지 않게 해주는 어댑터(중개) 역할을 한다. (현재는 Microsoft.Extensions.Logging의 ILogger를 사용)

 

Application/Service/TodoService.cs

using TodoList.Application.Common.Logging;
using TodoList.Application.Dtos;
using TodoList.Application.Interfaces;
using TodoList.Application.Requests;
using TodoList.Domain.Entities;
using TodoList.Domain.ValueObjects;

namespace TodoList.Application.Services;

public class TodoService : ITodoService
{
    private readonly ITodoRepository _repository;
    private readonly IAppLogger<TodoService> _logger;

    public TodoService(ITodoRepository repository, IAppLogger<TodoService> logger)
    {
        _repository = repository;
        _logger = logger;
    }

    public async Task<IEnumerable<TodoDto>> GetAllAsync()
    {
        _logger.LogInformation("Fetching all todo items.");
        var todos = await _repository.GetAllAsync();
        return todos.Select(ToDto);
    }
	
    ...중략...
    

}

 

이렇게 IAppLogger인터페이스를 주입 받아 사용하면 Application 레이어에서 로깅을 활용하면서도, 구체적인 로깅 기술에 종속되지 않는 구조를 유지할 수 있다.

 

이후 program.cs에

builder.Logging.ClearProviders();
builder.Logging.AddConsole();

 

를 추가하면 기본적으로 DEBUG CONSOLE에서 로그를 확인할 수 있다. 하지만 이 정도로 끝난다면 디버깅 콘솔을 찍는 것과 큰 차이가 없고, 운영서버에서 제대로 로깅을 하는 것이 불가능하기 때문에 Serilog 패키지를 활용해 로그를 파일로 정리하는 것 까지 만들어 보자.

 


 

우선 API에 Serilog.AspNetCore패키지를 설치하고, 나머지 패키지들을 Infrastructure에 설치한다.

// Api
dotnet add package Serilog.AspNetCore

// InfraStructure
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.File

 

설치가 완료되면 Api의 Program.cs에 Serilog 설정 코드를 추가한다.

 

TodoList.API/Program.cs

using Serilog;

var builder = WebApplication.CreateBuilder(args);

// Serilog 설정
Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .WriteTo.File("logs/log.txt", rollingInterval: RollingInterval.Day)
    .CreateLogger();
builder.Host.UseSerilog();

// Swagger 및 OpenAPI 설정
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// 애플리케이션 및 인프라스트럭처 서비스 등록
builder.AddApplicationServices();
builder.AddInfrastructureServices();

builder.Services.AddOpenApi();
builder.Services.AddControllers();
var app = builder.Build();


if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.MapControllers();
app.Run();

 

이렇게 세팅을 하면 기존 logger를 대신하여 Serlog를 사용하여 로깅을 할 수 있게 된다. 로깅 설정은 내 프로젝트에 맞게 수정만 해주면 된다.

 

끝.

 

소스코드

https://github.com/FreeBono/EasyCleanArchitecture

 

GitHub - FreeBono/EasyCleanArchitecture: This project is made with a clean architecture that is easy to follow.

This project is made with a clean architecture that is easy to follow. - FreeBono/EasyCleanArchitecture

github.com

 

반응형