정책 규칙이란?
**정책 규칙(Policy Rule)**은 조건 → 액션의 쌍입니다. 입력 facts가 조건을 만족하면 규칙의 액션이 실행됩니다. 규칙은 우선순위 순서로 평가되며 1이 가장 높습니다. 한 버전 안에서 우선순위는 항상1…N 연속입니다. 새 규칙은 끝에 붙고, 순서를 바꾸면 전체가 다시 매겨집니다.
조건 문법
조건은SINGLE과 GROUP 두 노드 타입의 트리 구조입니다.
SINGLE 조건
단일 fact를 값과 비교하는 leaf 노드:GROUP 조건
자식 조건을AND 또는 OR로 결합하는 branch 노드:
연산자
IN / NOT_IN의 경우 호환 타입 열은 검사 대상 fact의 타입(STRING 또는 NUMBER)을 가리킵니다.
제공하는 value는 리스트 자체이며, 그 valueType은 LIST_STRING 또는 LIST_NUMBER입니다.값 타입
중첩 조건 예시
(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와 refVar가 다를 때
refVar는 PERCENTAGE × 세 칸에서만 의미를 갖습니다.
다른 칸에서 지정하면 조용히 무시되지 않고 오류가 납니다.
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 — 거부 결정 기록
생성 변수 (Generated Variables)
변경된 facts와 별도로, 엔진은 액션별 변화 정보를generatedVariables로 노출합니다:
한 규칙에서 여러 액션이 같은 fact를 변경하면
__delta는 누적 변화량을 보고합니다. 액션 하나하나의 스냅샷은 executionTraces에 남아, 감사 시 원인을 끝까지 되짚을 수 있습니다.
상호 배타 그룹(Mutex) — 규칙 간 충돌 해결
한 버전 안에서 규칙은 **상호 배타 그룹(mutex group)**에 속할 수 있습니다. 상호 배타 그룹은 조건이 맞는 규칙 중 몇 개를 발화시킬지 제어합니다.mutexMode가 EXCLUSIVE이면 경쟁에서 이긴 규칙 하나만 발화합니다.
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
배포 전에 규칙을 테스트하세요.

