다음을 통해 공유


.NET 기능 관리

Microsoft.FeatureManagement
Microsoft.FeatureManagement.AspNetCore

Microsoft.FeatureManagement
Microsoft.FeatureManagement.AspNetCore
Microsoft.FeatureManagement.Telemetry.ApplicationInsights
Microsoft.FeatureManagement.Telemetry.ApplicationInsights.AspNetCore

.NET 기능 관리 라이브러리는 기능 플래그를 기반으로 애플리케이션 기능을 개발하고 공개하는 방법을 제공합니다. 새로운 기능이 개발되면 많은 애플리케이션에는 해당 기능을 사용하도록 설정해야 하는 시기와 조건 등 특별한 요구 사항이 있습니다. 이 라이브러리는 이러한 관계를 정의하는 방법을 제공하고 일반적인 .NET 코드 패턴에 통합되어 이러한 기능을 노출할 수 있도록 합니다.

기능 플래그는 .NET 및 ASP.NET Core 애플리케이션이 기능을 동적으로 켜거나 끄는 방법을 제공합니다. 개발자는 조건문과 같은 간단한 사용 사례에서 조건부 경로 추가 또는 MVC 필터와 같은 고급 시나리오까지 기능 플래그를 사용할 수 있습니다. 기능 플래그는 .NET Core 구성 시스템 위에 빌드됩니다. 모든 .NET Core 구성 공급자는 기능 플래그의 백본 역할을 할 수 있습니다.

.NET 기능 관리 라이브러리를 사용하면 다음과 같은 혜택이 있습니다.

  • 기능 관리에 대한 일반적인 규칙

  • 낮은 진입 장벽

    • IConfiguration 기반
    • JSON 파일 기능 플래그 설정 지원
  • 기능 플래그 수명 관리

    • 구성 값은 실시간으로 변경될 수 있습니다. 기능 플래그는 전체 요청에서 일관될 수 있습니다.
  • 간단한 시나리오부터 복잡한 시나리오까지 다룹니다.

    • 선언적 구성 파일을 통해 기능 켜기/끄기 전환
    • 서버 호출을 기반으로 기능 상태를 동적으로 평가합니다.
  • ASP.NET Core 및 MVC 프레임워크용 API 확장

    • 라우팅
    • 필터
    • 작업 특성

    .NET 기능 관리 라이브러리는 오픈 소스입니다. 자세한 내용을 보려면 GitHub 리포지토리를 참조하세요.

기능 플래그

기능 플래그는 이름과 기능을 활성화하는 데 사용되는 기능 필터 목록의 두 부분으로 구성됩니다.

기능 필터

기능 필터는 기능을 사용하도록 설정해야 하는 경우에 대한 시나리오를 정의합니다. 기능의 켜기 또는 끄기를 평가할 때 필터 중 하나가 해당 기능을 사용하도록 설정해야 한다고 결정할 때까지 해당 기능 필터 목록이 트래버스됩니다. 이 시점에서 기능은 사용하도록 설정된 것으로 간주되며 기능 필터를 통한 트래버스가 중지됩니다. 기능을 사용하도록 설정해야 함을 나타내는 기능 필터가 없으면 사용하지 않도록 설정된 것으로 간주됩니다.

예를 들어, Microsoft Edge 브라우저 기능 필터를 설계할 수 있습니다. 이 기능 필터는 HTTP 요청이 Microsoft Edge에서 오는 한 연결된 모든 기능을 활성화합니다.

기능 플래그 구성

.NET Core 구성 시스템은 기능 플래그의 상태를 결정하는 데 사용됩니다. 이 시스템의 기초는 IConfiguration입니다. IConfiguration에 대한 모든 공급자는 기능 플래그 라이브러리의 기능 상태 제공자로 사용될 수 있습니다. 이 시스템은 appsettings.json에서 Azure App Configuration 등에 이르는 다양한 시나리오를 지원합니다.

기능 플래그 선언

기능 관리 라이브러리는 .NET Core의 IConfiguration 시스템에 대한 공급자이므로 appsettings.json을 기능 플래그 원본으로 지원합니다. 아래에는 json 파일에서 기능 플래그를 설정하는 데 사용되는 형식의 예가 있습니다.

{
    "Logging": {
        "LogLevel": {
            "Default": "Warning"
        }
    },

    // Define feature flags in a json file
    "FeatureManagement": {
        "FeatureT": {
            "EnabledFor": [
                {
                    "Name": "AlwaysOn"
                }
            ]
        },
        "FeatureU": {
            "EnabledFor": []
        },
        "FeatureV": {
            "EnabledFor": [
                {
                    "Name": "TimeWindow",
                    "Parameters": {
                        "Start": "Wed, 01 May 2019 13:59:59 GMT",
                        "End": "Mon, 01 Jul 2019 00:00:00 GMT"
                    }
                }
            ]
        }
    }
}

json 문서의 FeatureManagement 섹션은 규칙에 따라 기능 플래그 설정을 로드하는 데 사용됩니다. 위 섹션에서는 세 가지 다른 기능을 볼 수 있습니다. 기능은 EnabledFor 속성을 사용하여 기능 필터를 정의합니다. FeatureT에 대한 기능 필터에는 AlwaysOn이 표시됩니다. 이 기능 필터는 기본 제공되어 있으며 지정하면 항상 기능이 사용하도록 설정됩니다. AlwaysOn 기능 필터에는 구성이 필요하지 않으므로 Name 속성만 있습니다. FeatureU에는 EnabledFor 속성에 필터가 없으므로 사용하도록 설정되지 않습니다. 사용하도록 설정된 이 기능에 의존하는 모든 기능은 기능 필터가 비어 있는 한 액세스할 수 없습니다. 그러나 해당 기능을 사용하도록 설정하는 기능 필터가 추가되자마자 작동을 시작할 수 있습니다. FeatureVTimeWindow라는 기능 필터를 지정합니다. 이는 구성 가능한 기능 필터의 예입니다. 이 예에서 필터에 Parameters 속성이 있음을 볼 수 있습니다. 필터를 구성하는 데 사용됩니다. 이 경우 해당 기능이 활성화되는 시작 및 종료 시간이 구성됩니다.

FeatureManagement 섹션의 자세한 스키마는 여기에서 확인할 수 있습니다.

고급: 기능 플래그 이름에는 콜론 ':'을 사용할 수 없습니다.

온/오프 선언

다음 코드 조각은 켜기/끄기 기능에 사용할 수 있는 기능을 정의하는 대체 방법을 보여 줍니다.

{
    "Logging": {
        "LogLevel": {
            "Default": "Warning"
        }
    },

    // Define feature flags in config file
    "FeatureManagement": {
        "FeatureT": true, // On feature
        "FeatureX": false // Off feature
    }
}

RequirementType

기능 플래그의 RequirementType 속성은 기능 상태를 평가할 때 필터가 Any 또는 All 논리를 사용해야 하는지 결정하는 데 사용됩니다. RequirementType이 지정되지 않은 경우 기본값은 Any입니다.

  • Any는 기능을 사용하도록 설정하려면 하나의 필터만 true로 평가되어야 함을 의미합니다.
  • All은 기능을 사용하도록 설정하려면 모든 필터가 true로 평가되어야 함을 의미합니다.

AllRequirementType은 트래버스를 변경합니다. 첫째, 필터가 없으면 기능이 사용하지 않도록 설정됩니다. 그런 다음 필터 중 하나가 해당 기능을 사용하지 않도록 설정해야 한다고 결정할 때까지 기능 필터가 트래버스됩니다. 기능을 사용하지 않도록 설정해야 함을 나타내는 필터가 없으면 사용하도록 설정된 것으로 간주됩니다.

"FeatureW": {
    "RequirementType": "All",
    "EnabledFor": [
        {
            "Name": "TimeWindow",
            "Parameters": {
                "Start": "Mon, 01 May 2023 13:59:59 GMT",
                "End": "Sat, 01 Jul 2023 00:00:00 GMT"
            }
        },
        {
            "Name": "Percentage",
            "Parameters": {
                "Value": "50"
            }
        }
    ]
}

위의 예에서 FeatureWAllRequirementType을 지정합니다. 즉, 기능을 사용하도록 설정하려면 모든 필터가 true로 평가되어야 합니다. 이 경우 지정된 기간 동안 50%의 사용자에게 이 기능이 사용하도록 설정됩니다.

Microsoft 기능 관리 스키마

기능 관리 라이브러리는 기능 플래그를 선언하기 위한 Microsoft Feature Management schema 사용도 지원합니다. 이 스키마는 원래 언어에 구애받지 않으며 모든 Microsoft 기능 관리 라이브러리에서 지원됩니다.

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "FeatureT",
                "enabled": true,
                "conditions": {
                    "client_filters": [
                        {  
                            "name": "Microsoft.TimeWindow",
                            "parameters": {
                                "Start": "Mon, 01 May 2023 13:59:59 GMT",
                                "End": "Sat, 01 Jul 2023 00:00:00 GMT"
                            }
                        }
                    ]
                }
            }
        ]
    }
}

