Amazon Web Services 한국 블로그

새로운 기능 — Amazon CloudWatch Evidently 기반 A/B 테스트 및 기능 관리

개발자로서 Amazon CloudWatch Evidently의 출시를 발표하게 되어 기쁩니다. 이는 개발자가 애플리케이션 코드에 실험 및 기능 관리를 쉽게 도입할 수 있게 해주는 새로운 Amazon CloudWatch 기능입니다. CloudWatch Evidently는 유사하지만 서로 다른 두 가지 사용 사례에 사용할 수 있습니다. 즉, 기능 플래그라고도 하는 다크 출시 구현과 A/B 테스트입니다.

기능 플래그는 코드를 배포할 필요 없이 기능을 활성화하거나 비활성화할 수 있는 소프트웨어 개발 기술입니다. 이 기능은 릴리스에서 기능 배포를 분리합니다. 코드의 기능은 실제 릴리스 전에 배포됩니다. 이는 if-then-else 문 뒤에 숨겨져 있습니다. 런타임 시 애플리케이션 코드는 원격 서비스를 쿼리합니다. 이 서비스는 새 기능에 노출된 사용자의 비율을 결정합니다. 일부 특정 고객(예: 베타 테스터)에 대한 애플리케이션 동작을 구성할 수도 있습니다.

기능 플래그를 사용하면 출시 전에 새 코드를 배포할 수 있습니다. 그런 다음 일부 고객에게 점진적으로 새로운 기능을 도입할 수 있습니다. 출시할 때 기술 지표 및 비즈니스 지표를 모니터링합니다. 모든 것이 순조롭게 진행되면 트래픽을 늘려 새 기능을 추가 사용자에게 노출할 수 있습니다. 문제가 발생하면 한 번의 클릭 또는 API 호출로 서버 측 라우팅을 수정하여 고객에게 이전의 유효한 기능만 제공할 수 있습니다. 이렇게 하면 배포를 롤백할 필요 없이 사용자 환경을 되돌릴 수 있습니다.

A/B 테스트는 기능 플래그와 유사점이 많지만 다른 용도로도 사용합니다. A/B 테스트는 여러 변형이 있는 무작위 실험으로 구성됩니다. A/B 테스트를 사용하면, 일반적으로 변형 A에 대한 대상의 반응을 변형 B를 기준으로 테스트하고 둘 중 어느 것이 더 효과적인지 판단하여 단일 기능의 여러 버전을 비교할 수 있습니다. 예를 들어 전자 상거래 웹 사이트(Amazon에서 잘 알고 있는 시나리오)를 상상해 보겠습니다. 결제 버튼에 대해 다양한 모양이나 크기 또는 색상을 실험한 다음, 어떤 변형이 수익에 가장 큰 영향을 미치는지 측정할 수 있습니다.

A/B 테스트에 필요한 인프라는 기능 플래그에 필요한 인프라와 유사합니다. 앱에 여러 시나리오를 배포하고 고객 트래픽의 일부를 한 시나리오 또는 다른 시나리오로 라우팅하는 방법을 제어합니다. 그런 다음 심층 분석 통계 분석으로 변형의 영향을 비교합니다. CloudWatch Evidently는 고급 통계 지식 없이도 실험 결과를 해석하고 그에 따른 조치를 하는 데 도움을 줍니다. 실험이 진행되는 동안 언제든지 p-값신뢰 구간 등 Evidently 통계 엔진에서 제공하는 인사이트를 의사 결정에 사용할 수 있습니다.

Amazon에서는 기능 플래그를 광범위하게 사용하여 출시를 제어하고 A/B 테스트를 통해 새로운 아이디어를 실험합니다. 우리는 수년간 개발자 도구와 라이브러리를 구축하고 실험 서비스를 대규모로 유지 및 운영해 왔습니다. 이제 여러분은 우리의 경험을 통해 혜택을 누릴 수 있습니다.

CloudWatch Evidently는 기능 플래그에 ‘출시(launches)’라는 용어를 사용하고 A/B 테스트에는 ‘실험(experiments)’이라는 용어를 사용합니다. 이는 이 문서의 나머지 부분에서도 마찬가지로 적용됩니다.

애플리케이션 개발자의 관점에서 작동 방식을 살펴보겠습니다.

