Windows Workflow Foundation 규칙 엔진 소개

2006. 12. 5. 09:57 IT 및 개발/.NET FX & Visual C#
이 기사에서는 Windows WF(Workflow Foundation)의 규칙 엔진 기능에 대한 개요를 제공합니다. WF에서 조건과 규칙 집합이 어떻게 사용되는지와 전달 체인, 추적 및 트레이싱을 비롯한 규칙 모음의 동작에 대해서 설명합니다.

참고 이 기사는 베타 2를 기준으로 작성되었으므로 여기 설명된 작업을 다음 버전의 Windows Workflow Foundation에서 수행하려면 변경이 필요할 수 있습니다.

소개

Microsoft는 Windows WF(Workflow Foundation)의 출시에 맞춰 WinFX 개발자 플랫폼에 새로운 규칙 기능을 도입했습니다. 새로 도입된 이 기능은 작업 실행 동작을 제어하는 간단한 조건에서부터 모든 기능을 갖춘 전달 체인 규칙 엔진에 의해 실행되는 복잡한 규칙 집합에 이르기까지 다양합니다.

규칙 기능을 사용하면 전체 비즈니스 프로세스 범위 내에서 응용 프로그램 논리 단위의 선언적 모델링이 가능합니다. 규칙 엔진 기술에 대한 샘플 시나리오로 순서 검증, 가격 계산, 홍보 강화, 예외 프로세스 관리, 클래임 판결 및 관리를 들 수 있습니다.

이 기술을 개발한 주요 목적은 워크플로와 규칙이 완전하게 통합된 환경을 제공하기 위해서입니다. 일반적으로 업계 전체에서 규칙과 워크플로는 전혀 다른 기술로 취급되고 있으며 대개 서로 다른 공급업체에 의해 제공됩니다. 타사 규칙 엔진이 워크플로 및 BPM(비즈니스 프로세스 관리) 공급자로부터 기본 제공되거나 통합되는 경우도 종종 있지만 개발자나 관리자 환경이 복잡하고 어려운 것은 확실합니다.

Microsoft는 개발자가 워크플로의 모든 지점에서 규칙을 쉽게 통합할 수 있도록 WF에서 워크플로와 규칙 모델링 간 원활한 연계가 가능한 개발자 환경을 제공하는 데 주력했습니다. 이제 개발자들은 자신의 결정이 통합에 미칠 영향을 걱정하지 않고 워크플로 모델, 규칙, 코드 등 논리를 모델링할 대상을 결정할 수 있습니다. 그러면서도 워크플로 범위 밖에서 규칙을 실행할 수 있는 기능은 그대로 유지됩니다.

두 번째 주요 목적은 개발자들이 규칙 정의에 사용할 수 있는 손쉬운 모델을 제공하기 위한 것입니다. 지금까지 규칙 기술은 뛰어난 전문성을 갖춘 규칙 전문가 그룹에서만 사용하는 틈새 기술이었습니다. 도구의 개선을 통해 규칙 사용자의 범위가 넓어지긴 했지만 모델에 따라 기반 엔진의 구현 기술에 대한 전문가급 지식이 필요한 경우도 종종 있습니다. Microsoft는 플랫폼에서 규칙 기능을 제공함으로써 대다수 .NET 개발자 커뮤니티는 물론 궁극적으로 비개발자들까지도 사용할 수 있는 모델을 채택했습니다. 어떤 기술이든 해당 분야에 대한 일정 수준의 전문 지식이 필요하겠지만 Microsoft의 목표는 모든 .NET 개발자들이 규칙 모델을 빠르게 습득하여 이를 자신의 응용 프로그램에 쉽게 통합할 수 있도록 하는 것입니다.

WF는 사용이 편리한 모델을 제공할 뿐 아니라 전달 체인 평가와 정확한 평가 제어가 필요한 복잡한 규칙 시나리오를 지원하는 강력한 평가 엔진도 제공합니다. 이러한 기능은 다양하게 확장이 가능한 형태로 제공되기 때문에 개발자들은 Microsoft 플랫폼을 기반으로 다양한 시나리오를 지원할 수 있는 규칙 기능을 제공할 수 있습니다.

이 문서에서는 WF에서 제공하는 규칙 기능의 기술적 측면을 소개하고 사용 가능한 기능 및 이러한 기능의 사용법에 대해서 설명합니다. 이 문서의 마지막에는 WF의 규칙 기능을 알아보는 데 참조할 수 있는 추가적인 자료 목록이 나와 있습니다.

Windows Workflow Foundation의 규칙 개요

규칙 기술은 WF에서 작업에 대한 조건과 정책 작업의 전달 체인 규칙 집합이라는 두 가지 주요 방식으로 사용됩니다. 전달 체인에 대해서는 이 문서의 뒷부분에서 설명하겠지만 간단히 말하자면 전달 체인이란 한 규칙의 작업이 다른 종속 규칙을 다시 평가하도록 만드는 기능입니다.