참고 항목

구성에서 feature_management 섹션을 찾을 수 있으면 FeatureManagement 섹션은 무시됩니다.

기능 관리 라이브러리는 .NET Core의 IConfiguration 시스템에 대한 공급자이므로 appsettings.json을 기능 플래그 원본으로 지원합니다. 기능 플래그는 Microsoft Feature Management schema를 사용하여 선언됩니다. 이 스키마는 원래 언어에 구애받지 않으며 모든 Microsoft 기능 관리 라이브러리에서 지원됩니다.

아래에는 json 파일에서 기능 플래그를 선언하는 예가 있습니다.

{
    "Logging": {
        "LogLevel": {
            "Default": "Warning"
        }
    },

    // Define feature flags in a json file
    "feature_management": {
        "feature_flags": [
            {
                "id": "FeatureT",
                "enabled": false
            },
            {
                "id": "FeatureU",
                "enabled": true,
                "conditions": {}
            },
            {
                "id": "FeatureV",
                "enabled": true,
                "conditions": {
                    "client_filters": [
                        {  
                            "name": "Microsoft.TimeWindow",
                            "parameters": {
                                "Start": "Mon, 01 May 2023 13:59:59 GMT",
                                "End": "Sat, 01 July 2023 00:00:00 GMT"
                            }
                        }
                    ]
                }
            }
        ]
    }
}

json 문서의 feature_management 섹션은 규칙에 따라 기능 플래그 설정을 로드하는 데 사용됩니다. 기능 플래그 개체는 feature_management 섹션 아래의 feature_flags 배열에 나열되어야 합니다. 위 섹션에서는 세 가지 다른 기능을 제공했음을 알 수 있습니다. 기능 플래그에는 idenabled 속성이 있습니다. id는 기능 플래그를 식별하고 참조하는 데 사용되는 이름입니다. enabled 속성은 기능 플래그의 사용하도록 설정 상태를 지정합니다. enabled가 false인 경우 기능은 끄기입니다. enabled가 true이면 기능의 상태는 conditions에 따라 달라집니다. conditions가 없으면 기능이 켜기입니다. conditions가 있고 충족되면 기능이 켜기입니다. conditions가 있고 충족되지 않으면 기능이 끄기입니다. conditions 속성은 기능을 동적으로 사용하도록 설정하는 데 사용되는 조건을 선언합니다. 기능은 client_filters 배열에서 기능 필터를 정의합니다. FeatureVMicrosoft.TimeWindow라는 기능 필터를 지정합니다. 이는 구성 가능한 기능 필터의 예입니다. 이 예에서 필터에 Parameters 속성이 있음을 볼 수 있습니다. 필터를 구성하는 데 사용됩니다. 이 경우 해당 기능이 활성화되는 시작 및 종료 시간이 구성됩니다.

고급: 기능 플래그 이름에는 콜론 ':'을 사용할 수 없습니다.

RequirementType

conditionsrequirement_type 속성은 기능의 상태를 평가할 때 필터가 Any 또는 All 논리를 사용해야 하는지 결정하는 데 사용됩니다. requirement_type이 지정되지 않은 경우 기본값은 Any입니다.

  • Any는 기능을 사용하도록 설정하려면 하나의 필터만 true로 평가되어야 함을 의미합니다.
  • All은 기능을 사용하도록 설정하려면 모든 필터가 true로 평가되어야 함을 의미합니다.

Allrequirement_type은 트래버스를 변경합니다. 첫째, 필터가 없으면 기능이 사용하지 않도록 설정됩니다. 필터가 있는 경우 필터 중 하나가 해당 기능을 사용하지 않도록 설정해야 한다고 결정할 때까지 기능 필터가 트래버스됩니다. 기능을 사용하지 않도록 설정해야 함을 나타내는 필터가 없으면 사용하도록 설정된 것으로 간주됩니다.

{
    "id": "FeatureW",
    "enabled": true,
    "conditions": {
        "requirement_type": "All",
        "client_filters": [
            {
                "name": "Microsoft.TimeWindow",
                "parameters": {
                    "Start": "Mon, 01 May 2023 13:59:59 GMT",
                    "End": "Sat, 01 Jul 2023 00:00:00 GMT"
                }
            },
            {
                "name": "Microsoft.Percentage",
                "parameters": {
                    "Value": "50"
                }
            }
        ]
    }
}

위의 예에서 FeatureWAllrequirement_type을 지정합니다. 즉, 기능을 사용하도록 설정하려면 모든 필터가 true로 평가되어야 합니다. 이 경우 지정된 기간 동안 50%의 사용자에게 이 기능이 사용하도록 설정됩니다.

.NET 기능 관리 스키마

이전 버전에서 기능 관리 라이브러리의 기본 스키마는 .NET feature management schema이었습니다. v4.0.0부터 변형 및 원격 분석을 포함한 새로운 기능은 .NET 기능 관리 스키마에 대해 지원되지 않습니다.

참고 항목

Microsoft Feature Management schema로 작성된 기능 플래그를 구성에서 찾을 수 있으면 .NET feature management schema로 작성된 기능 플래그는 무시됩니다.

소비

기능 관리의 기본 형태는 기능 플래그가 사용하도록 설정되어 있는지 확인한 다음 그 결과에 따라 작업을 수행하는 것입니다. 이는 IFeatureManagerIsEnabledAsync 메서드를 통해 수행됩니다.

…
IFeatureManager featureManager;
…
if (await featureManager.IsEnabledAsync("FeatureX"))
{
    // Do something
}

서비스 등록

기능 관리는 .NET Core 종속성 주입을 사용합니다. 표준 규칙을 사용하여 기능 관리 서비스를 등록할 수 있습니다.

using Microsoft.FeatureManagement;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddFeatureManagement();
    }
}

기본적으로 기능 관리자는 .NET Core 구성 데이터의 "FeatureManagement" 섹션에서 기능 플래그 구성을 검색합니다. "FeatureManagement" 섹션이 없으면 구성은 비어 있는 것으로 간주됩니다.

참고 항목

섹션을 AddFeatureManagement에 전달하여 다른 구성 섹션에서 기능 플래그 구성을 검색하도록 지정할 수도 있습니다. 다음 예에서는 기능 관리자에게 대신 "MyFeatureFlags"라는 다른 섹션을 읽도록 지시합니다.

services.AddFeatureManagement(configuration.GetSection("MyFeatureFlags"));

종속성 주입

MVC와 함께 기능 관리 라이브러리를 사용하는 경우 종속성 주입을 통해 IFeatureManager를 가져올 수 있습니다.

public class HomeController : Controller
{
    private readonly IFeatureManager _featureManager;
    
    public HomeController(IFeatureManager featureManager)
    {
        _featureManager = featureManager;
    }
}

범위가 지정된 기능 관리 서비스

AddFeatureManagement 메서드는 애플리케이션 내에서 기능 관리 서비스를 싱글톤으로 추가하지만 대신 기능 관리 서비스를 범위가 지정된 서비스로 추가해야 하는 시나리오가 있습니다. 예를 들어, 사용자는 컨텍스트 정보를 위해 범위가 지정된 서비스를 사용하는 기능 필터를 사용하려고 할 수 있습니다. 이 경우에는 AddScopedFeatureManagement 메서드를 대신 사용해야 합니다. 이렇게 하면 기능 필터를 포함한 기능 관리 서비스가 범위 서비스로 추가됩니다.

services.AddScopedFeatureManagement();

ASP.NET Core 통합

기능 관리 라이브러리는 웹 애플리케이션에서 일반적인 기능 플래그 시나리오를 사용하도록 설정하기 위해 ASP.NET Core 및 MVC의 기능을 제공합니다. 이러한 기능은 Microsoft.FeatureManagement.AspNetCore NuGet 패키지를 참조하여 사용할 수 있습니다.

컨트롤러 및 작업

MVC 컨트롤러 및 작업을 실행하려면 특정 기능 또는 기능 목록 중 하나를 사용하도록 설정해야 할 수 있습니다. 이는 Microsoft.FeatureManagement.Mvc 네임스페이스에 있는 FeatureGateAttribute를 사용하여 수행할 수 있습니다.

[FeatureGate("FeatureX")]
public class HomeController : Controller
{
    …
}

위의 HomeController는 "FeatureX"에 의해 제어됩니다. HomeController에 포함된 작업을 실행하려면 먼저 "FeatureX"를 사용하도록 설정해야 합니다.

[FeatureGate("FeatureX")]
public IActionResult Index()
{
    return View();
}

위의 Index MVC 작업을 실행하려면 먼저 "FeatureX"를 사용하도록 설정해야 합니다.

사용하지 않도록 설정된 작업 처리

