Skip to main content

Command Palette

Search for a command to run...

소스 링크로 개선된 .NET 디버깅 환경 | Patrick Smacchia

Updated
3 min read
소스 링크로 개선된 .NET 디버깅 환경 | Patrick Smacchia

Patrick Smacchia님의 Improved .NET Debugging Experience with Source Link를 번역하였습니다.


소스 링크(Source Link)는 .NET 개발자가 응용 프로그램에서 참조하는 NuGet 패키지의 소스 코드를 디버깅할 수 있도록 하는 Microsoft 기술입니다. 소스 코드에 밑줄을 그은 이유는 디버깅 시 사용자가 참조된 어셈블리 내의 IL 코드에서 디컴파일된 C# 코드만 가져오는 것이 아니기 때문입니다. 대신 개발자는 라이브러리를 빌드하는 데 사용된 원본 C# 소스 코드를 디버깅하며, 원본 주석과 서식을 사용할 수 있습니다.

소스 링크는 언어, IDE 및 소스 제어에 구애받지 않습니다. 소스 링크는 Visual Studio, VS Code 또는 Rider IDE를 통해 수행한 디버깅 세션에서 사용할 수 있습니다.

Visual Studio에서 소스 링크를 사용한 디버깅

Newtonsoft.Json 패키지는 소스 링크를 지원합니다. 즉, 아래 프로그램을 디버깅할 때 SerializeObject() 메서드의 원본 소스 코드에 들어갈 수 있습니다.

var person = new Person { FirstName = "Albert", LastName = "Einstein ", YearOfBirth = 1879 };
string json = Newtonsoft.Json.JsonConvert.SerializeObject(person);
Console.WriteLine(json);

public class Person {
   public string FirstName { get; init; }
   public string LastName { get; init; }
   public int YearOfBirth { get; init; }
}

이 작업을 수행하기 전에 Visual Studio에서 몇 가지 설정을 설정해야 합니다:

  • 활성화: 도구 > 옵션 > 디버깅 > 기호 > Nuget.org 기호 서버

  • 도구 > 옵션 > 디버깅 > 일반

    • 비활성화: 내 코드만 사용

    • 활성화: 소스 서버 지원 활용, 소스 링크 지원 사용

그런 다음 프로그램 디버깅을 시작합니다(F5). 디버깅 세션을 시작하기 전에 참조된 패키지의 심볼을 로드하는 데 몇 초 정도 걸립니다:

Source Link Load Symbol

이제 Newtonsoft의 원본 소스를 단계별로 살펴볼 수 있습니다:

Source Link Setp Into

JsonSerializer.cs 파일은 GitHub에서 다운로드하여 C:\사용자\usr\AppData\Local\SourceServer\634989e5314d385c82c8a3269e286aacd49e4527b9c315d6bd38afcf4ee504e3\Src\Newtonsoft.Json 폴더에 저장되어 있습니다.

Source Link repository type

이 시나리오에서는 압축된 패키지에 PDB 파일이 포함되지 않습니다. 디버그 시 이 위치와 커밋 해시는 소스 파일과 PDB 파일을 GitHub에서 가져오는 데 사용되며, 이 파일은 \Temp\SymbolCache 디렉터리에 로컬로 저장됩니다.

Source Link symbols loaded

자체 패키지에 소스 링크 활성화하기

자체 패키지에 소스 링크를 활성화하면 이를 사용하는 개발자의 작업이 훨씬 쉬워집니다.

최소한 .csproj 프로젝트 파일에 <PublishRepositoryUrlsproj> 태그와 소스 링크 패키지에 대한 참조를 추가해야 합니다.


<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>

    <!-- Insert the tag <repositoy .../> in the .nuspec file -->
    <PublishRepositoryUrl>true</PublishRepositoryUrl>
  </PropertyGroup>

  <ItemGroup>
    <!-- Reference this package to enable SourceLink used with the source control GitHub -->
    <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>
</Project>

GitLab 또는 Bitbucket을 사용하는 경우 대신 Microsoft.SourceLink.GitLab 또는 Microsoft.SourceLink.Bitbucket.Git 패키지를 참조할 수 있습니다.

PDB 파일 포함하기

