Value DSL
Value DSL은 계산된 값, 전이 가드, 불변식, 데이터 변환을 정의하기 위한 Fascia의 제한된 표현식 언어입니다. 의도적으로 기능을 제한하고 있습니다 -- 함수 정의, 반복문, 부작용이 없습니다. 모든 표현식은 기존 데이터에서 결과를 산출하는 순수 계산입니다.
Value DSL 표현식은 Fascia 스펙 전반에 걸쳐 사용됩니다:
- Entity 불변식 -- 항상 참이어야 하는 비즈니스 규칙
- 상태 머신 가드 -- 전이가 발생하기 위해 충족해야 하는 조건
- Flow Transform 노드 -- Flow 단계 간 데이터 변환
- If/Switch 조건 -- Flow 그래프의 분기 로직
- Policy 조건 -- Risk Engine이 평가하는 규칙
연산자
산술 연산자
| Operator | Description | Example |
|---|---|---|
+ | 덧셈 | order.subtotal + order.tax |
- | 뺄셈 | order.total - order.discount |
* | 곱셈 | item.price * item.quantity |
/ | 나눗셈 | total / count |
% | 나머지 | index % 2 |
비교 연산자
| Operator | Description | Example |
|---|---|---|
== | 같음 | order.status == "confirmed" |
!= | 같지 않음 | user.role != "guest" |
> | 초과 | reservation.totalPrice > 0 |
< | 미만 | now() < reservation.startDate |
>= | 이상 | account.balance >= withdrawal.amount |
<= | 이하 | deposit <= totalPrice |
논리 연산자
| Operator | Description | Example |
|---|---|---|
&& | 논리 AND | isActive && isVerified |
|| | 논리 OR | isAdmin || isStaff |
! | 논리 NOT | !isDeleted |
멤버 접근
점 표기법을 사용하여 Entity 및 중첩 객체의 필드에 접근합니다:
reservation.totalPrice
reservation.customer.name
input.paymentMethod
내장 함수
문자열
| Function | Signature | Description |
|---|---|---|
concat | concat(a, b, ...) | 문자열 연결 |
length | length(str) | 문자열 길이 |
substring | substring(str, start, end) | 부분 문자열 추출 |
toLowerCase | toLowerCase(str) | 소문 자로 변환 |
toUpperCase | toUpperCase(str) | 대문자로 변환 |
trim | trim(str) | 앞뒤 공백 제거 |
startsWith | startsWith(str, prefix) | 접두사로 시작하는지 확인 |
endsWith | endsWith(str, suffix) | 접미사로 끝나는지 확인 |
contains | contains(str, search) | 부분 문자열 포함 여부 확인 |
replace | replace(str, search, replacement) | 첫 번째 일치 항목 교체 |
split | split(str, delimiter) | 문자열을 리스트로 분할 |
날짜
| Function | Signature | Description |
|---|---|---|
now | now() | 현재 날짜와 시간 |
addDays | addDays(date, days) | 날짜에 일수 추가 |
addHours | addHours(date, hours) | 날짜에 시간 추가 |
diffDays | diffDays(date1, date2) | 두 날짜 간 일수 차이 |
format | format(date, pattern) | 날짜를 문자열로 포맷 |
수학
| Function | Signature | Description |
|---|---|---|
abs | abs(n) | 절대값 |
ceil | ceil(n) | 올림 |
floor | floor(n) | 내림 |
round | round(n) | 반올림 |
min | min(a, b) | 두 값 중 작은 값 |
max | max(a, b) | 두 값 중 큰 값 |
집계
| Function | Signature | Description |
|---|---|---|
sum | sum(list, field) | 리스트에서 필드의 합계 |
count | count(list) | 리스트의 항목 수 |
avg | avg(list, field) | 리스트에서 필드의 평균 |
타입
| Function | Signature | Description |
|---|---|---|
toString | toString(value) | 문자열로 변환 |
toNumber | toNumber(value) | 숫자로 변환 |
isNull | isNull(value) | 값이 null인지 확인 |
coalesce | coalesce(a, b) | null이 아닌 첫 번째 값 반환 |
조건
| Function | Signature | Description |
|---|---|---|
if | if(condition, thenValue, elseValue) | 조건부 표현식 |
표현식 예시
총액의 10% 계산:
reservation.totalPrice * 0.1
조건부 표시 텍스트:
if(order.status == "pending", "Waiting for confirmation", "Processed")
기간(일수) 계산:
diffDays(reservation.endDate, reservation.startDate)
비즈니스 규칙 검사:
reservation.depositAmount <= reservation.totalPrice && reservation.totalPrice > 0
요약 문자열 포맷:
concat("Order #", toString(order.id), " - ", toUpperCase(order.status))
제약 사항
Value DSL은 안전성과 예측 가능성을 위해 의도적으로 제한되어 있습니다:
| Constraint | Limit |
|---|---|
| 함수 정의 불가 | 사용자 정의 함수를 정의할 수 없습니다 |
| 반복문/재귀 불가 | 반복(iteration)은 지원되지 않습니다 |
| 변수 변이 불 가 | 모든 표현식은 순수하며, 할당이 없습니다 |
| 외부 호출 불가 | API나 서비스를 호출할 수 없습니다 |
| 시스템 호출 불가 | 파일 시스템, 네트워크, OS에 접근할 수 없습니다 |
| 최대 표현식 깊이 | 256단계 중첩 |
| 최대 AST 노드 수 | 표현식당 1000개 노드 |
이러한 제약은 모든 Value DSL 표현식이 부작용 없이 제한된 시간 내에 종료되도록 보장하여, 런타임을 완전히 결정론적으로 만듭니다.