MVC 컨트롤러 또는 작업이 지정하는 기능이 사용하도록 설정되지 않아 차단되면 등록된 IDisabledFeaturesHandler가 호출됩니다. 기본적으로 HTTP 404를 반환하는 최소 처리기가 등록됩니다. 기능 플래그를 등록할 때 IFeatureManagementBuilder를 사용하여 재정의할 수 있습니다.

public interface IDisabledFeaturesHandler
{
    Task HandleDisabledFeature(IEnumerable<string> features, ActionExecutingContext context);
}

보기

MVC 보기에서는 <feature> 태그를 사용하여 기능의 사용하도록 설정 여부에 따라 조건부로 콘텐츠를 렌더링할 수 있습니다.

<feature name="FeatureX">
  <p>This can only be seen if 'FeatureX' is enabled.</p>
</feature>

기능이나 기능 집합이 사용하지 않도록 설정된 경우 콘텐츠를 표시하기 위해 태그 도우미 평가를 무효화할 수도 있습니다. 아래 예에서 negate="true"를 설정하면 FeatureX가 사용하지 않도록 설정된 경우에만 콘텐츠가 렌더링됩니다.

<feature negate="true" name="FeatureX">
  <p>This can only be seen if 'FeatureX' is disabled.</p>
</feature>

<feature> 태그는 name 특성에 쉼표로 구분된 기능 목록을 지정하여 여러 기능을 참조할 수 있습니다.

<feature name="FeatureX,FeatureY">
  <p>This can only be seen if 'FeatureX' and 'FeatureY' are enabled.</p>
</feature>

기본적으로 기능 태그를 렌더링하려면 나열된 모든 기능을 사용하도록 설정해야 합니다. 아래 예에 표시된 대로 requirement 특성을 추가하여 이 동작을 재정의할 수 있습니다.

<feature name="FeatureX,FeatureY" requirement="Any">
  <p>This can only be seen if either 'FeatureX' or 'FeatureY' or both are enabled.</p>
</feature>

MVC 보기에서 <feature> 태그를 사용하면 기능이 사용하도록 설정되었는지 또는 기능의 특정 변형이 할당되었는지 여부에 따라 조건부로 콘텐츠를 렌더링할 수 있습니다. 자세한 내용은 변형 섹션을 참조하세요.

<feature name="FeatureX">
  <p>This can only be seen if 'FeatureX' is enabled.</p>
</feature>
<feature name="FeatureX" variant="Alpha">
  <p>This can only be seen if variant 'Alpha' of 'FeatureX' is assigned.</p>
</feature>

기능이나 기능 집합이 사용하지 않도록 설정된 경우 콘텐츠를 표시하기 위해 태그 도우미 평가를 무효화할 수도 있습니다. 아래 예에서 negate="true"를 설정하면 FeatureX가 사용하지 않도록 설정된 경우에만 콘텐츠가 렌더링됩니다.

<feature negate="true" name="FeatureX">
  <p>This can only be seen if 'FeatureX' is disabled.</p>
</feature>
<feature negate="true" name="FeatureX" variant="Alpha">
  <p>This can only be seen if variant 'Alpha' of 'FeatureX' isn't assigned.</p>
</feature>

<feature> 태그는 name/variant 특성에 쉼표로 구분된 기능/변형 목록을 지정하여 여러 기능/변형을 참조할 수 있습니다.

<feature name="FeatureX,FeatureY">
  <p>This can only be seen if 'FeatureX' and 'FeatureY' are enabled.</p>
</feature>
<feature name="FeatureX" variant="Alpha,Beta">
  <p>This can only be seen if variant 'Alpha' or 'Beta' of 'FeatureX' is assigned.</p>
</feature>

참고 항목

variant가 지정된 경우 하나의 기능만 지정해야 합니다.

기본적으로 기능 태그를 렌더링하려면 나열된 모든 기능을 사용하도록 설정해야 합니다. 아래 예에 표시된 대로 requirement 특성을 추가하여 이 동작을 재정의할 수 있습니다.

참고 항목

Andrequirementvariant와 함께 사용하면 여러 변형을 할당할 수 없으므로 오류가 throw됩니다.

<feature name="FeatureX,FeatureY" requirement="Any">
  <p>This can only be seen if either 'FeatureX' or 'FeatureY' or both are enabled.</p>
</feature>

<feature> 태그가 작동하려면 태그 도우미가 필요합니다. 이는 기능 관리 태그 도우미를 ViewImports.cshtml 파일에 추가하여 수행할 수 있습니다.

@addTagHelper *, Microsoft.FeatureManagement.AspNetCore

MVC 필터

MVC 작업 필터는 기능 상태에 따라 조건부로 실행되도록 설정할 수 있습니다. 이는 기능 인식 방식으로 MVC 필터를 등록하여 수행됩니다. 기능 관리 파이프라인은 IAsyncActionFilter를 구현하는 비동기 MVC 작업 필터를 지원합니다.

services.AddMvc(o => 
{
    o.Filters.AddForFeature<SomeMvcFilter>("FeatureX");
});

위의 코드는 SomeMvcFilter라는 MVC 필터를 추가합니다. 이 필터는 "FeatureX"가 사용하도록 설정된 경우 MVC 파이프라인 내에서만 트리거됩니다.

Razor Pages

MVC Razor 페이지를 실행하려면 특정 기능 또는 기능 목록 중 하나를 사용하도록 설정해야 할 수 있습니다. 이는 Microsoft.FeatureManagement.Mvc 네임스페이스에 있는 FeatureGateAttribute를 사용하여 수행할 수 있습니다.

[FeatureGate("FeatureX")]
public class IndexModel : PageModel
{
    public void OnGet()
    {
    }
}

위의 코드는 "FeatureX"를 사용하도록 설정하도록 요구하는 Razor 페이지를 설정합니다. 기능이 사용하도록 설정되지 않으면 페이지에서 HTTP 404(NotFound) 결과를 생성합니다.

Razor 페이지에서 사용되는 경우 FeatureGateAttribute는 페이지 처리기 형식에 배치되어야 합니다. 개별 처리기 메서드에 배치할 수 없습니다.

애플리케이션 빌드

기능 관리 라이브러리를 사용하면 기능 상태에 따라 조건부로 실행되는 애플리케이션 분기 및 미들웨어를 추가할 수 있습니다.

app.UseMiddlewareForFeature<ThirdPartyMiddleware>("FeatureX");

위 호출을 통해 애플리케이션은 "FeatureX" 기능이 사용하도록 설정된 경우 요청 파이프라인에만 나타나는 미들웨어 구성 요소를 추가합니다. 런타임 중에 기능이 사용/사용 안 함으로 설정되면 미들웨어 파이프라인이 동적으로 변경될 수 있습니다.

이렇게 하면 기능에 따라 전체 애플리케이션을 분기하는 보다 일반적인 기능이 빌드됩니다.

app.UseForFeature(featureName, appBuilder => 
{
    appBuilder.UseMiddleware<T>();
});

기능 필터 구현

기능 필터를 만들면 정의한 기준에 따라 기능을 사용하도록 설정할 수 있습니다. 기능 필터를 구현하려면 IFeatureFilter 인터페이스를 구현해야 합니다. IFeatureFilter에는 EvaluateAsync라는 단일 메서드가 있습니다. 기능이 기능 필터에 대해 사용하도록 설정될 수 있음을 지정하면 EvaluateAsync 메서드가 호출됩니다. EvaluateAsynctrue를 반환하는 경우 해당 기능을 사용하도록 설정해야 한다는 의미입니다.

다음 코드 조각은 사용자 지정된 기능 필터 MyCriteriaFilter를 추가하는 방법을 보여 줍니다.

services.AddFeatureManagement()
        .AddFeatureFilter<MyCriteriaFilter>();

기능 필터는 AddFeatureManagement에서 반환된 IFeatureManagementBuilder에서 AddFeatureFilter<T>를 호출하여 등록됩니다. 이러한 기능 필터는 기능 플래그를 추가하는 데 사용된 서비스 컬렉션 내에 존재하는 서비스에 액세스할 수 있습니다. 종속성 주입을 사용하여 이러한 서비스를 검색할 수 있습니다.

참고 항목

기능 플래그 설정(예: appsettings.json)에서 필터를 참조하는 경우 형식 이름의 Filter 부분을 생략해야 합니다. 자세한 내용은 Filter Alias Attribute 섹션을 참조하세요.

매개 변수가 있는 기능 필터

일부 기능 필터에는 기능을 켜야 하는지 여부를 결정하는 매개 변수가 필요합니다. 예를 들어, 브라우저 기능 필터는 특정 브라우저 집합에 대한 기능을 켤 수 있습니다. Edge 및 Chrome 브라우저에서는 기능을 사용하도록 설정하는 것이 바람직할 수 있지만 Firefox에서는 그렇지 않습니다. 이를 위해 매개 변수를 예상하도록 기능 필터를 설계할 수 있습니다. 이러한 매개 변수는 기능 구성에 지정되며 코드에서는 IFeatureFilter.EvaluateAsyncFeatureFilterEvaluationContext 매개 변수를 통해 액세스할 수 있습니다.