일부 선택적 태그를 사용하면 기본 .nupkg 패키지 내부 또는 확장자가 .snupkg인 사이드 패키지에 PDB 파일을 포함할 수 있습니다. 첫 번째 옵션은 심볼이 필요하지 않은 시나리오에서도 메인 패키지의 크기가 증가하여 복원 시간이 길어지므로 권장되지 않습니다.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    ...

    <!-- Embed symbol files (*.pdb) in the .nupkg package -->
    <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>

    <!-- or embed symbol package in a symbol package (.snupkg) -->
    <IncludeSymbols>true</IncludeSymbols>
    <SymbolPackageFormat>snupkg</SymbolPackageFormat>
  </PropertyGroup>
...

NuGet.org는 자체 심볼 서버 리포지토리를 호스팅하며, 이 리포지토리는 .snupkg 심볼 사이드 패키지와 함께 작동합니다. 이 글의 첫 번째 섹션에서 도구 > 옵션 > 디버깅 > 심볼 > NuGet.org 심볼 서버를 선택했을 때 Visual Studio에 NuGet.org 심볼 서버 리포지토리에서 심볼을 가져오도록 지시했습니다.

PDB 파일에 소스 포함

마지막으로 이러한 옵션을 사용하여 PDB 파일 내에 소스 파일을 선택적으로 포함하도록 결정할 수 있습니다:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    ...

    <!-- Embed all project source files into the generated PDB -->
    <EmbedAllSources>true</EmbedAllSources>

    <!-- Embed project source files that are not tracked by the source control or imported from a source package to the generated PDB.
         Has no effect if EmbedAllSources is true. -->
    <EmbedUntrackedSources>true</EmbedUntrackedSources>
  </PropertyGroup>
...

마무리

소스 링크를 사용하면 디버깅 프로세스가 더욱 원활하고 직관적이며 통찰력 있게 진행되어 개발 주기를 단축할 수 있습니다. 소스 링크는 NuGet 에코시스템에 원활하게 통합되어 개발자가 레퍼런스의 내부를 자세히 살펴볼 수 있으므로 전례 없는 효율성으로 문제와 이슈를 해결할 수 있습니다.


More from this blog

개발, 테스트, 운영에서의 도커 활용

핵심 원칙: "한 번 빌드하고, 어디서든 실행한다 (Build once, run anywhere)" 도커의 가장 큰 장점은 환경 일관성입니다. 동일한 도커 이미지를 사용하여 개발, 테스트, 운영 환경을 구성함으로써 "제 PC에서는 됐는데..." 하는 문제를 최소화할 수 있습니다. 1. 개발 단계 (Development) 목표: 빠른 코드 변경 반영, 쉬운 디버깅, 실제 운영 환경과 유사한 환경 구성. Docker 사용 방안: Dockerf...

May 9, 20256 min read15

[EF Core] 데이터 삭제 시 소프트 삭제 적용

DB에서 데이터를 삭제하면 일반적으로 복구할 수 없습니다. 또한 관계에 따라 영구 삭제 자체가 어려울 수도 있습니다. 그래서 데이터를 영구 삭제하는 대신 IsDeleted 속성을 true로 주고 IsDeleted 속성을 필터링해서 조회하는 방법을 사용하기도 합니다. 이를 소프트 삭제라고 합니다. 그런데 EF에서 알아서 데이터 삭제 시 소프트 삭제를 하고 쿼리시 IsDeleted 속성을 체크해서 삭제한 데이터를 제외한 데이터만 쿼리하게 하는 ...

Mar 18, 20243 min read19

[EF Core] ValueConverter를 이용해서 엔터티 속성의 도메인 관리

EF Core를 사용하면서 문자열 길이 등의 특성을 일일이 지정하는 것은 번거롭습니다. ... [MaxLength(32)] public string? 제목 { get; set; } 엔터티가 한 개일 때는 상관이 없으나 제목 유형이 여러 엔터티에 사용될 경우 유형을 지정하기 번거롭습니다. 속성 유형을 도메인으로 관리하면 참 편할텐데요, ValueConverter를 이용할 수 있습니다. 그런데 이것을 인터페이스 정적 추상를 사용해서 다음처럼 ...

Mar 16, 20242 min read8

디모이 블로그

154 posts

.NET 관련 기술을 선호하고 새로운 언어를 배우는데 관심이 있습니다.