출시의 활용
이 데모에서는 간단한 방명록 웹 애플리케이션을 사용합니다. 지금까지 방명록 페이지는 읽기 전용이며 댓글은 백엔드에서만 입력할 수 있습니다. 저는 고객이 방명록 페이지에 의견을 입력할 수 있는 새로운 기능을 개발했습니다. 이 새로운 기능을 일주일에 걸쳐 점진적으로 출시하고, 변경 사항이 중요한 기술 또는 비즈니스 지표(예: p95 대기 시간, 고객 참여, 페이지 뷰 등)에 영향을 미치는 경우 되돌릴 수 있는 기능을 유지하려고 합니다. 사용자가 인증되고, 사용자 ID를 기준으로 사용자를 분류합니다.

출시 전:
Evidently - 실험 중지
출시 후:
Evidently - 실험 진행

프로젝트 만들기
먼저 Evidently를 구성해 보겠습니다. AWS 관리 콘솔을 열고 CloudWatch Evidently로 이동합니다. 그런 다음 Create a project(프로젝트 만들기)를 선택합니다.

Evidently - 프로젝트 만들기

프로젝트 이름(Project name)과 설명(Description)을 입력합니다.

Evidently를 사용하면 CloudWatch Logs 또는 S3에 선택적으로 이벤트를 저장할 수 있으므로 Amazon Redshift와 같은 시스템으로 이동하여 분석할 수 있습니다. 이 데모에서는 이벤트를 저장하지 않기로 했습니다. 완료되면 Create project(프로젝트 만들기)를 선택합니다.

Evidently - 프로젝트 만들기 두 번째

기능 추가
다음으로 Add feature(기능 추가)를 선택하여 이 프로젝트에 대한 기능을 만듭니다. Feature name(기능 이름)Feature description(기능 설명)을 입력합니다. 다음으로 Feature variations(기능 변형)를 정의합니다. 이 예에는 두 가지 변형이 있으며 저는 부울 유형을 사용합니다. true는 방명록이 편집 가능함을 나타내고, false는 읽기 전용임을 나타냅니다. 변형 유형은 boolean, double, long 또는 string일 수 있습니다.

Evidently - 기능 만들기재정의(Overrides)를 할 수 있습니다. 재정의를 사용하면 선택한 사용자에 대한 변형을 미리 정의할 수 있습니다. 저의 베타 테스터인 ‘seb’라는 사용자가 항상 편집 가능한 변형을 받으셨으면 좋겠습니다.

Evidently - 기능 만들기 - 재정의콘솔은 JavaScript 및 Java 코드 조각을 공유하여 애플리케이션에 추가합니다.

Evidently - 코드 조각코드 조각에 관해 이야기가 나왔으니 코드 수준에서 변경 사항을 살펴보겠습니다.

내 애플리케이션 코드 기능 구현
저는 이 데모에 대해 간단한 웹 애플리케이션을 사용합니다. 이 애플리케이션을 JavaScript로 코딩했습니다. JavaScript용 AWS SDKWebpack을 사용하여 코드를 패키징합니다. 또한 JQuery로 DOM을 조작하여 요소를 숨기거나 표시합니다. 이 예제를 모든 사례에서 포함할 수 있도록 표준 JavaScript와 최소한의 프레임워크 수를 사용하도록 이 애플리케이션을 설계했습니다. 실제 프로젝트에 대해 React 또는 Angular와 같은 더 높은 수준의 도구와 프레임워크를 얼마든지 사용할 수 있습니다.

먼저 Evidently 클라이언트를 초기화합니다. 다른 AWS 서비스와 마찬가지로 인증을 위해 액세스 키와 비밀 액세스 키를 제공해야 합니다. 인증 부분은 잠시 남겨 두겠습니다. 이 문서 끝에 사용 가능한 옵션에 관해 논의하는 메모를 추가했습니다. 이 예제에서는 Amazon Cognito Identity Pools를 사용하여 임시 자격 증명을 받습니다.

// Initialize the Amazon CloudWatch Evidently client
const evidently = new AWS.Evidently({
    endpoint: EVIDENTLY_ENDPOINT,
    region: 'us-east-1',
    credentials: fromCognitoIdentityPool({
        client: new CognitoIdentityClient({ region: 'us-west-2' }),
        identityPoolId: IDENTITY_POOL_ID
    }),
});

이 클라이언트를 통해 내 코드는 EvaluateFeature API를 호출하여 고객에게 표시할 변형에 대한 결정을 내릴 수 있습니다. entityID는 고객을 분류하기 위한 문자열 기반 속성입니다. 예를 들면 세션 ID, 고객 ID 또는 이런 것의 해시(더 좋은 경우임) 등입니다. FeatureName 파라미터에는 평가할 기능의 이름이 포함되어 있습니다. 이 예제에서는 EditableGuestBook 값을 전달합니다.

