0Pricing
C# Academy · 강의

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 warnings

null 비허용 참조 형식과 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 warning

Nullable 경고: 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 null

null 비허용 필드 초기화하기

생성자에서 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 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. NRT 활성화와 이해
  2. 주석: ?, !, MaybeNull과 NotNull
  3. null 조건부 및 null 병합 연산자
  4. 코드베이스를 NRT로 마이그레이션하기
← C# Academy(으)로 돌아가기