C# Hot Reload 내부 동작 원리와 활용
Hot Reload는 .NET 6에서 도입된 기능으로, 애플리케이션을 재시작하거나 중단점에서 멈추지 않고도 실행 중인 코드를 수정하여 변경 사항을 즉시 반영합니다. 개발 이터레이션 속도를 크게 향상시킵니다.
1. Hot Reload vs Edit and Continue
섹션 제목: “1. Hot Reload vs Edit and Continue”| 항목 | Edit and Continue | Hot Reload |
|---|---|---|
| 도입 시기 | Visual Studio 구버전 | .NET 6+ |
| 중단점 필요 | 필요 | 불필요 |
| 디버거 필요 | 필요 | 불필요 |
| CLI 지원 | X | O (dotnet watch) |
| 비디버그 모드 | X | O |
| 지원 범위 | 더 제한적 | 더 넓음 |
2. Hot Reload 활성화
섹션 제목: “2. Hot Reload 활성화”# dotnet watch — 파일 변경 감지 후 자동 Hot Reloaddotnet watch run
# Hot Reload 없이 watch (재시작만)dotnet watch run --no-hot-reload
# 명시적 적용 (파일 저장 후 콘솔에서)# [Ctrl+R] — 변경 사항 강제 적용# [Ctrl+C] — 종료<!-- launchSettings.json에서 설정 -->{ "profiles": { "MyApp": { "hotReloadEnabled": true } }}3. 내부 동작 원리
섹션 제목: “3. 내부 동작 원리”3.1 MetadataUpdateHandler
섹션 제목: “3.1 MetadataUpdateHandler”Hot Reload는 System.Reflection.Metadata.MetadataUpdater를 통해 실행 중인 어셈블리의 메타데이터와 IL을 동적으로 교체합니다.
소스 파일 변경 ↓Roslyn 증분 컴파일 (변경된 부분만) ↓Delta IL + Delta Metadata 생성 ↓MetadataUpdater.ApplyUpdate() 호출 ↓CLR이 실행 중인 메서드 교체3.2 MetadataUpdateHandler 등록
섹션 제목: “3.2 MetadataUpdateHandler 등록”프레임워크와 라이브러리가 Hot Reload에 반응하도록 핸들러를 등록합니다.
[assembly: MetadataUpdateHandler(typeof(HotReloadHandler))]
static class HotReloadHandler{ // Hot Reload 적용 전 호출 internal static void ClearCache(Type[]? updatedTypes) { }
// Hot Reload 적용 후 호출 internal static void UpdateApplication(Type[]? updatedTypes) { Console.WriteLine("Hot Reload 적용됨"); // UI 갱신, 캐시 무효화 등 foreach (var type in updatedTypes ?? Array.Empty<Type>()) { Console.WriteLine($" 변경된 타입: {type.FullName}"); } }}4. 지원되는 변경 유형
섹션 제목: “4. 지원되는 변경 유형”// ✅ 지원: 메서드 본문 수정public string GetGreeting() => "Hello!"; // → "Hi!"
// ✅ 지원: 람다 표현식 변경Action greet = () => Console.WriteLine("Hello");
// ✅ 지원: 필드 초기화식 변경private int _count = 0; // → 1
// ✅ 지원: 속성 getter/setter 본문 변경public int Value { get => _value * 2; } // → _value * 3
// ❌ 미지원: 새 멤버 추가public void NewMethod() { } // 재시작 필요
// ❌ 미지원: 인터페이스 변경interface IService { void NewMethod(); } // 재시작 필요
// ❌ 미지원: 제네릭 타입 변경class Box<T> { public T? ExtraField; } // 재시작 필요5. ASP.NET Core 통합
섹션 제목: “5. ASP.NET Core 통합”// Razor 파일 변경 즉시 반영// 미들웨어/엔드포인트 변경도 일부 지원
var builder = WebApplication.CreateBuilder(args);builder.Services.AddRazorPages();
var app = builder.Build();app.MapRazorPages();app.Run();dotnet watch로 실행 시 .cshtml, .razor 파일 변경이 자동으로 반영됩니다.
6. Blazor와 Hot Reload
섹션 제목: “6. Blazor와 Hot Reload”@* Counter.razor *@@page "/counter"
<h1>카운터: @count</h1><button @onclick="Increment">증가</button>
@code { int count = 0;
void Increment() { count++; // 이 로직을 변경하면 Hot Reload로 즉시 반영 }}Blazor WebAssembly는 브라우저 새로고침 없이 변경 사항이 반영됩니다.
7. MAUI와 Hot Reload
섹션 제목: “7. MAUI와 Hot Reload”<!-- MauiProgram.cs에서 Hot Reload 지원 확인 -->// XAML 변경도 Hot Reload 지원// MainPage.xaml 수정 → 에뮬레이터에서 즉시 반영8. 프로그래밍 방식으로 Hot Reload 감지
섹션 제목: “8. 프로그래밍 방식으로 Hot Reload 감지”// 컴포넌트가 Hot Reload에 반응해야 할 때[assembly: MetadataUpdateHandler(typeof(ComponentRegistry))]
public static class ComponentRegistry{ private static readonly List<WeakReference<IHotReloadable>> _components = new();
public static void Register(IHotReloadable component) { _components.Add(new WeakReference<IHotReloadable>(component)); }
internal static void UpdateApplication(Type[]? types) { foreach (var weakRef in _components.ToList()) { if (weakRef.TryGetTarget(out var component)) component.OnHotReload(); else _components.Remove(weakRef); } }}
public interface IHotReloadable{ void OnHotReload();}9. 개발 워크플로 최적화
섹션 제목: “9. 개발 워크플로 최적화”# 권장 개발 명령dotnet watch run --project MyApp.csproj
# 특정 파일만 감시dotnet watch run --project MyApp.csproj -- --urls=https://localhost:7000
# 변경 후 자동 브라우저 새로고침 (Blazor)dotnet watch --project MyBlazorApp.csproj9.1 Visual Studio에서 Hot Reload
섹션 제목: “9.1 Visual Studio에서 Hot Reload”- 디버그 실행 (
F5) 또는 디버그 없이 실행 (Ctrl+F5) - 코드 수정
- 저장 (
Ctrl+S) → 자동 적용 - 또는 “Hot Reload” 버튼 클릭
10. 제약 사항과 해결법
섹션 제목: “10. 제약 사항과 해결법”제약: 새 타입/멤버 추가 불가해결: 기존 메서드 수정으로 대체 → 나중에 재시작 후 정리
제약: 제네릭 변경 불가해결: 비제네릭 헬퍼 메서드 추출 후 제네릭 메서드에서 호출
제약: 인터페이스 변경 불가해결: 새 인터페이스 분리 → 재시작 후 기존 인터페이스와 통합- Hot Reload는 실행 중 IL/메타데이터를 교체하여 재시작 없이 변경 반영
dotnet watchCLI와 Visual Studio에서 기본 지원- 메서드 본문, 람다, 필드 초기화 변경은 지원
- 새 멤버/타입 추가, 인터페이스 변경은 재시작 필요
MetadataUpdateHandler로 프레임워크와 Hot Reload 통합 가능