const evaluateFeature = async (entityId, featureName) => {

    // API request structure
    const evaluateFeatureRequest = {
        // entityId for calling evaluate feature API
        entityId: entityId,
        // Name of my feature
        feature: featureName,
        // Name of my project
        project: "AWSNewsBlog",
    };

    // Evaluate feature
    const response = await evidently.evaluateFeature(evaluateFeatureRequest).promise();
    console.log(response);
    return response;
}

응답에는 서버 측에서 정의된 트래픽 규칙에 따라 Evidently의 배정 결정이 포함됩니다.

{
 details: {
   launch: "EditableGuestBook", group: "V2"},
   reason: "LAUNCH_RULE_MATCH", 
   value: {boolValue: false},
   variation: "readonly"
}}

마지막 부분은 위에서 받은 값(value)에 따라 사용자 인터페이스의 일부를 숨기거나 표시하는 것으로 구성됩니다. 기본적인 jQuery DOM 조작을 사용하면 다음과 같습니다.

window.aws.evaluateFeature(entityId, 'EditableGuestbook').then((response, error) => {
    if (response.value.boolValue) {
        console.log('Feature Flag is on, showing guest book');
        $('div#guestbook-add').show();
    } else {
        console.log('Feature Flag is off, hiding guest book');
        $('div#guestbook-add').hide();
    }
});

출시 만들기
이제 서버 측에서 기능이 정의되고 클라이언트 코드의 기능이 구현되었으므로, 코드를 배포하고 고객에게 공개합니다. 나중에 이 기능을 출시하기로 결정할 수도 있습니다. 콘솔로 돌아가서 내 프로젝트를 선택한 다음 Create Launch(출시 만들기)를 선택합니다. 내 출시에 대해 Launch name(출시 이름)Launch decription(출시 설명)을 선택합니다. 그런 다음 출시하려는 기능을 선택합니다.

Evidently - 출시 만들기Launch Configuration(출시 구성) 섹션에서 각 변형에 전송되는 트래픽 양을 구성합니다. 출시를 여러 단계로 예약할 수도 있습니다. 이렇게 하면 일정에 따라 서로 다른 라우팅 단계를 계획할 수 있습니다. 예를 들어 첫날에는 트래픽의 10%를 새 기능으로 보내고, 둘째 날에는 20%를 보내는 식으로 할 수 있습니다. 이 예에서는 트래픽을 50/50으로 분할하기로 했습니다.

Evidently - 출시 구성마지막으로 변형의 성능을 측정하기 위해 최대 3개의 지표를 정의할 수 있습니다. 지표는 데이터 이벤트에 규칙을 적용하면 정의됩니다.

Evidently - 사용자 지정 지표다시 말하지만, Evidently에서 PutProjectEvents API를 사용하여 이러한 지표를 전송하려면 내 코드의 기능을 구현해야 합니다. 내 출시가 만들어지면 EvaluateFeature API는 entityId(이 데모의 사용자)의 서로 다른 값에 대해 서로 다른 값을 반환합니다.

언제든지 라우팅 구성을 변경할 수 있습니다. 또한 모니터링 대시보드에 액세스하여 내 변형의 배포와 각 변형에 대한 지표를 관찰할 수 있습니다.

Evidently - 출시 모니터링이 게시물을 작성하기 위해 이 출시를 방금 만들었으므로 여러분들의 실제 출시 그래프는 제 것보다 더 많은 데이터를 확보할 것입니다.

A/B 테스트
A/B 테스트도 비슷합니다. 테스트할 기능을 만들고 Experiment(실험)를 만듭니다. 트래픽의 일부를 변형 1로 라우팅한 다음 다른 부분을 변형 2로 라우팅하도록 실험을 구성합니다. 실험을 시작할 준비가 되면 Start experiment(실험 시작)을 선택합니다.

Evidently - 실험 시작

이 실험에서는 사용자 지정 지표를 보내려고 합니다. 예를 들면

// pageLoadTime custom metric
const timeSpendOnHomePageData = `{
   "details": {
      "timeSpendOnHomePage": ${timeSpendOnHomePageValue}
   },
   "userDetails": { "userId": "${randomizedID}", "sessionId": "${randomizedID}" }
}`;

const putProjectEventsRequest: PutProjectEventsRequest = {
   project: 'AWSNewsBlog',
   events: [
    {
        timestamp: new Date(),
        type: 'aws.evidently.custom',
        data: JSON.parse(timeSpendOnHomePageData)
    },
   ],
};

this.evidently.putProjectEvents(putProjectEventsRequest).promise().then(res =>{})

