NRT 활성화와 이해
nullable 컨텍스트를 활성화하고 nullable 및 non-nullable 참조 형식을 이해하며 컴파일러 경고를 읽습니다.
NRT 활성화와 이해은(는) CoddyKit의 무료 C# Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C# Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
10억 달러짜리 실수
null을 발명한 Tony Hoare는 이를 자신의 '10억 달러짜리 실수'라고 불렀습니다. C#에서는 기본적으로 모든 참조 형식이 null일 수 있으므로 NullReferenceException이 가장 흔한 런타임 충돌 원인이 됩니다. Nullable Reference Types(NRT)는 이 문제를 컴파일러 수준에서 해결합니다.
Nullable 컨텍스트 활성화
프로젝트 파일에서 전역으로 NRT를 활성화하거나 지시문을 사용하여 파일별로 활성화할 수 있습니다. 활성화하면 컴파일러는 기본적으로 참조 형식을 null을 허용하지 않는 형식으로 취급합니다.
<!-- In .csproj — enable for the whole project -->
<PropertyGroup>
<Nullable>enable</Nullable>
</PropertyGroup>
// Or per-file:
#nullable enable
// ... code with NRT warnings
#nullable disable
// ... code without NRT warningsnull 비허용 참조 형식과 null 허용 참조 형식
NRT가 활성화되면 string은 절대 null이 아님을 의미하고, string?은 null일 수 있음을 의미합니다. null을 null 비허용 형식에 할당하거나 확인 없이 null 허용 값을 역참조하면 컴파일러가 경고합니다.
#nullable enable
string nonNull = "Hello"; // OK
string? maybeNull = null; // OK — explicitly nullable
nonNull = null; // WARNING: CS8600
Console.WriteLine(maybeNull.Length); // WARNING: CS8602 — may be null
// Fix:
if (maybeNull is not null)
Console.WriteLine(maybeNull.Length); // safe흐름 분석
컴파일러는 흐름 분석을 수행합니다. 조건문과 분기를 따라 null 상태를 추적하고, 값이 null이 아님을 증명할 수 있으면 경고를 억제합니다.
string? name = GetName();
// After null check, name is treated as non-null:
if (name is not null)
Console.WriteLine(name.Length); // no warning
// Same with early return:
if (name is null) return;
Console.WriteLine(name.Length); // no warning — null was returned
// Pattern matching:
if (name is string s)
Console.WriteLine(s.ToUpper()); // no warningNullable 경고: CS8600–CS8629
이해해야 할 주요 NRT 경고는 다음과 같습니다. CS8600(null을 null 비허용 형식에 할당), CS8602(null일 수 있는 값의 역참조), CS8603(null 비허용 형식에 null 반환), CS8618(초기화되지 않은 null 비허용 필드).
#nullable enable
public class Order
{
public string CustomerName { get; set; } // CS8618: not initialized
public string? TrackingNumber { get; set; } // OK — nullable
public Order(string name)
{
CustomerName = name; // now initialized — CS8618 gone
}
}
string? s = GetValue();
Console.WriteLine(s.Length); // CS8602: s might be nullnull 비허용 필드 초기화하기
생성자에서 null 비허용 필드나 속성을 설정하지 않으면 CS8618이 발생합니다. 해결 방법은 선언부에서 초기화하거나, 생성자를 통해 해당 값을 필수로 받거나, DI/ORM 패턴에서 null 용서 연산자를 사용하는 것입니다.
// Option 1: Initialize in declaration
public string Name { get; set; } = "";
// Option 2: Require via constructor
public class Product
{
public string Name { get; }
public Product(string name) => Name = name;
}
// Option 3: null-forgiving for ORM entities
public string Name { get; set; } = null!;
// null! tells compiler "trust me, this will be set by EF Core"제네릭 형식의 Nullable
제네릭 형식 매개 변수에 null 비허용 제약 조건을 지정할 수 있습니다. where T : notnull 제약 조건은 T가 절대 null이 될 수 없도록 보장합니다.
// Without constraint: T could be nullable
public T? Find<T>(int id) { ... }
// With notnull: T must be a non-nullable type
public T FindRequired<T>(int id) where T : notnull
{
var result = InternalFind<T>(id);
return result ?? throw new KeyNotFoundException();
}
// T? is meaningful only when T is known to be non-nullable
public T? FindOrDefault<T>(int id) where T : class { ... }인터페이스와 재정의에서의 Nullable
인터페이스를 구현하거나 메서드를 재정의할 때는 null 허용성 주석이 일치해야 합니다. 컴파일러는 구현이 인터페이스 선언보다 null을 덜 제한하지 않는지 확인합니다.
public interface IRepository<T>
{
T? FindById(int id); // may return null
T GetOrThrow(int id); // never null
}
// Implementation:
public class ProductRepo : IRepository<Product>
{
public Product? FindById(int id) => _db.Find(id);
public Product GetOrThrow(int id) =>
_db.Find(id) ?? throw new KeyNotFoundException();
}Nullable 값 형식과 Nullable 참조 형식
int?(Nullable<int> — C# 8 이전부터 존재한 값 형식 래퍼)와 string?(NRT 주석 — 컴파일 시에만 적용되며 런타임 오버헤드가 없음)를 혼동하지 마십시오.
// Nullable value type (runtime Nullable<int>)
int? age = null;
bool hasValue = age.HasValue;
int value = age.GetValueOrDefault();
// Nullable reference type (compile-time annotation only)
string? name = null;
// string? has NO runtime wrapper — it's just a compile-time hint
// null check is still needed at runtime
if (name is not null)
Console.WriteLine(name.ToUpper());!를 사용하여 경고 억제하기
null 용서 연산자(!)는 컴파일러보다 개발자가 상황을 더 잘 알고 있을 때 특정 Nullable 경고를 억제합니다. 신중하게 사용하고 안전한 이유를 문서화하십시오.
// Use ! when you know the value cannot be null
var user = _db.Users.FirstOrDefault(u => u.Email == email);
var name = user!.Name; // user is guaranteed by business logic
// EF Core navigation properties set by the framework:
public class Order
{
public Customer Customer { get; set; } = null!; // set by EF Core
}실전: Nullable API 응답
JSON 응답에 필드가 포함될 수도 있고 포함되지 않을 수도 있는 API 래퍼에서는 null 허용성 주석을 사용하여 의도를 명확하게 전달할 수 있습니다.
#nullable enable
public class WeatherResponse
{
public string City { get; set; } = ""; // always present
public double Temperature { get; set; } // always present
public string? Description { get; set; } // optional field
public string? AlertMessage { get; set; } // only when there's an alert
}
// Consumer:
var weather = await api.GetWeatherAsync("London");
Console.WriteLine(weather.City); // safe
Console.WriteLine(weather.Description?.ToUpper() ?? "N/A"); // safe null-handling빠른 확인
일반 참조 형식(string)과 비교할 때 Nullable Reference Types(string?)의 런타임 오버헤드는 얼마입니까?
복습: NRT 활성화 및 이해
핵심 요점:
- .csproj에서
<Nullable>enable</Nullable>을 사용하여 전역으로 활성화 string= 절대 null이 아님,string?= null일 수 있음- 흐름 분석은 분기와 반환을 따라 null 상태를 추적
- NRT 주석은 컴파일 시에만 적용되므로 런타임 오버헤드가 없음
- CS8618: 생성자에서 null 비허용 필드를 초기화하거나 ORM에는
= null!사용 - !는 신중하게 사용하고 null 용서 연산자가 안전한 이유를 문서화
자주 묻는 질문
“NRT 활성화와 이해” 강의는 무료인가요?
네 — “NRT 활성화와 이해” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C# Academy 강의 전체를 잠금 해제할 수 있습니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“NRT 활성화와 이해”에서 뭘 배우나요?
nullable 컨텍스트를 활성화하고 nullable 및 non-nullable 참조 형식을 이해하며 컴파일러 경고를 읽습니다. 브라우저에서 직접 실행하는 실습 코드로 C# Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
C# Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 C# Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“NRT 활성화와 이해” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 C# Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 C# Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.