public class FeatureFilterEvaluationContext
{
    /// <summary>
    /// The name of the feature being evaluated.
    /// </summary>
    public string FeatureName { get; set; }

    /// <summary>
    /// The settings provided for the feature filter to use when evaluating whether the feature should be enabled.
    /// </summary>
    public IConfiguration Parameters { get; set; }
}

FeatureFilterEvaluationContext에는 Parameters라는 속성이 있습니다. 이러한 매개 변수는 기능 필터가 기능 사용 여부를 평가하는 방법을 결정하는 데 사용할 수 있는 원시 구성을 나타냅니다. 브라우저 기능 필터를 다시 한 번 예로 사용하기 위해 필터는 Parameters를 사용하여 기능을 위해 지정될 허용 브라우저 집합을 추출한 다음 요청이 해당 브라우저 중 하나에서 전송되고 있는지 확인할 수 있습니다.

[FilterAlias("Browser")]
public class BrowserFilter : IFeatureFilter
{
    …

    public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext context)
    {
        BrowserFilterSettings settings = context.Parameters.Get<BrowserFilterSettings>() ?? new BrowserFilterSettings();

        //
        // Here we would use the settings and see if the request was sent from any of BrowserFilterSettings.AllowedBrowsers
    }
}

필터 별칭 특성

기능 플래그에 대해 기능 필터가 등록되면 구성에 사용되는 별칭은 Filter 접미사가 제거된 기능 필터 형식의 이름입니다. 예를 들어, MyCriteriaFilter는 구성에서 MyCriteria로 참조됩니다.

"MyFeature": {
    "EnabledFor": [
        {
            "Name": "MyCriteria"
        }
    ]
}

이는 FilterAliasAttribute를 사용하여 재정의할 수 있습니다. 기능 필터는 이 특성으로 장식되어 기능 플래그 내에서 이 기능 필터를 참조하기 위해 구성에 사용해야 하는 이름을 선언할 수 있습니다.

누락된 기능 필터

특정 기능 필터에 대해 기능이 사용하도록 구성되어 있고 해당 기능 필터가 등록되지 않은 경우 기능을 평가할 때 예외가 throw됩니다. 기능 관리 옵션을 사용하여 예외를 사용하지 않도록 설정할 수 있습니다.

services.Configure<FeatureManagementOptions>(options =>
{
    options.IgnoreMissingFeatureFilters = true;
});

HttpContext 사용

기능 필터는 HTTP 요청의 속성을 기반으로 기능을 사용하도록 설정해야 하는지 여부를 평가할 수 있습니다. 이는 HTTP 컨텍스트를 검사하여 수행됩니다. 기능 필터는 종속성 주입을 통해 IHttpContextAccessor를 획득하여 HTTP 컨텍스트에 대한 참조를 가져올 수 있습니다.

public class BrowserFilter : IFeatureFilter
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public BrowserFilter(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
    }
}

IHttpContextAccessor를 사용하려면 시작 시 종속성 주입 컨테이너에 추가해야 합니다. 다음 방법을 사용하여 IServiceCollection에 등록할 수 있습니다.

public void ConfigureServices(IServiceCollection services)
{
    …
    services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    …
}

고급: IHttpContextAccessor/HttpContext는 서버 쪽 Blazor 앱의 Razor 구성 요소에서 사용하면 안 됩니다. Blazor 앱에서 http 컨텍스트를 전달하기 위한 권장되는 방식은 범위가 지정된 서비스에 데이터를 복사하는 것입니다. Blazor 앱의 경우 기능 관리 서비스를 등록하려면 AddScopedFeatureManagement를 사용해야 합니다. 자세한 내용은 Scoped Feature Management Services 섹션을 참조하세요.

기능 평가를 위한 컨텍스트 제공

기능을 켜기 또는 끄기로 설정해야 하는지 확인하기 위해 기능 필터가 획득하고 활용할 수 있는 HttpContext와 같은 앰비언트 컨텍스트가 콘솔 애플리케이션에 없습니다. 이 경우 애플리케이션은 기능 필터에서 사용할 수 있도록 기능 관리 시스템에 컨텍스트를 나타내는 개체를 제공해야 합니다. 이 작업은 IFeatureManager.IsEnabledAsync<TContext>(string featureName, TContext appContext)를 사용하여 수행됩니다. 기능 관리자에 제공되는 appContext 개체는 기능 필터에서 기능 상태를 평가하는 데 사용될 수 있습니다.

MyAppContext context = new MyAppContext
{
    AccountId = current.Id;
}

if (await featureManager.IsEnabledAsync(feature, context))
{
…
}

상황에 맞는 기능 필터

상황에 맞는 기능 필터는 IContextualFeatureFilter<TContext> 인터페이스를 구현합니다. 이러한 특수 기능 필터는 IFeatureManager.IsEnabledAsync<TContext>가 호출될 때 전달되는 컨텍스트를 활용할 수 있습니다. IContextualFeatureFilter<TContext>TContext 형식 매개 변수는 필터가 처리할 수 있는 컨텍스트 형식을 설명합니다. 이를 통해 상황에 맞는 기능 필터 개발자는 이를 활용하려는 사용자들에게 필요한 것이 무엇인지 설명할 수 있습니다. 모든 형식은 개체의 하위 항목이므로 제공된 컨텍스트에 대해 IContextualFeatureFilter<object>를 구현하는 필터를 호출할 수 있습니다. 보다 구체적인 상황에 맞는 기능 필터의 예를 설명하려면 계정이 구성된 사용하도록 설정된 계정 목록에 있는 경우 사용하도록 설정되는 기능을 고려합니다.

public interface IAccountContext
{
    string AccountId { get; set; }
}

[FilterAlias("AccountId")]
class AccountIdFilter : IContextualFeatureFilter<IAccountContext>
{
    public Task<bool> EvaluateAsync(FeatureFilterEvaluationContext featureEvaluationContext, IAccountContext accountId)
    {
        //
        // Evaluate if the feature should be on with the help of the provided IAccountContext
    }
}

기능의 상태를 평가할 수 있으려면 AccountIdFilter에서 IAccountContext를 구현하는 개체가 제공되어야 한다는 것을 알 수 있습니다. 이 기능 필터를 사용할 때 호출자는 전달된 개체가 IAccountContext를 구현하는지 확인해야 합니다.

참고 항목

단일 형식에서는 단일 기능 필터 인터페이스만 구현할 수 있습니다. 둘 이상의 기능 필터 인터페이스를 구현하는 기능 필터를 추가하려고 하면 ArgumentException이 발생합니다.

동일한 별칭으로 상황에 맞는 필터와 상황에 맞지 않는 필터 사용

IFeatureFilterIContextualFeatureFilter의 필터는 동일한 별칭을 공유할 수 있습니다. 특히, ContextType에 적용 가능한 필터가 최대 1개만 있는 한 0 또는 1개의 IFeatureFilter 및 0 또는 N개의 IContextualFeatureFilter<ContextType>이 공유하는 하나의 필터 별칭을 가질 수 있습니다.

다음은 동일한 이름의 상황에 맞는 필터와 상황에 맞지 않는 필터가 애플리케이션에 등록된 경우 필터를 선택하는 과정을 설명합니다.

FilterA라는 상황에 맞지 않는 필터와 각각 TypeBTypeC 컨텍스트를 허용하는 두 개의 상황에 맞는 필터 FilterB 및 FilterC가 있다고 가정해 보겠습니다. 세 필터 모두 동일한 별칭 SharedFilterName을 공유합니다.

구성에 기능 필터 SharedFilterName을 사용하는 기능 플래그 MyFeature도 있습니다.

세 가지 필터가 모두 등록된 경우:

  • IsEnabledAsync("MyFeature")를 호출하면 FilterA가 기능 플래그를 평가하는 데 사용됩니다.
  • IsEnabledAsync("MyFeature", context)를 호출할 때 컨텍스트 형식이 TypeB이면 FilterB가 사용됩니다. 컨텍스트 형식이 TypeC이면 FilterC가 사용됩니다.
  • IsEnabledAsync("MyFeature", context)를 호출할 때 컨텍스트 형식이 TypeF이면 FilterA가 사용됩니다.

기본 제공 기능 필터

Microsoft.FeatureManagement 패키지와 함께 제공되는 몇 가지 기능 필터(PercentageFilter, TimeWindowFilter, ContextualTargetingFilterTargetingFilter)가 있습니다. AddFeatureManagement 메서드로 기능 관리를 등록하면 TargetingFilter를 제외한 모든 필터가 자동으로 추가됩니다. TargetingFilter는 아래 Targeting 섹션에 자세히 설명된 WithTargeting 메서드를 사용하여 추가됩니다.