Results(결과) 페이지로 전환하면 Event Count(이벤트 수), Total Value(전체 값), Average(평균), Improvement(개선)(95% 신뢰 구간), Statistical significance(통계적 유의성)에 대한 원시 값과 그래프 데이터가 표시됩니다. 통계적 유의성은 변동이 기준선과 비교하여 지표에 얼마나 영향을 미치는지 나타냅니다.

이러한 결과는 실험 전반에 걸쳐 생성되며 신뢰 구간과 통계적 유의성은 확인 시기와 관계없이 항상 유효합니다. 또한 실험이 끝나면 Evidently는 실험의 Bayesian 관점을 생성하여 변동 간의 차이가 존재할 가능성에 대한 정보를 제공합니다.

다음 두 스크린샷은 시간 경과에 따른 두 지표의 평균값과 95% 신뢰 구간 내 지표에 대한 개선 사항에 대한 그래프를 보여줍니다.

Evidently - 실험 모니터링 - 평균값Evidently - 실험 모니터링 - 개선 사항

추가 고려 사항
마무리하기 전에 몇 가지 추가 고려 사항을 알려드리고 싶습니다.

첫째, 프런트엔드 애플리케이션 개발의 맥락에서 Evidently를 시연했다는 점을 이해하는 것이 중요합니다. 그러나 Evidently는 프런트엔드 웹 또는 모바일, 백엔드 API 또는 기계 학습(ML) 등 모든 애플리케이션 유형에서 사용할 수 있습니다. 예를 들어 Evidently를 사용하여 두 가지 기계 학습 모델을 배포하고, 위에서 설명한 실험을 수행할 수 있습니다.

둘째, 다른 AWS 서비스와 마찬가지로 Evidently API는 모든 AWS SDK에서 사용할 수 있습니다. 그러므로 C++, Go, Java, JavaScript(및 Typescript), .Net, NodeJS, PHP, Python, Ruby와 같은 9개 프로그래밍 언어에서 EvaluateFeature 및 기타 API를 사용할 수 있습니다. Rust 및 Swift용 AWS SDK는 제작 중입니다.

셋째, 여기서 시연한 프런트엔드 애플리케이션의 경우 Evidently API에 대한 호출을 인증하는 방법을 고려하는 것이 중요합니다. 액세스 키와 비밀 액세스 키를 하드 코딩하는 것은 불가합니다. 프런트엔드 시나리오의 경우 Amazon Cognito Identity Pools를 사용하여 사용자 자격 증명 토큰을 임시 액세스 및 비밀 키로 교환하는 것이 좋습니다. 사용자 자격 증명 토큰은 Cognito 사용자 풀 또는 서드 파티 인증 시스템(예: Active Directory, Login with Amazon, Login with Facebook, Login with Google, Signin with Apple, OpenID Connect 또는 SAML을 준수하는 모든 시스템)에서 얻을 수 있습니다. Cognito Identity Pools는 익명 액세스도 허용합니다. 자격 증명 토큰이 필요하지 않습니다. Cognito Identity Pools는 IAM 역할과 연결된 임시 토큰을 제공합니다. 정책에서 evidently:EvaluateFeature API에 대한 호출을 허용해야 합니다.

마지막으로, 기능 플래그를 사용할 때는 스프린트 기간 중에 코드 정리 시간을 계획하세요. 기능이 출시되면 EvaluateFeature API 호출 및 처음에 기능을 숨기는 데 사용된 if-then-else 로직을 제거해야 할 수도 있습니다.

요금 및 가용성
Amazon Cloudwatch Evidently는 미국 동부(버지니아 북부), 미국 동부(오하이오), 미국 서부(오레곤), 아시아 태평양(싱가포르), 아시아 태평양(시드니), 아시아 태평양(도쿄), EU(아일랜드), EU(프랑크푸르트), EU(스톡홀름)의 9개 AWS 리전에서 정식 출시되었습니다. 평소와 같이 앞으로 몇 달 안에 점차 다른 지역으로 확장할 것입니다.

요금은 종량제(pay-as-you-go)이며 최소 또는 기본 요금이 없습니다. CloudWatch Evidently는 Evidently 이벤트 및 Evidently 분석 단위를 기반으로 계정에 요금을 부과합니다. Evidently 분석 단위는 Evidently에서 생성한 규칙에 따라 Evidently 이벤트에서 생성됩니다. 예를 들어 사용자 결제 이벤트는 두 개의 Evidently 분석 단위(결제 값과 장바구니의 항목 수)를 생성할 수 있습니다. 요금에 대한 자세한 내용은 Amazon CloudWatch 요금을 참조하세요.

지금 바로 CloudWatch Evidently로 실험을 시작해 보세요!

— seb