CodeGym /행동 /C# SELF /로깅: Microsoft.Extensions.L...

로깅: Microsoft.Extensions.Logging

C# SELF
레벨 64, 레슨 0
사용 가능

1. 소개

프로그래밍에서 로깅은 단순히 "콘솔에 뭐라도 찍는 것"이 아니야. 로깅은 블랙박스이자 GPS 트래커이고 계기판이기도 해. 로그가 없으면 큰 프로그램은 미스테리한 블랙박스가 돼: "서비스가 왜 멈췄지?", "사용자가 메일을 못 받았는데 왜?", "이 모듈을 지난 3개월 동안 누가 실행이라도 했나?" — 이런 질문들에 답하려면 로그가 저장되고 접근 가능해야 해.

현실에서 로깅이 왜 필요할까?

버그 탐지와 진단
프로그램이 죽었다면 — 로그가 어디서, 왜 그런지 알려줘. 죽지는 않았지만 이상하게 동작한다면 — 로그가 그 상황에 이르게 한 단계들을 보여줄 거야.

상태 모니터링
로그로 현재 시스템이 동작 중인지, 서버에 요청이 많은지, 오류가 발생하는지, 누가 무엇을 하고 있는지 알 수 있어.

보안
권한 없는 접근 시도, 의심스러운 활동, 인증 오류 등을 로깅해서 추적할 수 있어.

감사(audit)
누가, 무엇을, 언제 했는지. 악성 관리자(예: 해고된)가 데이터를 지웠다면 로그로 복구하거나 최소한 어떤 행동을 했는지 파악할 수 있어.

개발 및 운영 지원
로그는 개발자뿐만 아니라 테스터, 운영자, 시스템 관리자에게도 유용해. 반년 뒤에 너 자신이 이렇게 말할거야: '로그 추가하길 잘했어!'

Console.WriteLine부터 프로덕션 로깅까지

초보자의 첫 반응: "그냥 Console.WriteLine이면 안 돼?" 작은 학습용 프로그램에선 그걸로 충분할 수 있어. 하지만 앱이 서버에서 돌아가고, 동시에 여러 쓰레드/요청을 처리하거나 수십, 수백 명이 쓰면 콘솔만으론 부족해. 필요한 것들:

  • 중요한 정보와 디버깅 정보를 분리
  • 로그를 콘솔뿐 아니라 파일, DB, 중앙 집약형 시스템으로 보낼 수 있어야 함
  • 로그 상세도(level)를 조절(최소 — 오류만, 최대 — 전부)
  • 자동으로 날짜/시간, 부가 정보 추가
  • 유연한 설정
  • 무엇보다도 — 로그 전송 대상을 바꾸려 코드에서 매번 수정하지 않기

바로 여기서 '진짜' 로거들의 시대가 시작돼.

2. .NET에서의 현대 로깅 기초

.NET 생태계에는 강력하고 유연한 표준 로깅 프레임워크가 있어 — Microsoft.Extensions.Logging. ASP.NET Core와 함께 등장한 "뉴 웨이브" .NET 라이브러리의 일부지만, 이제는 서버, 데스크탑, 모바일 어디서나 쓰여.

이 프레임워크의 장점은?

  • 추상화 — 특정 구현에 묶이지 않아(로거는 파일, 콘솔, 클라우드에 쓰거나 동시에 여러 곳에 보낼 수 있음).
  • 로그 레벨 지원(Trace, Debug, Information, Warning, Error, Critical).
  • DI 컨테이너에 통합되어 모든 최신 .NET 앱에서 사용하기 쉬움.
  • 구조화 로깅, 고급 포매터, 다양한 통합을 지원하는 풍부한 확장 생태계.

주요 개념과 클래스

이제 Microsoft.Extensions.Logging로 작업할 때 필요한 핵심 객체들을 살펴보자:

