Skip to main content

정책 규칙이란?

**정책 규칙(Policy Rule)**은 조건 → 액션의 쌍입니다. 입력 facts가 조건을 만족하면 규칙의 액션이 실행됩니다. 규칙은 우선순위 순서로 평가되며 1이 가장 높습니다. 한 버전 안에서 우선순위는 항상 1…N 연속입니다. 새 규칙은 끝에 붙고, 순서를 바꾸면 전체가 다시 매겨집니다.
각 규칙은 특정 정책 버전에 속하며, 이름 / 우선순위 / 조건(트리 구조 로직) / 하나 이상의 액션을 가집니다.

조건 문법

조건은 SINGLEGROUP 두 노드 타입의 트리 구조입니다.
LexQ는 type: "SINGLE" / type: "GROUP", field, operator, value, valueType 필드를 사용하는 자체 condition DTO 포맷을 사용합니다. Console 내부 폼 표현(다른 필드명 사용 가능)과 혼동하지 마세요. API 또는 CLI 호출 시에는 항상 엔진 포맷을 사용해야 합니다.

SINGLE 조건

단일 fact를 값과 비교하는 leaf 노드:

GROUP 조건

자식 조건을 AND 또는 OR로 결합하는 branch 노드:

연산자

IN / NOT_IN의 경우 호환 타입 열은 검사 대상 fact의 타입(STRING 또는 NUMBER)을 가리킵니다. 제공하는 value는 리스트 자체이며, 그 valueTypeLIST_STRING 또는 LIST_NUMBER입니다.
목록 타입 fact에 CONTAINS를 쓰지 마세요. CONTAINSSTRING 부분 일치입니다. LIST_STRING / LIST_NUMBER fact에는 HAS_ANY / HAS_ALL / HAS_NONE을 사용하고, 값은 쉼표로 이은 문자열이 아니라 배열(["electronics"])로 보내야 합니다.IN / NOT_IN은 반대 방향입니다. 스칼라 fact를 목록 값과 대조합니다. HAS_*는 양쪽이 모두 목록입니다.

값 타입

중첩 조건 예시

(customerTier = "VIP" AND paymentAmount >= 100000) OR region IN ["KR", "JP"]
위 예시에서 customerTier, region, paymentAmount는 사용자 정의 fact로 Fact Definitions에 등록하는 것이 좋습니다. 등록하지 않은 채로 참조해도 됩니다. LexQ는 미등록 키를 거부하지 않고 비차단 경고로 알립니다. 다만 등록해야 타입 검증과 필수 입력 fact(Required Input Facts) 분석이 동작합니다. 기본 제공 시스템 fact는 userId, userTags 두 개뿐입니다.

액션 타입

LexQ 엔진의 액션은 도메인에 종속되지 않는 원시 연산입니다. 엔진은 숫자와 구조만 볼 뿐 커머스, 핀테크, 보험 같은 특정 업종을 가정하지 않습니다. 업무 의미는 여러분이 정한 fact 이름에 담깁니다. 엔진은 외부 시스템을 호출하지 않습니다. fact를 바꾸고 결정을 기록할 뿐이며, 응답을 읽고 무엇을 할지는 호출한 쪽이 정합니다. 엔진 상태와 외부 상태를 분리해야 감사 추적이 성립하기 때문입니다.

MUTATE_FACT 파라미터

operator × method 매트릭스 DIV + AMOUNT 조합에서는 operand가 0 이면 안 됩니다.
targetVar는 요청 facts에 숫자로 들어 있어야 합니다. 없으면 오류가 발생하며, 엔진이 0으로 대신 채우지 않습니다. 값을 누적하는 정책이라면 시작값을 함께 보내야 합니다 (pointsEarned: 0). 엔진은 상태를 갖지 않으므로 여러분의 데이터베이스를 읽지 않습니다.없던 fact를 만드는 일은 SET_FACT가 합니다.

targetVar와 refVar가 다를 때

refVarPERCENTAGE × 세 칸에서만 의미를 갖습니다. 다른 칸에서 지정하면 조용히 무시되지 않고 오류가 납니다. AMOUNT에는 기준이라는 개념이 없고, MUL × PERCENTAGE는 배수 표기라서 기준을 읽지 않기 때문입니다. 계산 기준이 변경 대상과 다를 때 사용합니다.
loyaltyPoint += orderTotal × 5% 입니다. 적립 대상과 계산 기준이 서로 다른 fact 입니다. refVar를 생략하면 loyaltyPoint += loyaltyPoint × 5%가 되어 결과가 완전히 달라집니다.
값의 범위는 제한하지 않습니다. 음수 operand와 100을 넘는 비율 모두 유효합니다. 환급(-5), 가산금(150), 위험 점수, 게임 포인트처럼 범위를 벗어나는 값이 필요한 도메인이 실제로 있습니다. 범위 검증은 엔진이 아니라 fact 정의에서 하세요.