작업 조건

조건은 WF에 제공하는 다음과 같은 네 가지 작업에서 사용됩니다.

  • IfElseBranch
  • While
  • 복제기
  • CAG(ConditionedActivityGroup)

조건은 작업의 실행 동작을 제어하는 데 사용됩니다. 예를 들어 지정된 IfElseBranch의 실행 여부를 결정하는 데 사용될 수 있습니다. 조건은 코드 내에 구성된 처리기가 있는 CodeConditionsRuleConditionReference의 형태로 지정할 수 있습니다. RuleConditionReference는 워크플로 프로젝트의 워크플로와 연결된 .rules 파일의 RuleCondition 정의를 가리킵니다. 그림 1에서는 Visual Studio에서의 사용 예를 보여 줍니다.


그림 1. WF 규칙 조건 작성

규칙 조건 추가

IfElse 작업 내부의 IfElseBranch 작업에 규칙 조건을 추가하는 단계는 다음과 같습니다.

  1. IfElseBranch와 같이 조건이 있는 작업을 선택하면 Properties 표에 Condition 속성이 표시됩니다.
  2. Condition 속성에 대한 드롭다운에서 CodeCondition 또는 RuleConditionReference를 선택할 수 있습니다.
  3. RuleConditionReference를 선택할 경우 ConditionNameExpression 속성이 표시되도록 Condition 속성을 확장할 수 있습니다.
  4. 조건 이름을 입력한 후 Expression 속성의 줄임표를 클릭하여 Rule Condition Editor를 시작합니다. 이 편집기에서는 개발자가 Intellisense와 같은 지원을 통해 텍스트 형태로 조건을 입력할 수 있습니다. 입력한 텍스트는 RuleCondition의 연결된 개체 모델 표현으로 구문 분석됩니다.
  5. OK를 선택하면 RuleCondition 정의가 프로젝트에 추가되는 <WorkflowName>.rules 파일로 serialize됩니다.

편집기에 this.를 입력하면 워크플로의 필드 또는 속성을 참조할 수 있습니다. 점을 입력하면 워크플로의 멤버를 선택할 수 있는 Intellisense와 비슷한 메뉴가 나타납니다. 멤버를 직접 입력할 수도 있습니다. this.order.Total과 같은 중첩 호출도 가능합니다. 코드에서처럼 클래스 이름 다음에 메서드 이름을 입력하여 참조된 형식에 대해 static 메서드를 호출할 수 있습니다.

식에 사용할 수 있는 관계 연산자는 다음과 같습니다.

  • 같음("==" 또는 "=")
  • 보다 큼(">")
  • 크거나 같음(">=")
  • 보다 작음("<")
  • 작거나 같음("<=")

또한 다음과 같은 산술 연산자를 사용할 수 있습니다.

  • 더하기("+")
  • 빼기("-")
  • 곱하기("*")
  • 나누기("/")
  • 나머지("MOD")

다음과 같은 연산자를 사용하여 식을 결합하거나 부정할 수 있습니다.

  • AND("AND", "&&")
  • OR("OR", "||")
  • NOT("NOT", "!")
  • 비트 AND("&")
  • 비트 OR("|")

개발자가 코드 조건 대신 규칙 조건을 사용하는 가장 큰 이유는 규칙 조건은 모델의 일부가 되고 워크플로 인스턴스 실행 시 런타임에 동적으로 업데이트할 수 있기 때문입니다. 규칙 조건의 두 번째 이점은 모델의 일부이기 때문에 모델을 기반으로 정교한 도구를 구축할 수 있어 추가적인 작성 환경을 제공하고 종속성 관리, 조건 간 분석 등의 작업을 지원할 수 있다는 것입니다.

정책 작업

정책 작업은 규칙 집합의 정의와 실행을 캡슐화합니다. 규칙 집합이란 실행 가능한 기능 집합을 갖춘 규칙의 모음이며 규칙은 워크플로 멤버에서 작동하는 If-Then-Else 식입니다. 이에 대한 설명은 그림 2에 나와 있으며 규칙 조건에서 설명한 내용과 유사합니다.


그림 2. WF 규칙 집합 작성

정책 작업 추가

