C# Hot Reload — 런타임 코드 교체
Hot Reload는 실행 중인 .NET 앱에 코드 변경을 적용하는 기능입니다. EnC(Edit and Continue)를 기반으로 .NET 6에서 표준화되었으며, ASP.NET Core, MAUI, Unity(실험적), Blazor에서 모두 지원됩니다. 재시작 없이 UI 렌더링, 비즈니스 로직을 즉시 확인할 수 있어 개발 피드백 루프를 크게 단축합니다.
1. dotnet watch로 Hot Reload 실행
섹션 제목: “1. dotnet watch로 Hot Reload 실행”# Hot Reload 활성화 (기본값)dotnet watch
# 명시적 실행dotnet watch --hot-reload
# 특정 프로젝트dotnet watch --project ./src/MyApp/MyApp.csproj
# 변경 시 완전 재시작 강제 (Hot Reload 비활성화)dotnet watch --no-hot-reload
# 환경 변수로 제어DOTNET_WATCH_RESTART_ON_RUDE_EDIT=true dotnet watch2. 지원되는 변경 유형
섹션 제목: “2. 지원되는 변경 유형”// ✅ 지원: 메서드 본문 변경public string GetGreeting() => "Hello, World!"; // → "안녕하세요!" 로 변경 가능
// ✅ 지원: 새 메서드 추가public void NewMethod() { }
// ✅ 지원: 람다식 변경app.MapGet("/", () => "v2"); // v1 → v2
// ⚠️ Rude Edit (재시작 필요): 클래스 계층 변경class Animal { }class Dog : Animal { } // Dog에 새 기반 클래스 추가 → 재시작
// ⚠️ Rude Edit: 인터페이스 추가/제거// ⚠️ Rude Edit: 제네릭 파라미터 변경// ⚠️ Rude Edit: 구조체 레이아웃 변경3. MetadataUpdateHandler — 코드 교체 후 훅
섹션 제목: “3. MetadataUpdateHandler — 코드 교체 후 훅”using System.Reflection.Metadata;
// Hot Reload가 타입을 업데이트한 직후 호출됨[assembly: MetadataUpdateHandler(typeof(MyUpdateHandler))]
internal static class MyUpdateHandler{ // 업데이트된 타입 목록 수신 public static void UpdateApplication(Type[]? updatedTypes) { if (updatedTypes is null) return;
foreach (var type in updatedTypes) { Console.WriteLine($"[HotReload] {type.FullName} 업데이트됨");
// 캐시 무효화 예시 if (typeof(IComponent).IsAssignableFrom(type)) ComponentCache.Invalidate(type); } }
// 업데이트 전 정리 작업 public static void ClearCache(Type[]? updatedTypes) { // 예: DI 컨테이너 서비스 제거 }}4. ASP.NET Core에서 Hot Reload
섹션 제목: “4. ASP.NET Core에서 Hot Reload”// Program.cs — Razor Pages/MVC는 별도 설정 불필요var builder = WebApplication.CreateBuilder(args);builder.Services.AddRazorPages();
var app = builder.Build();app.MapRazorPages();app.Run();
// dotnet watch 실행 시:// - Razor 파일(.cshtml) 변경 → 즉시 반영// - C# 서비스 메서드 변경 → Hot Reload 적용// - DI 등록 변경 → 재시작 필요5. MAUI / Blazor WASM Hot Reload
섹션 제목: “5. MAUI / Blazor WASM Hot Reload”# MAUIdotnet watch --project MyMauiApp.csproj
# Blazor WASM (브라우저 자동 새로고침)dotnet watch --project BlazorApp.csproj
# Blazor 컴포넌트 변경 지원:# - @code 블록 내 로직# - HTML 마크업# - CSS isolation (.razor.css)6. Visual Studio / Rider 연동
섹션 제목: “6. Visual Studio / Rider 연동”Visual Studio:- 디버그 모드: 변경 저장 → 자동 적용 (Alt+F10: 수동 적용)- 설정: 도구 > 옵션 > 디버깅 > .NET/C++ Hot Reload- 표시기: 편집기 하단 "Hot Reload" 상태 표시
JetBrains Rider:- Run > Apply Hot Reload Changes (Ctrl+Alt+F10)- 자동 적용: Run > Edit Configurations > Enable Hot Reload
dotnet watch:- 파일 저장 시 자동 감지- 콘솔에 "Hot reload applied" 메시지 출력7. 제한사항과 우회
섹션 제목: “7. 제한사항과 우회”// 제한: 제네릭 메서드 본문 변경 (일부 시나리오)// 우회: 비제네릭 내부 구현으로 분리public T Process<T>(T input) => (T)ProcessInternal(input!); // ProcessInternal 변경 가능
// 제한: static 생성자 변경// 우회: 초기화 로직을 일반 메서드로 분리
// 제한: 어트리뷰트 변경// 우회: 재시작 감수 또는 조건부 어트리뷰트 제거
// Rude Edit 시 자동 재시작 허용// DOTNET_WATCH_RESTART_ON_RUDE_EDIT=trueHot Reload는 메서드 본문과 Razor 마크업 변경에 가장 잘 동작합니다. MetadataUpdateHandler로 캐시 무효화 훅을 등록하면 Hot Reload와 앱 상태를 동기화할 수 있습니다. 클래스 구조 변경은 여전히 재시작이 필요하므로, DOTNET_WATCH_RESTART_ON_RUDE_EDIT=true로 자동 재시작을 허용해 두면 개발 흐름이 끊기지 않습니다.