기본 제공된 각 기능 필터에는 고유한 매개 변수가 있습니다. 다음은 예를 함께 보여 주는 기능 필터 목록입니다.

Microsoft.Percentage

이 필터는 설정된 백분율을 기준으로 기능을 사용하도록 설정하는 기능을 제공합니다.

"EnhancedPipeline": {
    "EnabledFor": [
        {
            "Name": "Microsoft.Percentage",
            "Parameters": {
                "Value": 50
            }
        }
    ]
}

Microsoft.TimeWindow

이 필터는 기간을 기반으로 기능을 사용하도록 설정하는 기능을 제공합니다. End만 지정된 경우 해당 시간까지 기능이 사용되는 것으로 간주됩니다. Start만 지정된 경우 해당 시간 이후의 모든 지점에서 기능이 켜진 것으로 간주됩니다.

"EnhancedPipeline": {
    "EnabledFor": [
        {
            "Name": "Microsoft.TimeWindow",
            "Parameters": {
                "Start": "Wed, 01 May 2019 13:59:59 GMT",
                "End": "Mon, 01 Jul 2019 00:00:00 GMT"
            }
        }
    ]
}

기간은 주기적으로 되풀이되도록 구성할 수 있습니다. 이는 하루 중 트래픽이 적거나 높은 기간이나 특정 요일에 기능을 켜야 하는 시나리오에 유용할 수 있습니다. 개별 기간을 되풀이 기간으로 확장하려면 Recurrence 매개 변수에 되풀이 규칙을 지정해야 합니다.

참고 항목

Recurrence를 사용하도록 설정하려면 StartEnd를 모두 지정해야 합니다.

"EnhancedPipeline": {
    "EnabledFor": [
        {
            "Name": "Microsoft.TimeWindow",
            "Parameters": {
                "Start": "Fri, 22 Mar 2024 20:00:00 GMT",
                "End": "Sat, 23 Mar 2024 02:00:00 GMT",
                "Recurrence": {
                    "Pattern": {
                        "Type": "Daily",
                        "Interval": 1
                    },
                    "Range": {
                        "Type": "NoEnd"
                    }
                }
            }
        }
    ]
}

Recurrence 설정은 Pattern(기간이 반복되는 빈도) 및 Range(되풀이 방법이 반복되는 기간)의 두 부분으로 구성됩니다.

되풀이 방법

가능한 되풀이 방법 형식은 DailyWeekly 두 가지입니다. 예를 들어, 기간은 "매일", "3일마다", "매주 월요일" 또는 "격주 금요일"을 반복할 수 있습니다.

형식에 따라 Pattern의 특정 필드는 필수, 선택 또는 무시됩니다.

  • Daily

    일별 되풀이 방법을 사용하면 각 발생 사이의 일 수를 기준으로 기간이 반복됩니다.

    속성 정확도 설명
    형식 Required Daily로 설정해야 합니다.
    간격 선택 사항 각 발생 사이의 일 수를 지정합니다. 기본값은 1입니다.
  • Weekly

    주별 되풀이 방법을 사용하면 각 발생 집합 사이의 주 수를 기준으로 동일한 요일에 기간이 반복됩니다.

    속성 정확도 설명
    형식 Required Weekly로 설정해야 합니다.
    DaysOfWeek Required 이벤트가 발생하는 요일을 지정합니다.
    간격 선택 사항 각 발생 집합 사이의 주 수를 지정합니다. 기본값은 1입니다.
    FirstDayOfWeek 선택 사항 주의 첫 번째 날로 간주되는 요일을 지정합니다. 기본값은 Sunday여야 합니다.

    다음 예에서는 격주로 월요일과 화요일에 기간을 반복합니다.

    "Pattern": {
        "Type": "Weekly",
        "Interval": 2,
        "DaysOfWeek": ["Monday", "Tuesday"]
    }
    

참고 항목

Start는 되풀이 방법에 맞는 유효한 첫 번째 발생이어야 합니다. 또한 기간의 지속 시간은 발생 빈도보다 길 수 없습니다. 예를 들어, 매일 25시간의 기간을 되풀이하는 것은 유효하지 않습니다.

되풀이 범위

가능한 되풀이 범위 형식은 NoEnd, EndDateNumbered의 세 가지입니다.

  • NoEnd

    NoEnd 범위로 인해 되풀이가 무기한 발생합니다.

    속성 정확도 설명
    형식 Required NoEnd로 설정해야 합니다.
  • EndDate

    EndDate 범위를 사용하면 종료 날짜까지 적용 가능한 패턴에 맞는 모든 날짜에 기간이 발생합니다.

    속성 정확도 설명
    형식 Required EndDate로 설정해야 합니다.
    EndDate Required 패턴 적용을 중지할 날짜 시간을 지정합니다. 마지막 발생의 시작 시간이 종료 날짜 이전인 한 해당 발생의 종료 시간은 그 이후까지 연장될 수 있습니다.

    다음 예에서는 2024년 4월 1일에 마지막 발생이 발생할 때까지 매일 기간을 반복합니다.

    "Start": "Fri, 22 Mar 2024 18:00:00 GMT",
    "End": "Fri, 22 Mar 2024 20:00:00 GMT",
    "Recurrence":{
        "Pattern": {
            "Type": "Daily",
            "Interval": 1
        },
        "Range": {
            "Type": "EndDate",
            "EndDate": "Mon, 1 Apr 2024 20:00:00 GMT"
        }
    }
    
  • Numbered

    Numbered 범위는 기간이 고정된 횟수(패턴에 따라) 발생하도록 합니다.

    속성 정확도 설명
    형식 Required Numbered로 설정해야 합니다.
    NumberOfOccurrences Required 발생 횟수를 지정합니다.

    다음 예에서는 4월 1일(월), 4월 2일(화), 4월 8일(월)에 각각 3번 발생할 때까지 월요일과 화요일의 기간을 반복합니다.

    "Start": "Mon, 1 Apr 2024 18:00:00 GMT",
    "End": "Mon, 1 Apr 2024 20:00:00 GMT",
    "Recurrence":{
        "Pattern": {
            "Type": "Weekly",
            "Interval": 1,
            "DaysOfWeek": ["Monday", "Tuesday"]
        },
        "Range": {
            "Type": "Numbered",
            "NumberOfOccurrences": 3
        }
    }
    

되풀이 규칙을 만들려면 PatternRange를 모두 지정해야 합니다. 모든 패턴 형식은 모든 범위 형식에서 작동할 수 있습니다.

고급: Start 속성의 표준 시간대 오프셋이 되풀이 설정에 적용됩니다.

Microsoft.Targeting

이 필터는 대상 그룹 고객을 위한 기능을 사용하도록 설정하는 기능을 제공합니다. 대상 지정에 대한 자세한 설명은 아래의 대상 지정 섹션에 설명되어 있습니다. 필터 매개 변수에는 사용자, 그룹, 제외된 사용자/그룹, 기능에 액세스해야 하는 사용자 기반의 기본 비율을 설명하는 Audience 개체가 포함됩니다. Groups 섹션에 나열된 각 그룹 개체는 액세스 권한을 가져야 하는 그룹 멤버의 비율도 지정해야 합니다. 사용자가 Exclusion 섹션에 직접 지정된 경우 또는 사용자가 제외된 그룹에 있는 경우 기능이 사용하지 않도록 설정됩니다. 또한 사용자가 Users 섹션에 직접 지정되거나, 사용자가 임의 그룹 출시의 포함된 비율에 속하거나, 사용자가 기본 출시 비율에 속하는 경우 해당 사용자는 기능을 사용하도록 설정하게 됩니다.

"EnhancedPipeline": {
    "EnabledFor": [
        {
            "Name": "Microsoft.Targeting",
            "Parameters": {
                "Audience": {
                    "Users": [
                        "Jeff",
                        "Alicia"
                    ],
                    "Groups": [
                        {
                            "Name": "Ring0",
                            "RolloutPercentage": 100
                        },
                        {
                            "Name": "Ring1",
                            "RolloutPercentage": 50
                        }
                    ],
                    "DefaultRolloutPercentage": 20,
                    "Exclusion": {
                        "Users": [
                            "Ross"
                        ],
                        "Groups": [
                            "Ring2"
                        ]
                    }
                }
            }
        }
    ]
}

기능 필터 별칭 네임스페이스

기본 제공된 기능 필터 별칭은 모두 Microsoft 기능 필터 네임스페이스에 있습니다. 이는 동일한 별칭을 공유할 수 있는 다른 기능 필터와의 충돌을 방지하기 위한 것입니다. 기능 필터 네임스페이스의 세그먼트는 '.' 문자로 분할됩니다. 기능 필터는 Microsoft.Percentage와 같은 정규화된 별칭 또는 Microsoft.PercentagePercentage인 마지막 세그먼트로 참조될 수 있습니다.

