코드베이스를 NRT로 마이그레이션하기
단계적 마이그레이션 전략을 적용합니다. 경고를 활성화하고 API에 주석을 추가하며 문제를 수정하고 오탐을 방지합니다.
코드베이스를 NRT로 마이그레이션하기은(는) CoddyKit의 무료 C# Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C# Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
마이그레이션의 과제
기존 코드 기반에서 NRT를 활성화하면 일반적으로 수백 개의 경고가 발생합니다. 한 번에 모두 전환하는 방식은 위험합니다. 대신 단계적 마이그레이션을 사용하십시오. 경고를 점진적으로 활성화하고, 파일별로 수정하며, 추진력을 잃지 않아야 합니다.
1단계: 경고만 활성화
<Nullable>warnings</Nullable>를 enable 대신 사용하여 시작하십시오. 이렇게 하면 주석이 없는 코드를 오류로 처리하지 않고 경고만 활성화할 수 있으므로 안전한 출발점이 됩니다.
<!-- Phase 1: warnings only, no breaking change -->
<PropertyGroup>
<Nullable>warnings</Nullable>
</PropertyGroup>
<!-- Phase 2: full enable per file as you migrate -->
<!-- Phase 3: switch to enable globally when done -->2단계: 파일별로 활성화
각 파일에서 작업할 때 파일 맨 위에 #nullable enable을 추가하십시오. 이렇게 하면 현재 편집 중인 파일로 변경 범위를 제한할 수 있어 검토하기가 쉬워집니다.
#nullable enable
// Now this file has full NRT analysis
public class OrderService
{
private readonly IOrderRepository _repo;
// Compiler now warns about uninitialized non-nullable fields,
// unsafe dereferences, and assignment to non-nullable
public OrderService(IOrderRepository repo) => _repo = repo;
}
// Other files without #nullable enable are still unchecked경고 분류하기
경고는 두 가지 범주로 나뉩니다. 억제해도 안전한 경고(ORM 엔터티, DI로 주입되는 필드)와 실제 버그(실제로 null인 값의 역참조)입니다. 무엇이든 억제하기 전에 이 둘을 구분하십시오.
// Category 1: safe to suppress with null!
// EF Core navigation properties — set by EF, never null in practice
public class Order
{
public Customer Customer { get; set; } = null!;
}
// Category 2: real bug — must fix
public string GetFullName()
{
return FirstName + " " + LastName; // LastName was string? -- BUG!
}생성자 경고 CS8618 수정
CS8618은 null이 허용되지 않는 속성이 생성자에서 설정되지 않을 때 발생합니다. 가장 권장되는 해결 방법은 생성자에서 해당 값을 필수로 지정하는 것입니다. = null!은 프레임워크가 설정하는 값에만 사용하십시오.
// BEFORE (CS8618)
public class Product
{
public string Name { get; set; } // warning
public Category Category { get; set; } // warning
}
// AFTER — constructor required:
public class Product
{
public string Name { get; set; }
public Category Category { get; set; }
public Product(string name, Category category)
{
Name = name;
Category = category;
}
}레거시 API 처리
타사 또는 레거시 API에는 주석이 추가되지 않았을 수 있습니다. 이러한 API의 반환 형식은 무지 상태(oblivious)이므로 null 허용인지 null 비허용인지 알 수 없습니다. 반환 결과를 null 허용 변수에 대입하여 의도를 명시하십시오.
// Legacy API returns 'string' but might be null (oblivious type)
string? legacyResult = OldLibrary.GetValue(); // store as nullable
if (legacyResult is null) return;
// Or convert at the boundary:
string safe = OldLibrary.GetValue() ?? "";
// For third-party types, check if they have NRT annotations:
// NuGet packages often add nullable annotations in newer versions특정 경고를 억제하는 #pragma 사용
경고가 실제로는 오탐이고 = null!이 지나치게 번잡하게 느껴진다면, 특정 줄에만 적용되도록 #pragma warning disable을 사용하십시오.
// Suppress for a specific case with explanation:
#pragma warning disable CS8618 // ORM populates this via reflection
public DbSet<Product> Products { get; set; }
#pragma warning restore CS8618
// Or inline with a comment:
public DbSet<Order> Orders { get; set; } = null!; // set by EF CoreNRT 경고를 오류로 처리하기
파일의 모든 경고를 수정한 후에는 <WarningsAsErrors>Nullable</WarningsAsErrors>를 추가하거나 CI에서 적용하여 회귀를 방지하십시오. 새로운 null 관련 문제가 발생하면 빌드가 실패합니다.
<!-- After full migration: treat nullable warnings as build errors -->
<PropertyGroup>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<!-- Or selectively: -->
<!-- <WarningsAsErrors>CS8600;CS8602;CS8603</WarningsAsErrors> -->
</PropertyGroup>공개 API에 주석 달기
라이브러리를 다른 코드에서 사용할 때 NRT 주석은 공개 API 계약의 일부가 됩니다. 결과가 null일 수 있으면 T?를 반환하고, 결과가 반드시 존재하면 T를 반환하십시오.
public interface IProductService
{
// Contract: FindById MAY return null, GetById never does
Product? FindById(int id);
Product GetById(int id); // throws if not found
// Collection: never null (may be empty)
IReadOnlyList<Product> GetAll();
// String: may be empty but not null
string GetSummary(int id);
}마이그레이션 지표 및 추적
#nullable enable이 포함된 파일 수를 세거나 CI에서 dotnet build 2>&1 | grep CS86을 실행하여 진행 상황을 추적하십시오. 전체 프로젝트 마이그레이션의 목표 날짜를 정하십시오.
# Count NRT warnings in current build
dotnet build 2>&1 | grep -c 'CS860[0-9]\|CS861[0-9]\|CS862[0-9]'
# List files still missing #nullable enable
grep -rL '#nullable enable' src/ --include='*.cs'
# Track in CI: fail if warning count increases
# Set a budget: warnings <= N, where N decreases each sprint빠른 확인
null이 허용되지 않는 속성에 = null!을 대입하면 무엇을 의미합니까?
NRT로 마이그레이션 요약
핵심 요점:
- 단계적 마이그레이션을 사용하십시오: 경고 모드 → 파일별 활성화 → 전체 활성화
- 실제 버그는 수정하고, ORM/DI 패턴에는
= null!을 사용하십시오 - 값을 억제하는 대신 생성자에서 값을 필수로 지정하여 CS8618을 수정하십시오
- 레거시 API 결과를
T?변수에 대입하여 의도를 명시하십시오 - 회귀를 방지하기 위해 CI에서 null 허용 경고를 오류로 처리하십시오
- 주석이 달린 공개 API는 사용하는 쪽에 명확한 계약을 제공합니다
자주 묻는 질문
“코드베이스를 NRT로 마이그레이션하기” 강의는 무료인가요?
네 — “코드베이스를 NRT로 마이그레이션하기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C# Academy 강의 전체를 잠금 해제할 수 있습니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“코드베이스를 NRT로 마이그레이션하기”에서 뭘 배우나요?
단계적 마이그레이션 전략을 적용합니다. 경고를 활성화하고 API에 주석을 추가하며 문제를 수정하고 오탐을 방지합니다. 브라우저에서 직접 실행하는 실습 코드로 C# Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
C# Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 C# Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“코드베이스를 NRT로 마이그레이션하기” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 C# Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 C# Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- NRT 활성화와 이해
- 주석: ?, !, MaybeNull과 NotNull
- null 조건부 및 null 병합 연산자
- 코드베이스를 NRT로 마이그레이션하기