정책 작업에 대한 규칙 집합을 구성하기 위한 단계는 다음과 같습니다.

  1. 도구 상자에서 워크플로 디자이너로 정책 작업을 끕니다.
  2. RuleSetReference에서 규칙 집합의 이름을 입력합니다.
  3. RuleSet Definition 필드에서 줄임표를 선택하여 Rule Set Editor를 시작합니다.
  4. 편집기의 목록 상자에 규칙 모음이 나타납니다.
  5. 규칙을 선택하면 조건, Then 작업, Else 작업 및 추가 속성 집합이 표시됩니다.
  6. Rule Condition Editor에서처럼 텍스트로 조건, Then 작업 및 Else 작업을 입력하여 관련 개체 모델 표현으로 구문 분석합니다. 규칙은 워크플로의 멤버에 대해 작성됩니다.
  7. OK를 선택하면 워크플로와 연결된 .rules 파일로 규칙 집합이 serialize됩니다.

RuleSetReference 속성에서 줄임표를 선택하면 그림 3과 같이 기존 규칙 집합을 선택하거나 규칙 집합을 추가 또는 제거하거나 이름을 바꿀 수 있는 편집기가 시작됩니다.


그림 3. WF 규칙 집합 브라우저

규칙 평가

규칙 집합의 각 규칙에는 기본값이 0인 우선 순위 값이 있습니다. 규칙 집합의 규칙은 우선 순위 값에 따라 정렬된 컬렉션으로 간주할 수 있습니다. WF 규칙 평가기는 규칙을 개별적으로 평가하고 규칙의 조건 평가 결과에 따라 규칙의 작업을 실행합니다.

평가 방식은 다음과 같은 절차를 통해 개념적으로 설명할 수 있습니다.

  1. 활성 규칙의 목록을 대상으로 평가가 시작됩니다.
  2. 가장 높은 우선 순위를 가진 규칙을 찾습니다.
  3. 규칙을 평가하고 Then/Else 작업을 적절히 실행합니다.
  4. 규칙의 작업이 목록에 있는 우선 순위가 높은 이전 규칙에서 사용한 필드/속성을 업데이트할 경우 이전 규칙을 다시 평가하고 Then/Else 작업을 적절히 실행합니다. 이때 현재 규칙과 종속성이 있는 규칙만 다시 평가됩니다.
  5. 규칙 집합의 모든 규칙을 평가할 때까지 프로세스를 계속합니다.

간단한 예제를 살펴보도록 합시다. 다음과 같은 규칙 집합이 있다고 가정하는데 여기서 AB 등의 알파벳은 워크플로의 데이터를 나타냅니다.

규칙4(우선 순위=4)

IF A = 15
THEN B = 5

규칙3(우선 순위=3)

IF C = 5
THEN B = 10

규칙2(우선 순위=2)

IF D = 2
THEN A = 15

규칙1(우선 순위=1)

IF B = 5
THEN E = 7

다음과 같은 입력 데이터가 있다고 가정해 봅시다.

  • A = 0
  • B = 0
  • C = 5
  • D = 2
  • E = 0

평가는 다음과 같이 진행됩니다.

  • 규칙4를 평가합니다. 결과는 false이며 Else 작업이 없기 때문에 더 이상 작업이 실행되지 않습니다.
  • 규칙3은 true로 평가되므로 B = 10으로 설정하는 작업이 실행됩니다. 규칙4는 B의 값에 종속적이지 않으므로 규칙2 평가로 넘어갑니다.
  • 규칙2가 true로 평가되어 A = 15로 설정하는 작업이 실행됩니다.
  • 규칙4는 조건에 A의 값을 사용하므로 A의 값이 다시 평가됩니다. 결과는 true이며 B = 5로 설정하는 작업이 실행됩니다. 규칙3과 규칙2는 조건이 A의 값에 종속적이지 않으므로 다시 평가되지 않습니다. 앞의 어떤 규칙도 B의 값에 종속적이지 않으므로 규칙1 평가로 넘어갑니다.
  • 규칙1이 true로 평가되고 E = 7로 설정하는 작업이 실행됩니다.

결과 데이터 집합은 다음과 같습니다.

  • A = 15
  • B = 5
  • C = 5
  • D = 2
  • E = 7
전달 체인

앞서 살펴보았듯이 체인은 규칙 간 식별된 종속성을 기준으로 합니다. 보다 구체적으로 말하자면 한 규칙의 작업과 다른 규칙의 조건 간의 종속성을 기준으로 한다고 할 수 있습니다. 이러한 종속성은 다음 세 가지 방법 중 하나로 식별하거나 선언할 수 있습니다.

  • 암시적
  • 특성 기반
  • 명시적
암시적

암시적 종속성은 엔진에 의해 자동으로 식별됩니다. 규칙 집합이 처음 실행되면 규칙의 조건에서 읽거나 작업에 쓰는 필드/속성을 평가하여 각 규칙을 분석합니다. 이러한 분석은 조건의 식과 작업의 문을 순서에 따라 평가하는 방식으로 수행됩니다. 예를 들어 다음과 같은 규칙이 있다고 가정해 봅시다.

규칙1