대상 지정

대상 지정은 개발자가 사용자 기반에 새로운 기능을 점진적으로 롤아웃할 수 있도록 하는 기능 관리 전략입니다. 이 전략은 대상 그룹으로 알려진 일련의 사용자를 대상으로 지정한다는 개념을 바탕으로 빌드되었습니다. 대상 그룹은 특정 사용자, 그룹, 제외된 사용자/그룹, 전체 사용자 기반 중 지정된 비율로 구성됩니다. 대상 그룹에 포함된 그룹은 전체 멤버의 비율로 더 세분화될 수 있습니다.

다음 단계에서는 새로운 '베타' 기능에 대한 점진적 출시의 예를 보여 줍니다.

  1. 개별 사용자 Jeff와 Alicia에게 베타에 대한 액세스 권한이 부여됩니다.
  2. 다른 사용자 Mark가 옵트인을 요청하여 포함되었습니다.
  3. "Ring1" 사용자로 알려진 그룹의 20%가 베타에 포함되어 있습니다.
  4. 베타 버전에 포함된 "Ring1" 사용자 수는 최대 100%까지 증가합니다.
  5. 사용자 기반의 5%가 베타 버전에 포함됩니다.
  6. 출시 비율이 100%까지 올라가고 기능이 완전히 출시됩니다.

기능 출시를 위한 이 전략은 포함된 Microsoft.Targeting 기능 필터를 통해 라이브러리에 기본 제공되어 있습니다.

웹 애플리케이션에서 대상 지정

대상 지정 기능 필터를 사용하는 웹 애플리케이션 예는 FeatureFlagDemo 프로젝트 예에서 사용할 수 있습니다.

애플리케이션에서 TargetingFilter 사용을 시작하려면 다른 기능 필터와 마찬가지로 애플리케이션의 서비스 컬렉션에 추가해야 합니다. 다른 기본 제공 필터와 달리 TargetingFilter는 애플리케이션의 서비스 컬렉션에 추가되는 다른 서비스를 사용합니다. 해당 서비스는 ITargetingContextAccessor입니다.

ITargetingContextAccessor 서비스에 사용되는 구현 형식은 대상 지정 필터를 사용하는 애플리케이션에 의해 구현되어야 합니다. 다음은 HttpContextTargetingContextAccessor라는 ITargetingContextAccessor 구현과 함께 TargetingFilter를 사용하기 위해 웹 애플리케이션에서 기능 관리를 설정하는 예입니다.

services.AddFeatureManagement()
        .WithTargeting<HttpContextTargetingContextAccessor>();

대상 지정 컨텍스트 접근자와 TargetingFilterIFeatureManagementBuilder에서 WithTargeting<T>를 호출하여 등록됩니다.

ITargetingContextAccessor

웹 애플리케이션에서 TargetingFilter를 사용하려면 ITargetingContextAccessor 구현이 필요합니다. 대상 지정 평가를 할 때에는 현재 사용자가 어떤 평가를 가져오고 있는지 등의 정보가 필요하기 때문입니다. 이 정보를 대상 지정 컨텍스트라고 합니다. 다양한 웹 애플리케이션이 다양한 위치에서 이 정보를 추출할 수 있습니다. 애플리케이션이 대상 컨텍스트를 끌어올 수 있는 일반적인 예는 요청의 HTTP 컨텍스트 또는 데이터베이스입니다.

애플리케이션의 HTTP 컨텍스트에서 대상 지정 컨텍스트 정보를 추출하는 예가 FeatureFlagDemo 프로젝트 예에 포함되어 있습니다. 이 방법은 여기에서 토론되는 IHttpContextAccessor의 사용에 따라 다릅니다.

콘솔 애플리케이션에서 대상 지정

대상 지정 필터는 대상 지정 컨텍스트를 사용하여 기능을 켜야 하는지 여부를 평가합니다. 이 대상 지정 컨텍스트에는 현재 평가 중인 사용자, 사용자가 속한 그룹 등의 정보가 포함되어 있습니다. 콘솔 애플리케이션에는 일반적으로 이 정보를 대상 필터로 전달하는 데 사용할 수 있는 앰비언트 컨텍스트가 없으므로 FeatureManager.IsEnabledAsync가 호출될 때 직접 전달되어야 합니다. 이는 ContextualTargetingFilter를 사용하여 지원됩니다. 기능 관리자에 대상 지정 컨텍스트를 플로팅해야 하는 애플리케이션은 TargetingFilter. 대신 이를 사용해야 합니다.

ContextualTargetingFilterIContextualTargetingFilter<ITargetingContext>이므로 기능을 평가하고 활성화하려면 ITargetingContext의 구현을 IFeatureManager.IsEnabledAsync에 전달해야 합니다.

IFeatureManager fm;
…
// userId and groups defined somewhere earlier in application
TargetingContext targetingContext = new TargetingContext
{
   UserId = userId,
   Groups = groups
};

await fm.IsEnabledAsync(featureName, targetingContext);

ContextualTargetingFilter는 여전히 ​​기능 필터 별칭 Microsoft.Targeting을 사용하므로 이 필터의 구성은 해당 섹션에 언급된 내용과 일치합니다.

콘솔 애플리케이션에서 ContextualTargetingFilter를 사용하는 예는 TargetingConsoleApp 프로젝트 예에서 사용할 수 있습니다.

대상 지정 평가 옵션

모든 기능에 걸쳐 대상 평가가 수행되는 방식을 사용자 지정하는 옵션을 사용할 수 있습니다. 이러한 옵션은 기능 관리를 설정할 때 구성할 수 있습니다.

services.Configure<TargetingEvaluationOptions>(options =>
{
    options.IgnoreCase = true;
});

대상 지정 제외

대상 그룹을 정의할 때 사용자 및 그룹을 대상 그룹에서 제외할 수 있습니다. 이는 기능이 사용자 그룹에 출시될 때 유용하지만 일부 사용자 또는 그룹을 출시에서 제외해야 합니다. 제외는 대상 그룹의 Exclusion 속성에 사용자 및 그룹 목록을 추가하여 정의됩니다.

"Audience": {
    "Users": [
        "Jeff",
        "Alicia"
    ],
    "Groups": [
        {
            "Name": "Ring0",
            "RolloutPercentage": 100
        }
    ],
    "DefaultRolloutPercentage": 0
    "Exclusion": {
        "Users": [
            "Mark"
        ]
    }
}

위의 예에서는 JeffAlicia라는 사용자에 대해 기능이 사용하도록 설정되었습니다. Ring0이라는 그룹의 사용자에 대해서도 사용하도록 설정되어 있습니다. 그러나 사용자 이름이 Mark인 경우 그룹 Ring0에 속해 있는지 여부에 관계없이 기능이 사용하지 않도록 설정됩니다. 제외는 나머지 대상 지정 필터보다 우선 순위가 높습니다.

변형

새로운 기능이 애플리케이션에 추가되면 기능에 여러 가지 다른 디자인 옵션이 제안되는 경우가 있을 수 있습니다. 디자인을 결정하기 위한 일반적인 솔루션은 사용자 기반의 다양한 세그먼트에 기능의 다른 버전을 제공하고 사용자 상호 작용을 기반으로 버전을 선택하는 일종의 A/B 테스트입니다. 이 라이브러리에서 이 기능은 변형이 있는 기능의 다양한 구성을 나타냄으로써 사용하도록 설정됩니다.

변형을 사용하면 기능 플래그가 단순한 켜기/끄기 플래그 이상이 될 수 있습니다. 변형은 문자열, 숫자, 부울 또는 구성 개체일 수 있는 기능 플래그의 값을 나타냅니다. 변형을 선언하는 기능 플래그는 각 변형을 사용해야 하는 상황을 정의해야 합니다. 이에 대한 자세한 내용은 변형 할당 섹션에서 다룹니다.

public class Variant
{
    /// <summary>
    /// The name of the variant.
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// The configuration of the variant.
    /// </summary>
    public IConfigurationSection Configuration { get; set; }
}

변형 가져오기

각 기능에 대해 IVariantFeatureManagerGetVariantAsync 메서드를 사용하여 변형을 검색할 수 있습니다.

…
IVariantFeatureManager featureManager;
…
Variant variant = await featureManager.GetVariantAsync(MyFeatureFlags.FeatureU, CancellationToken.None);

IConfigurationSection variantConfiguration = variant.Configuration;

// Do something with the resulting variant and its configuration

변형이 검색되면 변형의 구성을 변형의 Configuration 속성에서 IConfigurationSection으로 직접 사용할 수 있습니다. 또 다른 옵션은 .NET의 구성 바인딩 패턴을 사용하여 구성을 개체에 바인딩하는 것입니다.

IConfigurationSection variantConfiguration = variant.Configuration;

MyFeatureSettings settings = new MyFeatureSettings();