MUTATE_FACT — 정률(Percentage)

paymentAmount를 10% 줄입니다. 통화 fact라면 아래 반올림 절을 함께 보세요.

MUTATE_FACT — 정액(Fixed Amount)

MUTATE_FACT — 반올림(Rounding)

rounding을 지정하지 않으면 결과가 무손실 정밀도로 유지됩니다. 통화 단위로 맞춰야 할 때 지정하세요.
mode 에는 UP, DOWN, CEILING, FLOOR, HALF_UP, HALF_DOWN, HALF_EVEN을 넣을 수 있습니다. 기본값은 HALF_UP 입니다.

SET_FACT — 값 대입

타입에 관계없이 값을 대입합니다. 없는 fact를 새로 만드는 유일한 액션입니다.
SET_FACT는 덧붙이지 않고 통째로 대입합니다. LIST_STRING fact에 값을 누적하려면 현재 목록을 요청에 담아 보내고 새 목록 전체를 대입하세요. 산술 변경이 아니라 대입이므로 SET_FACT__delta를 만들지 않습니다.

BLOCK — 거부 결정 기록

BLOCK은 실행을 중단하지 않습니다. 같은 규칙의 뒤따르는 액션도, 이후 선택된 다른 규칙도 그대로 실행됩니다. isBlocked fact를 기록할 뿐이며, 실제로 요청을 막는 일은 호출한 쪽의 몫입니다.

생성 변수 (Generated Variables)

변경된 facts와 별도로, 엔진은 액션별 변화 정보를 generatedVariables로 노출합니다: 한 규칙에서 여러 액션이 같은 fact를 변경하면 __delta는 누적 변화량을 보고합니다. 액션 하나하나의 스냅샷은 executionTraces에 남아, 감사 시 원인을 끝까지 되짚을 수 있습니다.

상호 배타 그룹(Mutex) — 규칙 간 충돌 해결

한 버전 안에서 규칙은 **상호 배타 그룹(mutex group)**에 속할 수 있습니다. 상호 배타 그룹은 조건이 맞는 규칙 중 몇 개를 발화시킬지 제어합니다. mutexModeEXCLUSIVE이면 경쟁에서 이긴 규칙 하나만 발화합니다. MAX_N이면 우선순위 순서로 최대 mutexLimit개의 규칙이 발화합니다. 발화하지 못한 나머지 규칙은 Decision Trace에 status BLOCKED, reasonCode MUTEX_PRIORITY_LOST 또는 MUTEX_LIMIT_REACHED로 기록됩니다 (Decision Trace 참조).

Decision Trace

규칙 평가 결과는 모두 decision trace 엔트리로 기록되어 해당 규칙이 발화했는지, 왜 그렇게 결정됐는지를 설명합니다. LexQ가 모든 결정을 검증 가능하다고 말하는 근거가 여기에 있습니다. 어떤 결과든 status와 reasonCode 조합으로 되짚을 수 있습니다. decision trace 엔트리는 두 분류 필드를 가집니다:
  • status: 결과의 상위 분류
  • reasonCode: 그 분류 안에서의 구체적 사유

DecisionStatus

DecisionReasonCode

Status × ReasonCode 매핑

“왜 내 규칙이 발화하지 않았지?”를 디버깅할 때 decision trace는 두 단계로 답을 줍니다. status는 어떤 분류의 필터링이 규칙을 제거했는지 알려주고, reasonCode는 정확히 어떤 검증이 규칙을 거부했는지 알려줍니다.
CONDITION_MISMATCH에는 두 가지 사실이 섞여 있습니다. 조건이 거짓이었던 경우와, 조건을 평가할 수 없었던 경우(타입 불일치, 해소되지 않은 fact)입니다. 구체적인 사유는 reasonDetail에 담깁니다. 예를 들어 LIST_STRING fact에 평문 문자열이 들어오면 Evaluation error: FACT_TYPE_MISMATCH가 기록됩니다. 평가에 실패한 규칙이 있어도 실행 전체가 멈추지는 않으며 나머지 규칙은 정상 실행됩니다.

완전한 규칙 예시

다음 단계

Fact Definitions

규칙이 기대하는 입력 변수를 정의하세요.

Dry Run

배포 전에 규칙을 테스트하세요.