IF this.subtotal > 10000
THEN this.discount = .05

규칙2

IF this.discount > 0
THEN this.total = (1-this.discount) * this.subtotal

엔진은 규칙을 평가하여 규칙1이 subtotal 필드를 읽고 discount 필드를 쓴다는 사실을 확인합니다. 규칙2는 discount 및 subtotal 필드를 읽고 total 필드를 씁니다. 따라서 규칙2는 규칙1에 종속되므로 엔진에서는 규칙1이 Then 작업을 실행할 때마다 규칙2가 평가 또는 다시 평가되도록 합니다.

종속성은 리프 노드 수준에서 식별됩니다. 다음 규칙 집합을 예로 들어 보겠습니다.

규칙1

IF this.order.Subtotal > 10000
THEN this.order.Discount= .05

규칙2

IF this.order.Discount > 0
THEN this.order.Total = (1-this.order.Discount) * this.order.Subtotal

규칙3

IF this.order.CustomerType = "Residential"
THEN ...

여전히 규칙1과 2 사이에는 종속성이 있지만 규칙1 또는 2 중 어느 것도 CustomerType 속성을 업데이트하지 않으므로 규칙3은 이러한 규칙에 종속되지 않습니다. 즉, 종속성은 Order 개체 자체가 아닌 CustomerType 속성 수준에서 식별됩니다.

WF는 암시적 체인을 통해 사용자에게 필요한 체인 작업 중 대부분을 처리하므로 사용자는 명시적으로 모델을 업데이트할 필요가 없고 사실상 대부분의 경우 체인이나 체인의 필요성에 대해 알 필요가 없습니다. 암시적 체인은 복잡한 규칙 집합의 모델링을 보다 용이하게 하며 더욱 강력하면서도 대부분의 작업을 보이지 않게 수행하는 엔진의 기능을 담당하게 됩니다. 그러나 보다 복잡하고 구체적인 시나리오에 사용할 수 있도록 특성 기반 체인과 명시적 체인을 제어하는 두 가지 다른 방법도 제공됩니다.

특성 기반

규칙 내 메서드 호출의 경우 수행되는 읽기 및 쓰기를 명확하게 평가하는 것이 더욱 어렵습니다. 이 문제를 해결하기 위해 WF에서는 메서드에 적용하여 각 작업의 종류를 표시할 수 있는 다음과 같은 세 가지 특성을 제공합니다.

  • RuleRead
  • RuleWrite
  • RuleInvoke

메서드에 RuleRead 특성을 지정하면 메서드가 표시된 속성을 읽음을 나타냅니다. 마찬가지로 RuleWrite 특성은 메서드가 특정 필드 또는 속성을 업데이트함을 표시하는 데 사용할 수 있습니다. 암시적 종속성에서 사용한 첫 번째 두 규칙이 다음과 같이 다시 작성되었다고 가정해 봅시다.

규칙1

IF this.subtotal > 10000
THEN this.SetDiscount(.05)

규칙2

IF this.discount > 0
THEN this.total = (1-this.discount) * this.subtotal

SetDiscount 메서드는 다음과 같이 특성을 지정할 수 있으며, 이렇게 하면 규칙2가 discount 필드를 사용하므로 규칙1에 종속되어 있음을 엔진에서 식별할 수 있게 됩니다.

[RuleWrite("discount")]
void SetDiscount(double requestedDiscount)
{
    ...//discount 필드를 업데이트하는 코드
}
(참고: 프로그래머 코멘트는 샘플 프로그램 파일에는 영문으로 제공되며 기사에는 설명을 위해 번역문으로 제공됩니다.)

RuleInvoke 특성은 연결된 메서드 호출로 인한 종속성을 나타내는 데 사용할 수 있습니다. 예를 들어 규칙과 메서드를 다음과 같이 수정한다고 가정해 봅시다.

규칙1

IF this.subtotal > 10000
THEN this.SetDiscountWrapper(.05)

규칙2

IF this.discount > 0
THEN this.total = (1-this.discount) * this.subtotal
[RuleInvoke("SetDiscount")]
void SetDiscountWrapper(double requestedDiscount)
{
     ...
     SetDiscount(requestedDiscount);
     ...
}

[RuleWrite("discount")] 
void SetDiscount(double requestedDiscount)
{
}

규칙2의 조건은 SetDiscountWrapper를 호출하고 이 메서드는 discount 필드에 값을 쓰는 SetDiscount를 호출합니다. RuleInvoke 특성을 사용하면 이러한 간접 쓰기를 선언하여 엔진에서 감지하도록 할 수 있습니다.

특성 경로에서 참조되는 필드나 특성은 메서드와 동일한 클래스의 필드나 특성을 참조한다는 점이 중요합니다. 실행을 위해 규칙 집합에 반드시 루트 개체를 전달할 필요는 없기 때문입니다. 예를 들어 Order의 특성을 다음과 같이 지정할 수 있습니다.

