이 가이드에서는 대상 지정 필터를 사용하여 Node.js 애플리케이션의 대상 그룹에 기능을 롤아웃합니다. 대상 필터에 대한 자세한 내용은 대상 그룹층을 대상 그룹으로 기능 롤아웃를 참조하세요.
필수 조건
- 활성 구독이 있는 Azure 계정. 체험 계정 만들기
- App Configuration 저장소는 스토어를 만들기 위한 자습서에서 보여집니다.
- 대상 지정 필터가 있는 베타 기능 플래그입니다. 기능 플래그를 만듭니다.
- Node.js의 LTS 버전.
기능 플래그를 사용하여 웹 애플리케이션 만들기
이 섹션에서는 베타 기능 플래그 를 사용하여 웹 페이지의 베타 버전에 대한 액세스를 제어하는 웹 애플리케이션을 만듭니다.
Node.js Express 프로젝트 설정
targeting-filter-tutorial라는 폴더를 만들고 프로젝트를 초기화합니다.mkdir targeting-filter-tutorial cd targeting-filter-tutorial npm init -y다음 패키지를 설치합니다.
npm install @azure/app-configuration-provider npm install @microsoft/feature-management npm install expressapp.js 새 파일을 만들고 다음 코드를 추가합니다.
const express = require("express"); const server = express(); const port = "8080"; server.listen(port, () => { console.log(`Server is running at http://localhost:${port}`); });
Azure App Configuration에 연결
app.js 업데이트하고 다음 코드를 추가합니다.
// Existing code ... const appConfigEndpoint = process.env.AZURE_APPCONFIG_ENDPOINT; const { DefaultAzureCredential } = require("@azure/identity"); const { load } = require("@azure/app-configuration-provider"); const { FeatureManager, ConfigurationMapFeatureFlagProvider } = require("@microsoft/feature-management"); let appConfig; let featureManager; async function initializeConfig() { // Load feature flags from App Configuration. appConfig = await load(appConfigEndpoint, new DefaultAzureCredential(), { featureFlagOptions: { enabled: true, refresh: { enabled: true } } }); // Create feature manager with feature flag provider that accesses feature flags from App Configuration. featureManager = new FeatureManager( new ConfigurationMapFeatureFlagProvider(appConfig)); } // Use a middleware to refresh the configuration before each request. server.use((req, res, next) => { appConfig.refresh(); next(); }); // Existing code ...Azure App Configuration에 연결하여 기능 플래그를 로드하고, 자동 새로 고침을 사용하도록 설정하고, 나중에 기능 플래그에 액세스하기 위한 개체를 만듭니
FeatureManager다. 각 요청 전에 구성을 새로 고치기 위해 미들웨어가 추가됩니다.구성이 성공적으로 초기화된 후에만 Express 서버가 시작되도록 코드를 업데이트합니다.
// Existing code ... initializeConfig() .then(() => { // Start the express server. server.listen(port, () => { console.log(`Server is running at http://localhost:${port}`); }); })
기능 플래그 사용
app.js 파일에 다음 코드를 추가하여 Express 서버에 대한 경로 처리기를 구성합니다. 서버는 베타 기능 플래그가 사용되는지 여부에 따라 다른 콘텐츠를 제공합니다.
// Existing code ...
server.get("/", async (req, res) => {
const isBetaEnabled = await featureManager.isEnabled("Beta");
const [title, message] = isBetaEnabled
? ["Beta Page", "This is a beta page."]
: ["Home Page", "Welcome."];
res.send(
`<!DOCTYPE html>
<html>
<head><title>${title}</title></head>
<body style="display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0;">
<h1 style="text-align: center; font-size: 5rem;">${message}</h1>
</body>
</html>`
);
});
initializeConfig()
// Existing code ...
웹 애플리케이션에 대한 대상 지정 사용
대상 지정을 사용하도록 설정된 기능을 평가할 때는 대상 지정 컨텍스트가 필요합니다. 기능 평가를 위해 이 컨텍스트를 명시적으로 제공하려면 메서드에 매개 변수 featureManager.isEnabled 로 전달할 수 있습니다.
const isBetaEnabled = await featureManager.isEnabled("Beta", { userId: "UserA", groups: ["Group1"] });
웹 애플리케이션에서 대상 지정 컨텍스트는 ITargetingContextAccessor 인터페이스를 구현하여 주변 컨텍스트로 제공할 수도 있습니다. 앰비언트 대상 지정 컨텍스트는 대상 지정 정보가 각 featureManager.isEnabled() 호출에 명시적으로 전달하지 않고도 현재 HTTP 요청과 같은 환경에서 자동으로 검색됨을 의미합니다.
이 자습서에서는 앰비언트 대상 지정 컨텍스트를 사용합니다.
Express 서버 선언 다음에 다음 코드를 추가합니다. 현재 요청을 저장하는 데
AsyncLocalStorage이(가) 사용되어, 기능 관리자가 대상 지정 컨텍스트 접근자 콜백을 통해 대상 지정 컨텍스트를 자동으로 검색할 수 있도록 합니다. 자세한 내용은 요청 컨텍스트에 AsyncLocalStorage 사용을 참조하세요.const express = require("express"); const server = express(); const port = 8080; const { AsyncLocalStorage } = require("async_hooks"); const requestAccessor = new AsyncLocalStorage(); // Use a middleware to store request context. server.use((req, res, next) => { // Store the request in AsyncLocalStorage for this request chain. requestAccessor.run(req, () => { next(); }); }); // Create a targeting context accessor that retrieves user data from the current request. const targetingContextAccessor = { getTargetingContext: () => { // Get the current request from AsyncLocalStorage. const request = requestAccessor.getStore(); if (!request) { return undefined; } const { userId, groups } = request.query; return { userId: userId, groups: groups ? groups.split(",") : [] }; } }; // Existing code ...FeatureManager을(를) 생성할 때 대상 지정 컨텍스트 접근자를FeatureManagerOptions에 전달합니다.featureManager = new FeatureManager( new ConfigurationMapFeatureFlagProvider(appConfig), { targetingContextAccessor: targetingContextAccessor });
이전 단계를 완료한 후 app.js 파일에 다음 완전한 구현이 포함되어야 합니다.
const express = require("express");
const server = express();
const port = 8080;
const { AsyncLocalStorage } = require("async_hooks");
const requestAccessor = new AsyncLocalStorage();
// Use a middleware to store request context
server.use((req, res, next) => {
// Store the request in AsyncLocalStorage for this request chain
requestAccessor.run(req, () => {
next();
});
});
// Create a targeting context accessor that retrieves user data from the current request
const targetingContextAccessor = {
getTargetingContext: () => {
// Get the current request from AsyncLocalStorage
const request = requestAccessor.getStore();
if (!request) {
return undefined;
}
const { userId, groups } = request.query;
return {
userId: userId,
groups: groups ? groups.split(",") : []
};
}
};
const appConfigEndpoint = process.env.AZURE_APPCONFIG_ENDPOINT;
const { DefaultAzureCredential } = require("@azure/identity");
const { load } = require("@azure/app-configuration-provider");
const { FeatureManager, ConfigurationMapFeatureFlagProvider } = require("@microsoft/feature-management");
let appConfig;
let featureManager;
async function initializeConfig() {
// Load feature flags from App Configuration.
appConfig = await load(appConfigEndpoint, new DefaultAzureCredential(), {
featureFlagOptions: {
enabled: true,
refresh: {
enabled: true
}
}
});
// Create feature manager with feature flag provider that accesses feature flags from App Configuration and targeting context accessor.
featureManager = new FeatureManager(
new ConfigurationMapFeatureFlagProvider(appConfig),
{
targetingContextAccessor: targetingContextAccessor
});
}
// Use a middleware to refresh the configuration before each request
server.use((req, res, next) => {
appConfig.refresh();
next();
});
server.get("/", async (req, res) => {
const isBetaEnabled = await featureManager.isEnabled("Beta");
const [title, message] = isBetaEnabled
? ["Beta Page", "This is a beta page."]
: ["Home Page", "Welcome."];
res.send(
`<!DOCTYPE html>
<html>
<head><title>${title}</title></head>
<body style="display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0;">
<h1 style="text-align: center; font-size: 5rem;">${message}</h1>
</body>
</html>`
);
});
// Initialize the configuration and start the server
initializeConfig()
.then(() => {
// Start the express server.
server.listen(port, () => {
console.log(`Server is running at http://localhost:${port}`);
});
})
대상 지정 필터 작동 중
AZURE_APPCONFIG_ENDPOINT 환경 변수를 Azure Portal의 저장소 개요 아래에 있는 App Configuration 저장소의 엔드포인트로 설정합니다.
Windows 명령 프롬프트를 사용하는 경우 다음 명령을 실행하고, 명령 프롬프트를 다시 시작하여 변경 내용을 적용합니다.
setx AZURE_APPCONFIG_ENDPOINT "<endpoint-of-your-app-configuration-store>"PowerShell을 사용하는 경우 다음 명령을 실행합니다.
$Env:AZURE_APPCONFIG_ENDPOINT = "<endpoint-of-your-app-configuration-store>"macOS 또는 Linux를 사용하는 경우 다음 명령을 실행합니다.
export AZURE_APPCONFIG_ENDPOINT='<endpoint-of-your-app-configuration-store>'애플리케이션을 실행합니다.
node app.js브라우저를 열고
localhost:8080로 이동합니다. 앱의 기본 보기가 표시됩니다.
-
- URL에 쿼리 매개 변수로 추가하여
userId사용자 ID를 지정합니다.localhost:8080/?userId=test@contoso.com방문하십시오. 대상 사용자로 지정되었으므로test@contoso.com베타 페이지가 표시됩니다.
- URL에 쿼리 매개 변수로 추가하여
localhost:8080/?userId=testuser@contoso.com방문하십시오. 제외된 사용자로 지정되어 있으므로testuser@contoso.com베타 페이지를 볼 수 없습니다.
다음 단계
기능 필터에 대해 자세히 알아보려면 다음 문서로 계속하세요.
JavaScript 기능 관리 라이브러리의 전체 기능 개요를 보려면 다음 문서로 계속하세요.