클래스/인터페이스 용도
ILogger<T>
클래스 타입으로 지정된 로깅 인터페이스
ILogger
제네릭이 아닌 일반 로거 인터페이스
ILoggerFactory
로거 인스턴스를 생성하는 팩토리
ILoggingBuilder
애플리케이션에서 로깅을 설정할 때 사용
LogLevel
로그 레벨 열거형 (Trace, Debug, Information, ...)

로그 레벨

메시지를 중요도별로 나누면 "노이즈"를 필터링하고 필요한 걸 찾기 쉬워져:

레벨 (LogLevel) 어떤 용도로?
Trace
최대한 자세한 디버그 정보, 잡음, 타이밍 데이터
Debug
주요 디버깅 정보
Information
정상 동작을 위한 주요 이벤트 메시지
Warning
잠재적 문제에 대한 경고, 시스템은 계속 동작
Error
주의가 필요한 오류, 하지만 애플리케이션은 살아있음
Critical
시스템 전체에 위협이 되는 치명적 실패

3. 실습: 애플리케이션에 로깅 추가하기

추상적인 코드만 쓰지 말고, 데모 앱을 계속 키워보자. 이미 간단한 Calculator 클래스가 있고 강의를 따라가면서 이걸 확장한다고 하자.

예시: 기본 Calculator

public class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }
    // 나머지 메서드...
}

이제 여기에 로깅을 넣어보자. 외부(예: Dependency Injection, DI)에서 주입받을 ILogger<Calculator> 인터페이스가 필요해.

using Microsoft.Extensions.Logging;

public class Calculator
{
    private readonly ILogger<Calculator> _logger;

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

    public int Add(int a, int b)
    {
        int result = a + b;
        _logger.LogInformation("덧셈 수행: {A} + {B} = {Result}", a, b, result);
        return result;
    }
}

흥미로운 사실:
문자열을 이어 붙이는 대신 로거는 템플릿과 명명된 파라미터({A}, {B}, {Result})를 지원해. 덕분에 로그를 구조화해서 자동 처리나 검색에 유리하게 만들 수 있어.

4. 콘솔 애플리케이션에서 로거 생성 및 설정하기

1. NuGet 패키지 추가

프로젝트에는 다음이 필요해:

  • Microsoft.Extensions.Logging
  • Microsoft.Extensions.Logging.Console (콘솔에 쓰려면)
  • (선택) 필요한 경우 다른 provider들

2. 로거 설정

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

// DI 컨테이너 생성
var serviceProvider = new ServiceCollection()
    .AddLogging(builder => {
        builder.AddConsole(); // 콘솔 출력
        builder.SetMinimumLevel(LogLevel.Debug); // 최소 로그 레벨
    })
    .BuildServiceProvider();

// 필요한 타입의 로거 인스턴스 획득
var logger = serviceProvider.GetRequiredService<ILogger<Calculator>>();

var calculator = new Calculator(logger);
calculator.Add(5, 3); // 로그에 메시지가 찍힐 거야

초보자들이 흔히 하는 실수
"왜 콘솔에 로그가 안 보일까?" — 필요한 provider(.AddConsole())를 추가했는지, 최소 로그 레벨(SetMinimumLevel)이 올바른지 확인해. 레벨이 더 높게 설정되면 메시지가 필터링될 수 있어!

5. 유용한 팁

오류와 비정상 상황 로깅하기

예를 들어 0으로 나누는 상황을 로깅하고 싶다면, 다음처럼 메서드를 추가해보자:

public int Divide(int a, int b)
{
    if (b == 0)
    {
        _logger.LogError("0으로 나누기 시도! a={A}", a);
        throw new DivideByZeroException();
    }
    int result = a / b;
    _logger.LogInformation("나눗셈 수행: {A} / {B} = {Result}", a, b, result);
    return result;
}

왜 이게 필요할까?
실제로 뭔가 잘못됐을 때 Error 레벨 로그는 보통 관리자의 주목을 끌어: 알림/경고로 자동 전송되거나 모니터링에서 강조되어 문제 대응에 사용돼.