variantConfiguration.Bind(settings);

반환된 변형은 현재 평가 중인 사용자에 따라 달라지며 해당 정보는 TargetingContext의 인스턴스에서 가져옵니다. 이 컨텍스트는 GetVariantAsync를 호출할 때 전달될 수 있거나 등록된 경우 ITargetingContextAccessor의 구현에서 자동으로 검색될 수 있습니다.

변형 기능 플래그 선언

일반 기능 플래그와 비교하여 변형 기능 플래그에는 variantsallocation이라는 두 가지 추가 속성이 있습니다. variants 속성은 이 기능에 대해 정의된 변형을 포함하는 배열입니다. allocation 속성은 이러한 변형을 기능에 할당하는 방법을 정의합니다. 일반 기능 플래그를 선언하는 것과 마찬가지로 json 파일에서 변형 기능 플래그를 설정할 수 있습니다. 다음은 변형 기능 플래그의 예입니다.

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "MyVariantFeatureFlag",
                "enabled": true,
                "allocation": {
                    "default_when_enabled": "Small",
                    "group": [
                        {
                            "variant": "Big",
                            "groups": [
                                "Ring1"
                            ]
                        }
                    ]
                },
                "variants": [
                    { 
                        "name": "Big"
                    },  
                    { 
                        "name": "Small"
                    } 
                ]
            }
        ]
    }
}

변형 정의

각 변형에는 이름과 구성이라는 두 가지 속성이 있습니다. 이름은 특정 변형을 참조하는 데 사용되며 구성은 해당 변형의 값입니다. 구성은 configuration_reference 또는 configuration_value 속성을 사용하여 설정할 수 있습니다. configuration_reference는 기능 플래그 선언이 포함된 현재 구성의 섹션을 참조하는 문자열 경로입니다. configuration_value는 문자열, 숫자, 부울 또는 구성 개체일 수 있는 인라인 구성입니다. 둘 다 지정되면 configuration_value이 사용됩니다. 둘 다 지정되지 않으면 반환된 변형의 Configuration 속성은 null이 됩니다.

가능한 모든 변형 목록은 variants 속성 아래 각 기능에 대해 정의됩니다.

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "MyVariantFeatureFlag",
                "variants": [
                    { 
                        "name": "Big", 
                        "configuration_reference": "ShoppingCart:Big" 
                    },  
                    { 
                        "name": "Small", 
                        "configuration_value": {
                            "Size": 300
                        }
                    } 
                ]
            }
        ]
    },

    "ShoppingCart": {
        "Big": {
            "Size": 600,
            "Color": "green"
        },
        "Small": {
            "Size": 300,
            "Color": "gray"
        }
    }
}

변형 할당

기능의 변형을 할당하는 프로세스는 기능의 allocation 속성에 따라 결정됩니다.

"allocation": { 
    "default_when_enabled": "Small", 
    "default_when_disabled": "Small",  
    "user": [ 
        { 
            "variant": "Big", 
            "users": [ 
                "Marsha" 
            ] 
        } 
    ], 
    "group": [ 
        { 
            "variant": "Big", 
            "groups": [ 
                "Ring1" 
            ] 
        } 
    ],
    "percentile": [ 
        { 
            "variant": "Big", 
            "from": 0, 
            "to": 10 
        } 
    ], 
    "seed": "13973240" 
},
"variants": [
    { 
        "name": "Big", 
        "configuration_reference": "ShoppingCart:Big" 
    },  
    { 
        "name": "Small", 
        "configuration_value": "300px"
    } 
]

기능의 allocation 설정에는 다음과 같은 속성이 있습니다.

속성 설명
default_when_disabled 기능이 사용하지 않도록 설정된 것으로 간주되는 동안 변형이 요청될 때 사용해야 하는 변형을 지정합니다.
default_when_enabled 기능이 사용하도록 설정된 것으로 간주되고 사용자에게 다른 변형이 할당되지 않은 상태에서 변형이 요청될 때 사용해야 하는 변형을 지정합니다.
user 변형과 해당 변형을 할당해야 하는 사용자 목록을 지정합니다.
group 변형 및 그룹 목록을 지정합니다. 사용자가 그룹 중 하나 이상에 속해 있으면 변형이 할당됩니다.
percentile 해당 변형이 할당되기 위해 사용자가 계산한 백분율이 맞아야 하는 변형 및 백분율 범위를 지정합니다.
seed percentile에 대한 백분율 계산의 기준이 되는 값입니다. 동일한 seed 값이 사용되는 경우 특정 사용자에 대한 백분율 계산은 모든 기능에서 동일합니다. seed가 지정되지 않으면 기능 이름을 기반으로 기본 시드가 만들어집니다.

위의 예에서 기능이 사용하도록 설정되지 않은 경우 기능 관리자는 default_when_disabled로 표시된 변형을 현재 사용자에게 할당하며 이 경우에는 Small입니다.

기능이 사용하도록 설정된 경우 기능 관리자는 변형을 할당하기 위해 user, grouppercentile 할당을 순서대로 확인합니다. 이 특정 예에서 평가 중인 사용자의 이름이 Ring1인 그룹에서 Marsha인 경우 또는 사용자가 우연히 0에서 10번째 백분위수 사이에 속하는 경우 지정된 변형이 사용자에게 할당됩니다. 이 경우 이들 모두는 Big 변형을 반환합니다. 이러한 할당 중 일치하는 것이 없으면 사용자에게 default_when_enabled 변형, 즉 Small이 할당됩니다.

할당 논리는 Microsoft.Targeting 기능 필터와 유사하지만 할당에는 없지만 대상 지정에는 존재하는 일부 매개 변수가 있으며 그 반대의 경우도 마찬가지입니다. 대상 지정과 할당의 결과는 관련이 없습니다.

참고 항목

기능 변형 할당을 허용하려면 ITargetingContextAccessor를 등록해야 합니다. 이는 WithTargeting<T> 메서드를 호출하여 수행할 수 있습니다.

변형으로 사용 안 함 상태 재정의

변형을 사용하여 기능 플래그의 사용하도록 설정 상태를 재정의할 수 있습니다. 이는 변형에 기능 플래그의 평가를 확장할 수 있는 기회를 제공합니다. 호출자가 변형이 있는 플래그가 사용하도록 설정되어 있는지 확인하는 경우 기능 관리자는 현재 사용자에게 할당된 변형이 결과를 재정의하도록 설정되어 있는지 확인합니다. 이는 선택적 변형 속성 status_override를 사용하여 수행됩니다. 기본적으로 이 속성은 None으로 설정됩니다. 즉, 이 플래그가 사용 또는 사용 안 함으로 간주되는지에 따라 변형에 영향을 미치지 않습니다. status_overrideEnabled로 설정하면 변형이 선택될 때 사용하도록 설정할 플래그를 재정의할 수 있습니다. status_overrideDisabled로 설정하면 반대 기능이 제공되므로 변형이 선택될 때 플래그가 사용하지 않도록 설정됩니다. enabled 상태가 false인 기능은 재정의할 수 없습니다.

이진 파일 변형과 함께 기능 플래그를 사용하는 경우 status_override 속성이 매우 유용할 수 있습니다. 이를 통해 백분위수 할당 및 시드와 같은 변형과 함께 제공되는 새로운 기능의 혜택을 활용하면서 애플리케이션에서 IsEnabledAsyncFeatureGateAttribute와 같은 API를 계속 사용할 수 있습니다.

{
    "id": "MyVariantFeatureFlag",
    "enabled": true,
    "allocation": {
        "percentile": [
            {
                "variant": "On",
                "from": 10,
                "to": 20
            }
        ],
        "default_when_enabled":  "Off",
        "seed": "Enhanced-Feature-Group"
    },
    "variants": [
        {
            "name": "On"
        },
        {
            "name": "Off",
            "status_override": "Disabled"
        }
    ]
}

위의 예에서는 이 기능이 항상 사용하도록 설정되어 있습니다. 현재 사용자가 계산된 백분위수 범위 10~20에 있으면 On 변형이 반환됩니다. 그렇지 않으면 Off 변형이 반환되고 status_overrideDisabled와 같기 때문에 이제 기능이 사용하지 않도록 설정된 것으로 간주됩니다.

종속성 주입의 변형

다양한 사용자를 위한 다양한 서비스 구현을 표면화하기 위해 종속성 주입과 함께 변형 기능 플래그를 사용할 수 있습니다. 이는 IVariantServiceProvider<TService> 인터페이스를 사용하여 수행됩니다.

IVariantServiceProvider<IAlgorithm> algorithmServiceProvider;
...

IAlgorithm forecastAlgorithm = await algorithmServiceProvider.GetServiceAsync(cancellationToken); 