public class Order
{
    private double discount;

    public double Discount
    {
    get { return discount;}
    set { discount = value;}
    }

    [RuleWrite("Discount")]
    void CalculateDiscount(double requestedDiscount, double weighting)
    {
...//discount 필드를 업데이트하는 코드
    }
}

그런 다음 워크플로에서 이 클래스를 다음과 같이 사용할 수 있습니다.

public class Workflow1 :  SequentialWorkflowActivity
{
    private Order discount;

    ...
}

규칙2를 실행하면 규칙1이 다시 평가됩니다.

규칙1

IF this.order.Discount > 5
THEN ...

규칙2

IF ...
THEN this.order.CalculateDiscount( 5.0, .7)

특성 사용에 관해 알아두어야 할 몇 가지 추가적인 사항은 다음과 같습니다.

  • 특성은 메서드 호출에 대한 매개 변수가 아닌 Owner 클래스의 필드/속성을 가리킵니다.
  • 규칙 특성에 와일드카드도 사용할 수 있습니다. 예를 들어 RuleWrite("order/*")를 사용하여 "order" 필드에서 참조하는 개체의 모든 필드가 이 메서드에 의해 수정됨을 나타낼 수 있습니다. 이 예에서는 메서드가 Order 클래스가 아닌 워크플로 자체에 있습니다. 그러나 와일드카드는 경로의 끝에서만 사용할 수 있습니다. RuleWrite("*/Discount")와 같은 특성은 올바르지 않습니다.
  • RuleWrite("order")와 같은 특성을 참조 형식과 함께 사용하여 참조가 변경되었음을 나타낼 수 있습니다. 예를 들어 변수가 이제부터는 다른 Order 인스턴스를 가리킴을 나타낼 수 있습니다. IF this.order == this.order2와 같이 인스턴스 참조 자체를 테스트하는 모든 규칙뿐 아니라 변수의 필드/속성을 사용하는 모든 규칙은 영향을 받는 것으로 가정합니다.
  • 메서드 특성을 지정하지 않는 경우 기본 동작은 메서드 호출에서 대상 개체, 즉 메서드가 호출된 개체의 모든 필드/속성을 읽기는 하지만 이러한 필드/속성 중 어느 것에도 쓰지는 않는 것으로 가정합니다. 또한 메서드는 전달된 매개 변수를 읽지만 이러한 매개 변수 중 어느 것에도 쓰지는 않는 것으로 가정합니다. Outref 매개 변수는 규칙 작업에 사용될 경우 데이터가 기록되는 것으로 가정합니다.

명시적

필드/속성 종속성을 나타내는 마지막 방법은 Update 문을 사용하는 것입니다. Update 문은 필드/속성의 경로를 나타내는 문자열이나 필드/속성 액세스를 나타내는 식을 인수로 취합니다. 예를 들어 다음 두 문 중 하나를 규칙 집합 편집기에 입력하면 워크플로의 Customer 인스턴스의 Name 속성에 Update 문을 생성할 수 있습니다.

Update("this/customer/Name")

또는

Update(this.customer.Name)

Update 문은 규칙이 표시된 필드/속성에 값을 기록함을 나타냅니다. 따라서 Update 문은 규칙의 필드/속성에 직접 값을 설정하거나 필드/속성에 대해 RuleWrite 특성을 사용하는 메서드를 호출하는 것과 결과가 동일합니다.

Update 명령 역시 와일드카드 사용을 지원합니다. 예를 들어 규칙에 다음 Update 명령을 추가할 수 있습니다.

Update("this/customer/*")

그러면 조건에 Customer 인스턴스의 속성을 사용하는 모든 규칙이 다시 평가됩니다. 즉, 다음과 같은 두 개의 규칙은 각각 다시 평가됩니다.

IF this.customer.ZipCode == 98052
THEN ...

IF this.customer.CreditScore < 600
THEN ...

일반적으로 대부분의 상황에서 사용자가 명시적으로 Update 문을 모델링할 필요는 없습니다. 대개 필요한 종속성 분석과 체인 동작은 암시적 체인을 통해 제공되고 암시적 체인에서 종속성을 식별할 수 없는 경우에는 메서드 특성 지정이 주로 사용됩니다. 일반적으로 메서드에서 종속성을 한 번 식별하고 해당 메서드를 사용하는 많은 규칙에서 그 종속성을 활용할 수 있기 때문에 메서드 특성 지정이 Update 문을 사용하는 것보다 종속성을 나타내는 데 선호되는 방법입니다. 또한 규칙 작성자와 메서드를 구현한 사람이 다르거나 다른 시간에 작업한 경우 메서드 특성 지정을 사용하면 코드에 대해 가장 잘 아는 메서드 작성자가 메서드의 종속성을 식별할 수 있습니다.

