IOptions를 사용한 강력한 형식의 옵션
IOptions , IOptionsSnapshot , IOptionsMonitor 를 사용해 구성 섹션을 POCO 클래스에 바인딩합니다.
IOptions를 사용한 강력한 형식의 옵션은(는) CoddyKit의 무료 C# Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C# Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
강력한 형식의 옵션을 사용하는 이유
IConfiguration["Key"]로 구성을 읽으면 형식이 지정되지 않은 문자열을 얻게 됩니다. Options 패턴은 구성 섹션을 C# 클래스에 매핑하여 컴파일 시점의 안정성, IntelliSense, 유효성 검사 지원을 제공합니다.
옵션 클래스 정의
속성 이름이 JSON 키와 일치하는 일반 POCO 클래스를 만듭니다. 관례에 따라 구성 섹션을 식별할 수 있도록 정적 SectionName 상수를 추가합니다.
// Configuration class
public class JwtOptions
{
public const string SectionName = "Jwt";
public string SecretKey { get; set; } = string.Empty;
public string Issuer { get; set; } = string.Empty;
public string Audience { get; set; } = string.Empty;
public int ExpiryMinutes { get; set; } = 60;
}
// appsettings.json:
{
"Jwt": {
"SecretKey": "my-very-secret-key",
"Issuer": "https://myapp.com",
"Audience": "https://myapp.com/api",
"ExpiryMinutes": 120
}
}옵션 등록
Configure<T>를 호출하여 구성 섹션을 옵션 클래스에 바인딩합니다. 그러면 DI에 IOptions<T>, IOptionsSnapshot<T>, IOptionsMonitor<T>가 등록됩니다.
// Registration
builder.Services.Configure<JwtOptions>(
builder.Configuration.GetSection(JwtOptions.SectionName));
// Alternative shorthand:
builder.Services
.AddOptions<JwtOptions>()
.BindConfiguration(JwtOptions.SectionName);
// Consuming via IOptions<T>:
public class TokenService
{
private readonly JwtOptions _opts;
public TokenService(IOptions<JwtOptions> opts)
=> _opts = opts.Value;
public string CreateToken()
=> $"Issuer={_opts.Issuer}, Exp={_opts.ExpiryMinutes}m";
}IOptions와 IOptionsSnapshot 및 IOptionsMonitor 비교
수명과 다시 로드 동작이 서로 다른 세 가지 유형이 있습니다. 사용 사례에 맞는 유형을 선택해야 합니다.
// IOptions<T> — Singleton, reads config ONCE at startup
public class ApiClient(IOptions<ApiOptions> opts)
{
private readonly ApiOptions _opts = opts.Value; // never changes
}
// IOptionsSnapshot<T> — Scoped, reloads per request
public class ReportService(IOptionsSnapshot<ReportOptions> opts)
{
private readonly ReportOptions _opts = opts.Value; // fresh per request
}
// IOptionsMonitor<T> — Singleton, live updates + change notifications
public class FeatureService(IOptionsMonitor<FeatureFlags> monitor)
{
public bool IsEnabled(string feature)
=> monitor.CurrentValue.EnabledFeatures.Contains(feature);
}특성을 사용한 옵션 유효성 검사
옵션 속성에 System.ComponentModel.DataAnnotations 특성을 지정하고 ValidateDataAnnotations()를 호출하면 구성이 잘못된 경우 시작 시 즉시 실패합니다.
using System.ComponentModel.DataAnnotations;
public class SmtpOptions
{
[Required]
public string Host { get; set; } = string.Empty;
[Range(1, 65535)]
public int Port { get; set; } = 587;
[Required, EmailAddress]
public string FromAddress { get; set; } = string.Empty;
}
// Register with validation:
builder.Services
.AddOptions<SmtpOptions>()
.BindConfiguration("Smtp")
.ValidateDataAnnotations()
.ValidateOnStart(); // fail at startup, not first useIValidateOptions를 사용한 사용자 지정 유효성 검사
속성 간의 복잡한 규칙을 적용하려면 IValidateOptions<T>를 구현하여 프로그램에서 전체 유효성 검사 논리를 작성합니다.
public class JwtOptionsValidator : IValidateOptions<JwtOptions>
{
public ValidateOptionsResult Validate(string? name, JwtOptions opts)
{
var errors = new List<string>();
if (string.IsNullOrWhiteSpace(opts.SecretKey))
errors.Add("SecretKey must not be empty");
if (opts.SecretKey.Length < 32)
errors.Add("SecretKey must be at least 32 characters");
if (opts.ExpiryMinutes <= 0)
errors.Add("ExpiryMinutes must be positive");
return errors.Any()
? ValidateOptionsResult.Fail(errors)
: ValidateOptionsResult.Success;
}
}
builder.Services.AddSingleton<IValidateOptions<JwtOptions>, JwtOptionsValidator>();사후 구성
PostConfigure는 모든 Configure 호출이 끝난 후 실행되며 값을 재정의하거나 파생할 수 있습니다. 계산된 속성이나 환경별 조정에 유용합니다.
builder.Services.Configure<CacheOptions>(
builder.Configuration.GetSection("Cache"));
// Override in test environment:
builder.Services.PostConfigure<CacheOptions>(opts =>
{
if (builder.Environment.IsEnvironment("Testing"))
{
opts.AbsoluteExpirationMinutes = 1; // very short in tests
opts.UseDistributedCache = false; // use in-memory cache
}
});
// PostConfigure always runs LAST, even after AddOptions validators이름이 지정된 옵션
동일한 옵션 형식의 인스턴스가 여러 개 필요할 때(예: SMTP 서버 두 대) 이름이 지정된 옵션을 사용하여 서로 구분합니다.
// Register named options:
builder.Services.Configure<SmtpOptions>("Primary",
builder.Configuration.GetSection("Smtp:Primary"));
builder.Services.Configure<SmtpOptions>("Backup",
builder.Configuration.GetSection("Smtp:Backup"));
// Consume with IOptionsMonitor (supports named options):
public class EmailSender
{
private readonly SmtpOptions _primary;
private readonly SmtpOptions _backup;
public EmailSender(IOptionsMonitor<SmtpOptions> monitor)
{
_primary = monitor.Get("Primary");
_backup = monitor.Get("Backup");
}
}BindConfiguration 간단 표기법
AddOptions().BindConfiguration() 체인은 등록, 바인딩, 유효성 검사, 즉시 실패 처리를 하나의 식으로 수행하는 현대적인 유창한 방식입니다.
// Full registration chain:
builder.Services
.AddOptions<DatabaseOptions>()
.BindConfiguration("Database") // bind section
.ValidateDataAnnotations() // attribute validation
.Validate(opts => // custom rule
opts.MaxPoolSize >= opts.MinPoolSize,
"MaxPoolSize must be >= MinPoolSize")
.ValidateOnStart(); // fail at startup
// Shorthand for simple cases:
builder.Services.AddOptions<AppOptions>()
.BindConfiguration(AppOptions.SectionName)
.ValidateOnStart();실전: 기능 플래그 옵션
다시 로드 기능을 지원하는 완전한 기능 플래그 옵션 설정입니다. 재배포하지 않고도 appsettings에서 토글을 변경할 수 있습니다.
public class FeatureFlags
{
public bool EnableNewCheckout { get; set; }
public bool EnableAISearch { get; set; }
public bool EnableBetaDashboard { get; set; }
}
// appsettings.json:
// { "FeatureFlags": { "EnableNewCheckout": true, ... } }
builder.Services
.AddOptions<FeatureFlags>()
.BindConfiguration("FeatureFlags")
.ValidateOnStart();
// In a controller or service:
public class CheckoutController : ControllerBase
{
private readonly FeatureFlags _flags;
public CheckoutController(IOptionsMonitor<FeatureFlags> m)
=> _flags = m.CurrentValue;
[HttpGet("/checkout")]
public IActionResult Index() =>
_flags.EnableNewCheckout
? Ok("new checkout")
: Ok("legacy checkout");
}빠른 확인
실시간 구성 변경 사항을 반영해야 하는 싱글턴 서비스에서는 어떤 IOptions 변형을 사용해야 합니까?
복습: IOptions를 사용한 강력한 형식의 옵션
핵심 내용:
- Options 패턴은
Configure<T>또는AddOptions<T>().BindConfiguration()을 통해 구성 섹션을 POCO에 바인딩합니다 IOptions<T>: 싱글턴이며 시작할 때 한 번 읽습니다IOptionsSnapshot<T>: 범위 지정 수명이며 요청마다 다시 로드합니다. 싱글턴에 주입하면 안 됩니다IOptionsMonitor<T>: 싱글턴에서 안전하게 사용할 수 있으며 실시간CurrentValue와OnChange를 제공합니다- DataAnnotations와
ValidateDataAnnotations(),ValidateOnStart()를 사용해 유효성을 검사합니다 - 동일한 형식의 인스턴스가 여러 개이면 이름이 지정된 옵션을 사용합니다
자주 묻는 질문
“IOptions를 사용한 강력한 형식의 옵션” 강의는 무료인가요?
네 — “IOptions를 사용한 강력한 형식의 옵션” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C# Academy 강의 전체를 잠금 해제할 수 있습니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“IOptions를 사용한 강력한 형식의 옵션”에서 뭘 배우나요?
IOptions , IOptionsSnapshot , IOptionsMonitor 를 사용해 구성 섹션을 POCO 클래스에 바인딩합니다. 브라우저에서 직접 실행하는 실습 코드로 C# Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
C# Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 C# Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.
“IOptions를 사용한 강력한 형식의 옵션” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 C# Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 C# Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 구성 소스와 공급자
- IOptions를 사용한 강력한 형식의 옵션
- 옵션 유효성 검사와 명명된 옵션
- 보안 정보 관리