위 코드 조각에서 IVariantServiceProvider<IAlgorithm>은 종속성 주입 컨테이너에서 IAlgorithm 구현을 검색합니다. 선택한 구현은 다음에 따라 달라집니다.

  • IAlgorithm 서비스가 등록된 기능 플래그입니다.
  • 해당 기능에 할당된 변형입니다.

IVariantServiceProvider<T>IFeatureManagementBuilder.WithVariantService<T>(string featureName)을 호출하여 애플리케이션에서 사용할 수 있게 됩니다. 예는 아래를 참조하세요.

services.AddFeatureManagement() 
        .WithVariantService<IAlgorithm>("ForecastAlgorithm");

위의 호출을 통해 서비스 컬렉션에서 IVariantServiceProvider<IAlgorithm>을 사용할 수 있습니다. IAlgorithm의 구현은 services.AddSingleton<IAlgorithm, SomeImplementation>()과 같은 추가 메서드를 통해 별도로 추가되어야 합니다. IVariantServiceProvider가 사용하는 IAlgorithm의 구현은 ForecastAlgorithm 변형 기능 플래그에 따라 다릅니다. IAlgorithm의 구현이 서비스 컬렉션에 추가되지 않으면 IVariantServiceProvider<IAlgorithm>.GetServiceAsync()null 결과가 있는 작업을 반환합니다.

{
    // The example variant feature flag
    "id": "ForecastAlgorithm",
    "enabled": true,
    "variants": [
        { 
            "Name": "AlgorithmBeta" 
        },
        ...
    ] 
}

변형 서비스 별칭 특성

[VariantServiceAlias("Beta")]
public class AlgorithmBeta : IAlgorithm
{
    ...
}

변형 서비스 공급자는 구현의 형식 이름을 사용하여 할당된 변형과 일치시킵니다. 변형 서비스가 VariantServiceAliasAttribute로 데코레이팅된 경우 이 변형 서비스를 참조하기 위해 구성에서 이 특성에 선언된 이름을 사용해야 합니다.

원격 분석

기능 플래그 변경 내용이 배포되면 해당 변경 내용이 애플리케이션에 미치는 영향을 분석하는 것이 중요한 경우가 많습니다. 예를 들어, 다음과 같은 몇 가지 질문이 발생할 수 있습니다.

  • 내 플래그가 예상대로 사용하거나 사용하지 않도록 설정되어 있나요?
  • 대상 사용자가 예상대로 특정 기능에 액세스하고 있나요?
  • 특정 사용자에게 어떤 변형이 표시되나요?

이러한 형식의 질문은 기능 플래그 평가 이벤트의 발생 및 분석을 통해 답할 수 있습니다. 이 라이브러리는 원격 분석 게시자를 통해 이러한 이벤트 내보내기를 지원합니다. 기능 플래그가 평가될 때마다 하나 이상의 원격 분석 게시자를 등록하여 이벤트를 게시할 수 있습니다.

원격 분석 사용

기본적으로 기능 플래그에는 원격 분석이 내보내지지 않습니다. 특정 기능 플래그에 대한 원격 분석을 게시하려면 플래그가 원격 분석 내보내기에 대해 사용하도록 설정되었음을 반드시 선언해야 합니다.

appsettings.json에 정의된 기능 플래그의 경우 이는 telemetry 속성을 사용하여 수행됩니다.

{
    "feature_management": {
        "feature_flags": [
            {
                "id": "MyFeatureFlag",
                "enabled": true,
                "telemetry": {
                    "enabled": true
                }
            }
        ]
    }
}

위의 appsettings 코드 조각은 원격 분석에 사용하도록 설정된 MyFeatureFlag라는 기능 플래그를 정의합니다. 이는 enabled를 true로 설정하는 telemetry 개체로 표시됩니다. 플래그에 대한 원격 분석을 게시하려면 enabled 속성의 값이 true여야 합니다.

기능 플래그의 telemetry 섹션에는 다음과 같은 속성이 있습니다.

속성 설명
enabled 기능 플래그에 대해 원격 분석을 게시해야 하는지 여부를 지정합니다.
metadata 기능 플래그에 대한 사용자 지정 메타데이터를 평가 이벤트에 연결하는 데 사용할 수 있는 사전으로 모델링된 키-값 쌍의 컬렉션입니다.

사용자 지정 원격 분석 게시자

ITelemetryPublisher를 구현하고 이를 기능 관리자에 등록하면 기능 플래그 원격 분석의 사용자 지정 처리가 가능해집니다. 원격 분석이 사용하도록 설정된 기능 플래그가 평가될 때마다 등록된 원격 분석 게시자는 해당 평가 이벤트를 게시할 기회를 가져옵니다.

public interface ITelemetryPublisher
{
    ValueTask PublishEvent(EvaluationEvent evaluationEvent, CancellationToken cancellationToken);
}

EvaluationEvent 형식은 여기에서 참조할 수 있습니다.

원격 분석 게시자 등록은 AddFeatureManagement()를 호출할 때 완료됩니다. 다음은 MyTelemetryPublisher라는 ITelemetryPublisher 구현을 사용하여 원격 분석을 내보내도록 기능 관리를 설정하는 예입니다.

builder.services
    .AddFeatureManagement()
    .AddTelemetryPublisher<MyTelemetryPublisher>();

Application Insights 원격 분석 게시자

Microsoft.FeatureManagement.Telemetry.ApplicationInsights 패키지는 기능 플래그 평가 데이터를 Application Insights로 보내는 기본 제공된 원격 분석 게시자 구현을 제공합니다. 이를 활용하려면 아래와 같이 패키지에 대한 참조를 추가하고 Application Insights 원격 분석 게시자를 등록합니다.

builder.services
    .AddFeatureManagement()
    .AddTelemetryPublisher<ApplicationInsightsTelemetryPublisher>();

참고 항목

기본 Microsoft.FeatureManagement 패키지에는 이 원격 분석 게시자가 포함되어 있지 않습니다.

사용 예는 EvaluationDataToApplicationInsights 예에서 찾을 수 있습니다.

전제 조건

이 원격 분석 게시자는 이미 설정되고 애플리케이션 서비스로 등록된 Application Insights에 따라 다릅니다. 예를 들어, 이는 예 애플리케이션의 여기에서 수행됩니다.

캐싱

기능 상태는 IConfiguration 시스템에서 제공됩니다. 모든 캐싱 및 동적 업데이트는 구성 공급자가 처리해야 합니다. 기능 관리자는 기능이 사용하도록 설정되도록 선택할 때마다 기능 상태의 최신 값을 IConfiguration에 요청합니다.

스냅샷

요청 수명 동안 기능 상태를 일관되게 유지해야 하는 시나리오가 있습니다. 요청 중에 끌어오는 IConfiguration 원본이 업데이트되면 표준 IFeatureManager에서 반환된 값이 변경될 수 있습니다. 이는 IFeatureManagerSnapshot을 사용하여 방지할 수 있습니다. IFeatureManagerSnapshotIFeatureManager와 동일한 방식으로 검색할 수 있습니다. IFeatureManagerSnapshotIFeatureManager의 인터페이스를 구현하지만 요청 중에 기능의 첫 번째 평가 상태를 캐시하고 전체 기간 동안 기능의 동일한 상태를 반환합니다.

사용자 지정 기능 공급자

사용자 지정 기능 공급자를 구현하면 개발자는 데이터베이스 또는 기능 관리 서비스와 같은 원본에서 기능 플래그를 끌어올 수 있습니다. 기본적으로 사용되는 포함된 기능 공급자는 .NET Core의 구성 시스템에서 기능 플래그를 끌어옵니다. 이를 통해 appsettings.json 파일이나 Azure App Configuration과 같은 구성 공급자에서 기능을 정의할 수 있습니다. 기능 정의를 읽는 위치를 완벽하게 제어하기 위해 이 동작을 대체할 수 있습니다.

기능 정의 로드를 사용자 지정하려면 IFeatureDefinitionProvider 인터페이스를 구현해야 합니다.

public interface IFeatureDefinitionProvider
{
    Task<FeatureDefinition> GetFeatureDefinitionAsync(string featureName);

    IAsyncEnumerable<FeatureDefinition> GetAllFeatureDefinitionsAsync();
}

IFeatureDefinitionProvider 구현을 사용하려면 기능 관리를 추가하기 전에 서비스 컬렉션에 추가해야 합니다. 다음 예에서는 InMemoryFeatureDefinitionProvider라는 IFeatureDefinitionProvider 구현을 추가합니다.

services.AddSingleton<IFeatureDefinitionProvider, InMemoryFeatureDefinitionProvider>()
        .AddFeatureManagement()

다음 단계

애플리케이션에서 기능 플래그를 사용하는 방법을 알아보려면 다음 빠른 시작을 계속 진행합니다.

기능 필터를 사용하는 방법을 알아보려면 다음 자습서를 계속 진행합니다.

변형 기능 플래그를 사용하여 실험을 실행하는 방법을 알아보려면 다음 자습서를 계속 진행합니다.