그러나 다음 코드에서처럼 워크플로 작성자가 제어하지 않기 때문에 특성을 지정할 수 없는 클래스의 메서드로 필드/속성이 전달되는 경우와 같이 Update 문이 더 적합한 경우도 있습니다.

IF ...
THEN this.customer.UpdateCreditScore(this.currentCreditScore)
    Update(this.currentCreditScore)

전달 체인 제어

전달 체인은 규칙 간 종속성에 대한 정의 또는 종속성에 대한 지식 없이도 개별 규칙을 규칙 집합으로 그룹화할 수 있는 매우 강력한 개념입니다.

그러나 일부 시나리오에서는 규칙 작성자가 체인 동작을 보다 잘 제어할 수 있는 기능, 특히 체인 연결을 제한하는 기능이 필요할 수 있습니다. 이 기능을 사용하면 규칙을 모델링하는 사람이 다음과 같은 작업을 수행할 수 있습니다.

  • 잘못된 결과를 초래할 수 있는 규칙의 반복 실행 제한
  • 성능 향상
  • 무한 루프 방지

이러한 고급 제어는 WF 규칙에서 다음과 같은 두 가지 속성에 의해 가능합니다.

  • 규칙 집합의 Chaining Behavior 속성
  • 각 규칙의 Reevaluation Behavior 속성

이러한 속성값은 RuleSet Editor에서 설정할 수 있습니다.

Chaining Behavior 속성

규칙 집합의 Chaining Behavior 속성에 사용할 수 있는 값은 다음 세 가지입니다.

  • Full Chaining
  • Explicit Chaining
  • Sequential

Full Chaining 옵션은 기본값이며 지금까지 설명한 방식에 해당합니다. Explicit Chaining 옵션을 선택하면 암시적 체인과 특성 기반 체인이 해제되고 명시적 Update 문에 대해서만 체인이 연결됩니다. 이렇게 하면 규칙 작성자가 어떤 규칙에 의해 다시 평가 과정이 실행될지를 완벽하게 제어할 수 있습니다. 일반적으로 이 옵션은 과도하게 또는 무한적으로 규칙을 다시 평가하게 되는 순환 종속성을 방지하거나 규칙 집합의 기능적 완전성을 제공하는 데 필요하지 않은 규칙 다시 평가 과정을 제거함으로써 성능을 향상시키기 위해 사용합니다.

마지막 옵션은 Sequential입니다. 이 옵션을 선택하면 엔진이 엄격하게 순차적 방식으로 규칙을 다시 평가하게 됩니다. 각 규칙은 우선 순위에 따라 한 번씩만 평가되며 우선 순위가 높은 규칙은 우선 순위가 낮은 규칙에 영향을 미칠 수 있으나 반대 방향으로는 체인이 연결되지 않기 때문에 영향을 미치지 않습니다. 따라서 이 옵션은 규칙 간 종속성이 있는 경우 명시적 우선 순위를 지정하여 사용해야 합니다.

Reevaluation Behavior 속성

규칙의 Reevaluation Behavior 속성에 사용할 수 있는 값은 다음 두 가지입니다.

  • Always
  • Never

Always는 기본값으로 지금까지 설명한 방식에 해당합니다. 즉, 체인 연결에 따라 다른 규칙의 작업으로 인해 규칙이 항상 다시 평가됩니다. Never는 이름에서 알 수 있듯이 이러한 다시 평가 기능을 해제합니다. 규칙은 한 번만 평가되며 앞서 작업을 수행한 경우에도 다시 평가되지 않습니다. 즉, 규칙이 이전에 평가되고 그 결과로 Then 또는 Else 작업이 수행된 경우 이 규칙은 다시 평가되지 않습니다. 그러나 Then 또는 Else 작업에서 아무 것도 실행하지 않은 경우에는 규칙이 실행된 것으로 표시되지 않습니다.

일반적으로 이 속성은 규칙이 자체 작업이나 다른 규칙에 대해 가지는 종속성으로 인해 무한 루프가 발생하는 것을 방지하기 위해 규칙 수준에서 사용됩니다. 예를 들어 다음 규칙은 자체 무한 루프를 생성하며 이 규칙의 기능적 요구 사항을 충족시키기 위해 다시 평가할 필요가 없습니다.

IF this.shippingCharge < 2.5 AND this.orderValue > 100
THEN this.shippingCharge = 0

또한 규칙을 다시 평가하더라도 OrderValue 필드만 변경된 경우 사용자는 명시적 Update 문에 대해서만 체인을 연결하고 이 Update 문을 관련 규칙 작업에 추가하도록 규칙 집합의 체인 동작을 설정할 수 있습니다. 물론 이 규칙에 ShippingCost의 값이 이미 0이 아닌지 확인하는 조건을 추가할 수도 있지만 체인 제어를 사용하면 업무 요구 사항과는 달리 평가 세부 정보를 기준으로 규칙을 정의해야 할 필요성을 없애 줍니다.

Halt 함수

마지막 제어 방법으로 Halt 함수를 규칙 작업으로 추가하는 방법을 들 수 있습니다. 편집기의 Then 또는 Else 작업 부분에 "Halt"만 입력하면 됩니다. 그러면 규칙 집합의 실행이 즉시 중지되고 호출 코드로 제어권이 되돌아갑니다. 물론 이 함수는 체인 제어 이외의 경우에도 사용할 수 있습니다. 한 예로 특정 기능을 위한 규칙 집합에서 Halt 함수를 사용하여 목표가 달성되면 실행 순환 주기를 단축할 수 있습니다.

추가 모델링 설명

우선 순위 기반 실행

앞서 설명했듯이 사용자가 규칙 집합이나 해당 규칙 집합에 있는 규칙의 하위 집합에 특정 실행 순서를 적용하려는 경우 규칙에 우선 순위 필드를 사용하여 이 순서를 정확하게 정의할 수 있습니다. 이렇게 하면 체인을 사용할 필요가 없어지는 경우가 종종 있으므로 체인 기능을 해제할 수도 있습니다. 많은 경우 명시적 실행 순서를 제공하는 것만으로도 규칙 종속성이 충족되는 것으로 나타났습니다.

그러나 중요한 것은 WF의 전달 실행 방식을 통해 사용자가 실행 순서를 정의할 수 있으나 반드시 정의해야 하는 것이 아니라는 점입니다. 대부분의 경우 규칙 종속성이 충족되도록 엔진에 의해 관계가 자동으로 관리되므로 전달 체인 동작이 수행되면 규칙 우선 순위를 지정하지 않아도 정확한 규칙 집합 결과를 얻을 수 있습니다.

다음과 같은 규칙을 예로 들어 봅시다.

규칙1

IF this.Weather.Temperature < 50
THEN this.Drink.Style = "Latte"

규칙2

IF this.Drink.Style == "Latte"
THEN this.Snack.Style = "Scone"
ELSE this.Snack.Style = "Muffin"

WF에서는 규칙1이 먼저 실행되도록 더 높은 우선 순위를 지정할 수 있습니다. 이렇게 함으로써 규칙2가 평가되기 전에 Drink.Style이 설정됩니다.

그러나 원하는 결과를 얻기 위해 반드시 순서를 지정할 필요는 없습니다. 규칙2가 먼저 평가되었다고 가정해 봅시다. 이 경우 Drink.Stylenull이거나 다른 스타일일 수 있습니다. 그러면 Snack.StyleMuffin으로 설정됩니다. 그러나 규칙1이 실행되고 Drink.StyleLatte로 설정하면 규칙2가 다시 평가되므로 Snack.StyleScone으로 설정됩니다. 즉, 기본적으로 사용자는 순서를 지정할 수 있으나 그럴 필요가 없는 경우가 많습니다.

컬렉션 처리

어떤 경우에는 컬렉션에 있는 모든 항목에 대해 규칙을 평가해야 할 수 있습니다. 컬렉션에 대한 반복은 여러 가지 방법으로 수행될 수 있으나 그 중 한 가지 방법은 다음과 같은 규칙 패턴을 사용하는 것입니다.

규칙1(우선 순위=2)

//항상 이 규칙을 한 번 실행하여 열거자 생성
IF 1==1
THEN this.enumerator = this.myCollection.GetEnumerator()

규칙2(우선 순위=1)

IF this.enumerator.MoveNext()
THEN this.currentInstance = this.enumerator.Current

규칙3-N(우선 순위=0)

.... //this.currentInstance에 대해 작성된 추가적인 규칙

규칙N+1(우선 순위=-1)

// 항상 평가되는 조건
// this.currentInstance는 매번 평가됩니다.
//this.currentInstance는 변경되지만
// "1==1"은 한 번만 평가됩니다
IF this.currentInstance == this.currentInstance 
                                                                         
THEN ...
        Update("this/enumerator") //이로 인해 규칙2가 다시 평가됩니다
ELSE ...
         Update("this/enumerator")

추적 및 트레이싱

추적

호스트에서 추적 프로파일에 UserTrackPoint를 추가하여 추적 이벤트를 등록하면 규칙 집합 실행 시 호스트에 구성된 추적 서비스로 추적 이벤트가 전송됩니다. 전송되는 RuleActionTrackingEvent는 평가되는 규칙 이름뿐 아니라 조건 평가 결과(true/false)를 제공합니다. 이에 대한 예는 SDK의 RuleActionTrackingEvent 샘플을 참조하십시오.

작업에 대한 규칙 조건의 평가 결과는 추적 작업 실행을 통해 간접적으로 추적할 수 있습니다.

트레이싱

응용 프로그램 구성 파일에 다음과 같은 항목을 추가하면 추가적인 규칙 집합 평가 정보를 로그 파일로 전송할 수 있습니다.

<configuration>
  <system.diagnostics>
     <switches>
         <add name="Rules" value="Information"/>
     </switches>
  </system.diagnostics>
</configuration>

다음과 같은 정보가 로그 파일로 전송됩니다.

  • 조건 종속성 정보:
    • 예: Rule "ReturnNumberOfStops" Condition dependency: "this/currentFlight/OutboundFlight/NumberOfStops/"
  • 파생 작업에 대한 정보:
    • 예: Rule "ReturnNumberOfStops" THEN side-effect: "this/currentFlight/Score/"
  • 체인 관계:
    • 예: Rule "ReturnNumberOfStops" THEN actions trigger rule "ApprovedFlights"
  • 작업 집합 실행:
    • 예: Rules: "Executing RuleSet FlightRuleSet"
  • 조건 평가:
    • 예: Rules: Evaluating condition on rule "SetDefaultScore"
  • 조건 평가 결과:
    • 예: Rules: Condition evaluated to True
  • 작업 실행:
    • 예: Rules: Evaluation THEN actions for rule"SetDefaultScore"

모든 트레이싱 메시지는 현재 "정보" 수준으로 정의되어 있으므로 규칙 트레이싱을 보려면 구성 파일에서 정보의 수준이나 세부 내용 표시 기준을 조정해야 합니다.

결론

WF는 여러 가지 방법으로 활용하여 다양한 시나리오를 지원할 수 있는 유연한 규칙 기능을 제공합니다. 간단한 작업 조건에서 복잡한 전달 체인 규칙 집합에 이르기까지 이 기술을 사용하면 규칙에 대한 지원을 워크플로에 원활히 통합할 수 있습니다. 또한 모든 .NET 응용 프로그램에 규칙 기능을 제공하기 위해 워크플로 외부에서 규칙 엔진을 사용할 수도 있습니다.

이러한 기능을 통해 사용하면 고급 규칙 집합 및 응용 프로그램 시나리오를 지원할 수 있는 다양성과 확장성은 그대로 유지하면서도 신규 개발자들이 워크플로에 간단한 규칙을 쉽게 통합할 수 있습니다. 다음 섹션에서 소개하는 자료와 함께 이 문서를 참조함으로써 WF 규칙을 처음 접하는 개발자들은 이 기술을 배우고 활용하며 빠르게 생산성을 향상시킬 수 있을 것입니다.

추가 정보

  • MSDN 워크플로 사이트(영문)
    웹캐스트 및 실습에 대한 다양한 문서 및 링크 수록
  • 커뮤니티 사이트 샘플(영문)
    • 외부 규칙 집합 툴킷 워크플로 어셈블리의 외부로 규칙을 분리하는 방법에 대한 예제를 제공합니다.
    • 규칙 집합 분석 규칙 집합에서 규칙 간 그리고 규칙과 데이터 간 관계를 분석할 수 있는 도구입니다.
    • Excel의 규칙 워크플로와 상관없이 규칙을 독립적으로 사용하는 방법에 대한 예제를 제공합니다. Excel의 결정 테이블을 통해 작성된 규칙을 프로그래밍 방식으로 만드는 방법도 설명합니다.
  • SDK 샘플
    • IfElseWithRules IfElse 작업에서 RuleCondition을 사용하는 방법을 보여 줍니다(\Technologies\RulesAndConditions).
    • DynamicUpdateChangingRules 동적 업데이트 API를 사용하여 실행 중인 워크플로 인스턴스에서 RuleCondition을 변경하는 방법을 보여 줍니다(\Technologies\RulesAndConditions).
    • SimplePolicy API를 사용하여 간단한 규칙 집합과 정책 작업을 정의하는 방법을 보여 줍니다(\Technologies\Activities\Policy).
    • AdvancedPolicy 보다 복잡한 규칙 집합을 정의합니다(\Technologies\Activities\Policy).
    • RuleActionTrackingEventSample 추적 공급자에서 규칙 평가 결과를 수집하는 방법을 보여 줍니다(\Technologies\Tracking).
  • MSDN 워크플로 포럼(영문)
    • WF 규칙이나 WF의 전반적인 부분에 대한 질문이 있는 경우 이 토론 포럼을 방문하십시오.

출처 : 한국 마이크로소프트 MSDN (2006년 2월)