카테고리와 메타데이터 사용하기 (scopes)

.NET 로거는 scopes라는 추가 메타데이터를 지원해 — 특정 코드 블록 동안 모든 로그에 자동으로 붙는 정보야. 예를 들어 웹 요청이나 사용자 세션을 처리할 때 식별자를 scope에 넣을 수 있어.

using (_logger.BeginScope("UserId: {UserId}", 42))
{
    _logger.LogInformation("사용자 데이터 처리 시작");
    // ...
}

블록 안의 모든 메시지에 UserId: 42라는 태그가 추가돼서 나중에 사용자별로 로그를 찾기 편해.

예시: 로그 레벨 동작

_logger.LogTrace("이건 Trace — 거의 안 보일 거야");
_logger.LogDebug("이건 Debug — 개발자용");
_logger.LogInformation("이건 Information — 정상 동작 이벤트");
_logger.LogWarning("이건 Warning — 잠재적 문제");
_logger.LogError("이건 Error — 주의가 필요한 에러");
_logger.LogCritical("이건 Critical — 시스템이 불타고 있어, 소방수 필요!");

만약 SetMinimumLevel(LogLevel.Information)로 설정했다면, Information, Warning, Error, Critical 레벨만 보일 거야.

팁:
개발 단계에서는 TraceDebug를 켜서 자세히 진단하고, 운영 환경에서는 보통 Information 이상만 켜서 로그 용량이 불필요하게 커지는 걸 막아.

비주얼 다이어그램: 현대 로깅 아키텍처

graph TD
A[애플리케이션 코드] --ILogger<YourClass>--> B[Microsoft.Extensions.Logging]
B --> C1[Console Provider]
B --> C2[File Provider]
B --> C3[Cloud/Database Provider]
C1 -.-> D1[콘솔 로그]
C2 -.-> D2[파일 로그]
C3 -.-> D3[모니터링 시스템에 로그]

subgraph Providers
    C1
    C2
    C3
end

6. 추가 기능과 확장

구조화 로깅:
파라미터 값들을 문자열로만 저장하지 않고 키-값 형태로 유지하면(예: Seq, ELK/ElasticSearch, Application Insights) 해당 파라미터로 검색/집계가 가능해.

로깅 제공자들:
파일, Windows EventLog, Azure 등 수십 가지 provider를 추가할 수 있어.

appsettings.json을 통한 로깅 설정:
ASP.NET Core에서는 설정 파일로 로깅을 유연하게 구성할 수 있어서 앱 재컴파일 없이 레벨을 바꿀 수 있어.

예: 설정 파일에서 최소 로그 레벨 설정하기 (appsettings.json):

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "MyApp.Calculator": "Debug",
      "Microsoft": "Warning"
    }
  }
}

7. Microsoft.Extensions.Logging 사용 시 흔한 실수

실수 #1: 잘못된 로그 레벨 선택.
LogInformation을 오류 상황에 쓰고 LogErrorLogCritical를 안 쓰면 프로덕션에서 문제 찾기 힘들어.

실수 #2: 구조화 로깅 무시.
문자열 연결으로 로그를 찍으면 ({Parameter} 같은 플레이스홀더 대신) 파라미터 기반 검색 등의 이점을 잃어.

실수 #3: 로그 레벨 설정을 잘못함.
최소 레벨이 너무 높게 설정되면(예: Warning로) 필요한 디버그 메시지가 필터링돼.

실수 #4: 로그가 너무 많거나 너무 적음.
운영 환경에서 Trace를 켜 두면 노이즈가 심해지고, 로그가 전혀 없으면 문제 진단이 불가능해.

2
과제
C# SELF, 레벨 64, 레슨 0
잠금
'Microsoft.Extensions.Logging'를 사용한 기본 로깅
'Microsoft.Extensions.Logging'를 사용한 기본 로깅
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION