이 문서는 Common Expression Language (CEL)의 통합 API 문서 참조 역할을 합니다. 공식 CEL 스택 전반에서 시그니처, 동작, 지원 상태를 나타내는 모든 매크로, 연산자, 표준 함수를 나열합니다.
언어 동작 및 사양에 대한 자세한 내용은 CEL 언어 정의를 참고하세요.
스택 버전
이 참조 문서는 다음 버전의 CEL 스택을 기반으로 합니다.
- CEL Go:
v0.29.2이상 - CEL C++:
v0.15.0 - CEL Java:
v0.13.1 - CEL Python:
v0.1.3 - CEL C: 개발 스냅샷 (미출시)
GitHub 미러
CEL의 공식 구현은 GitHub의 cel-expr 조직 아래에 미러링됩니다.
1. 핵심 매크로
이러한 매크로는 컴파일 시간에 확장되는 기본 제공 매크로입니다.
| Macro | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
has(container.field) |
필드가 메시지에 있는지 또는 키가 맵에 있는지 테스트합니다. 서명: has(container.field) -> bool예: has(request.auth.claims.email) |
✓ | ✓ | ✓ | ✓ | ✓ |
list.all(var, predicate) |
목록의 모든 요소가 조건자를 충족하는지 테스트합니다. 서명: list.all(var, predicate) -> bool예: [1, 2, 3].all(x, x > 0) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.exists(var, predicate) |
목록의 요소 중 하나 이상이 조건자를 충족하는지 테스트합니다. 서명: list.exists(var, predicate) -> bool예: [1, 2, 3].exists(x, x > 2) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.exists_one(var, predicate) |
목록의 요소 중 정확히 1개가 조건자를 충족하는지 테스트합니다. 서명: list.exists_one(var, predicate) -> bool예: [1, 2, 3].exists_one(x, x == 2) // true |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.filter(var, predicate) |
조건에 따라 목록의 요소를 필터링합니다. 서명: list.filter(var, predicate) -> list예: [1, 2, 3].filter(x, x > 1) // [2, 3] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.map(var, transform) |
표현식을 사용하여 목록의 각 요소를 변환합니다. 서명: list.map(var, transform) -> list예: [1, 2, 3].map(x, x * 2) // [2, 4, 6] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
list.map(var, filter, transform) |
필터 조건자를 충족하는 목록의 요소를 변환합니다. 서명: list.map(var, filter, transform) -> list예: [1, 2, 3].map(x, x > 1, x * 2) // [4, 6] |
✓ | ✓ | ✓ | ✓ | ✓¹ |
¹ 매크로는 호스트 컴파일러에 의해 컴파일 중에 컴프리헨션으로 확장되므로 C 런타임에서 지원됩니다.
2. 핵심 연산자
| 연산자 | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
산술 (+, -, *, /, %) |
표준 산술 연산입니다. 부정 (-x) 및 항등 (+x). 목록 연결 (list + list)은 Go, C++, Java, Python에서 지원됩니다.서명: T + T -> TT - T -> TT * T -> TT / T -> TT % T -> T-T -> T+T -> Tlist + list -> list예: 1 + 2 * 3 // 7[1] + [2] // [1, 2] |
✓ | ✓ | ✓ | ✓ | ✓² |
비교 (==, !=, <, <=, >, >=) |
표준 비교입니다. 숫자 비교는 이질적입니다 (예: 1 == 1.0).서명: T == T -> boolT != T -> boolT < T -> boolT <= T -> boolT > T -> boolT >= T -> bool예: x < 42.01 == 1.0 // true |
✓ | ✓ | ✓ | ✓ | ✓ |
논리 (!, &&, ||, ? :) |
논리 NOT, AND, OR, 삼항 조건 연산자입니다. AND/OR 단락 회로 평가를 사용합니다. 서명: !bool -> boolbool && bool -> boolbool || bool -> boolbool ? T : T -> T예: x > 0 ? "positive" : "non-positive" |
✓ | ✓ | ✓ | ✓ | ✓ |
색인 생성 ([]) |
색인으로 목록의 요소에 액세스하거나 맵에서 키를 조회합니다. 서명: list[int] -> Tmap[K] -> V예: tags[0]users['john'] |
✓ | ✓ | ✓ | ✓ | ✓ |
멤버십 (in) |
요소가 목록에 있는지 또는 키가 맵에 있는지 확인합니다. 서명: T in list -> boolK in map -> bool예: 'admin' in roles |
✓ | ✓ | ✓ | ✓ | ✓ |
² 목록 연결 (list + list)은 C 런타임에서 지원되지 않지만 다른 산술 연산자는 지원됩니다.
3. 핵심 기능
일반 및 문자열 함수
| 함수 | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
size |
문자열 (문자), 바이트, 목록 또는 지도의 크기를 반환합니다. 서명: size(T) -> int (여기서 T는 string, bytes, list 또는 map임)<br /><br />**Examples:**<br />size("hello") // 5` |
✓ | ✓ | ✓ | ✓ | ✓ |
contains |
문자열에 하위 문자열이 포함되어 있는지 여부를 반환합니다. 서명: string.contains(string) -> bool예: "hello".contains("ell") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
startsWith |
문자열이 접두사로 시작하는지 여부를 반환합니다. 서명: string.startsWith(string) -> bool예: "hello".startsWith("he") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
endsWith |
문자열이 서픽스로 끝나는지 여부를 반환합니다. 서명: string.endsWith(string) -> bool예: "hello".endsWith("lo") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
matches |
문자열이 RE2 정규 표현식과 일치하는지 여부를 반환합니다. 서명: string.matches(string) -> bool예: "123".matches(r"^\d+$") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
날짜 및 시간 선택기 함수
이러한 함수는 google.protobuf.Timestamp 또는 google.protobuf.Duration에서 구성요소를 추출합니다.
| 함수 | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
getFullYear |
4자리 연도를 반환합니다. 서명: timestamp.getFullYear([tz]) -> int예: timestamp("2026-07-23T00:00:00Z").getFullYear() // 2026 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMonth |
월 (0~11)을 반환합니다. 서명: timestamp.getMonth([tz]) -> int예: timestamp("2026-07-23T00:00:00Z").getMonth() // 6 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfMonth |
월중 일을 반환합니다 (1~31). 서명: timestamp.getDayOfMonth([tz]) -> int예: timestamp("2026-07-23T00:00:00Z").getDayOfMonth() // 23 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfWeek |
요일 (0 = 일요일)을 반환합니다. 서명: timestamp.getDayOfWeek([tz]) -> int예: timestamp("2026-07-23T00:00:00Z").getDayOfWeek() // 4 |
✓ | ✓ | ✓ | ✓ | ✗ |
getDayOfYear |
연중 일 (0~365)을 반환합니다. 서명: timestamp.getDayOfYear([tz]) -> int예: timestamp("2026-07-23T00:00:00Z").getDayOfYear() // 203 |
✓ | ✓ | ✓ | ✓ | ✗ |
getHours |
시간 (0~23)을 반환합니다. 서명: timestamp.getHours([tz]) -> intduration.getHours() -> int예: duration("1h30m").getHours() // 1 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMinutes |
분을 반환합니다 (0~59). 서명: timestamp.getMinutes([tz]) -> intduration.getMinutes() -> int예: duration("1h30m").getMinutes() // 30 |
✓ | ✓ | ✓ | ✓ | ✗ |
getSeconds |
초 (0~59)를 반환합니다. 서명: timestamp.getSeconds([tz]) -> intduration.getSeconds() -> int예: duration("1h30m45s").getSeconds() // 45 |
✓ | ✓ | ✓ | ✓ | ✗ |
getMilliseconds |
밀리초 (0~999)를 반환합니다. 서명: timestamp.getMilliseconds([tz]) -> intduration.getMilliseconds() -> int예: duration("1.5s").getMilliseconds() // 500 |
✓ | ✓ | ✓ | ✓ | ✗ |
유형 변환
| 타겟 유형 | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
bool |
불리언으로 변환합니다. 서명: bool(bool) -> boolbool(string) -> bool예: bool("true") // true |
✓ | ✓ | ✓ | ✓ | ✓ |
bytes |
바이트로 변환합니다. 서명: bytes(bytes) -> bytesbytes(string) -> bytes예: bytes("hello") // b"hello" |
✓ | ✓ | ✓ | ✓ | ✓ |
double |
배정밀도 부동 소수점으로 변환합니다. 서명: double(double) -> doubledouble(int) -> doubledouble(uint) -> doubledouble(string) -> double예: double(1) // 1.0 |
✓ | ✓ | ✓ | ✓ | ✓ |
duration |
기간으로 변환합니다. 서명: duration(duration) -> durationduration(string) -> duration예: duration("1.5s") // 1.5s duration |
✓ | ✓ | ✓ | ✓ | ✓ |
int |
64비트 부호 있는 정수로 변환합니다. 서명: int(int) -> intint(uint) -> intint(double) -> int (0으로 반올림)int(string) -> intint(timestamp) -> int (에포크 이후 초)예: int(1.5) // 1 |
✓ | ✓ | ✓ | ✓ | ✓ |
string |
문자열로 변환합니다. 서명: string(T) -> string (bool, int, uint, double, bytes, timestamp, duration 지원)<br /><br />**Examples:**<br />string(1.5) // '1.5'` |
✓ | ✓ | ✓ | ✓ | ✓ |
timestamp |
타임스탬프로 변환합니다. 서명: timestamp(timestamp) -> timestamptimestamp(string) -> timestamp (RFC3339)예: timestamp("2026-07-23T00:00:00Z") |
✓ | ✓ | ✓ | ✓ | ✓ |
uint |
64비트 부호 없는 정수로 변환합니다. 서명: uint(uint) -> uintuint(int) -> uintuint(double) -> uintuint(string) -> uint예: uint(1) // 1u |
✓ | ✓ | ✓ | ✓ | ✓ |
dyn |
타입 검사를 위해 값을 동적 타입으로 변환합니다. 서명: dyn(T) -> dyn예: dyn([1, "two"]) |
✓ | ✓ | ✓ | ✓ | ✗ |
type |
값의 유형을 반환합니다. 서명: type(T) -> type예: type(1) // int |
✓ | ✓ | ✓ | ✓ | ✗ |
4. 확장 프로그램 (라이브러리)
바인딩 라이브러리
| 함수 | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
cel.bind |
중복 평가를 방지하기 위해 로컬 변수를 바인딩합니다. 서명: cel.bind(varName, initExpr, resultExpr) -> T예: cel.bind(x, a + b, x * x) |
✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
사용 설정 방법
- 이동:
ext.Bindings()을cel.NewEnv()에 전달합니다. - C++:
CompilerBuilder에BindingsCompilerLibrary()추가 (런타임은 자동으로 처리됩니다.) - Java:
CelCompiler및CelRuntime빌더에CelExtensions.bindings()를 추가합니다. - Python:
cel_expr_python.ext.ext_bindings를 가져오고cel.NewEnv(extensions=[...])에서ExtBindings()를 사용합니다.
인코더 라이브러리
| 함수 | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
base64.encode |
바이트를 base64 문자열로 인코딩합니다. 서명: base64.encode(bytes) -> string예: base64.encode(b"hello") // "aGVsbG8=" |
✓ (v0.6.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
base64.decode |
base64 문자열을 바이트로 디코딩합니다. 잘못된 입력에서 오류가 발생합니다. 서명: base64.decode(string) -> bytes예: base64.decode("aGVsbG8=") // b"hello" |
✓ (v0.6.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
json.encode |
CEL 값을 JSON 문자열로 직렬화합니다. 서명: json.encode(dyn) -> string예: json.encode([1, 2]) // "[1,2]" |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
사용 설정 방법
- 이동:
ext.Encoders()을cel.NewEnv()에 전달합니다. - C++:
- 컴파일러:
CompilerBuilder에EncodersCompilerLibrary()추가 - 런타임:
FunctionRegistry에서RegisterEncodersFunctions()호출
- 컴파일러:
- Java:
CelCompiler및CelRuntime빌더에CelExtensions.encoders()를 추가합니다. - Python:
cel_expr_python.ext.ext_encoders를 가져오고cel.NewEnv(extensions=[...])에서ExtEncoders()를 사용합니다.
수학 라이브러리
| 함수 | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
math.greatest |
숫자 인수 (또는 숫자 목록) 중 가장 큰 값을 반환합니다. 서명: math.greatest(arg, ...) -> T예: math.greatest(1, 3, 2) // 3 |
✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
math.least |
숫자 인수 (또는 숫자 목록) 중 가장 작은 값을 반환합니다. 서명: math.least(arg, ...) -> T예: math.least([1, 3, 2]) // 1 |
✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
math.abs |
절댓값입니다. 서명: math.abs(T) -> T (int, uint, double 지원)<br /><br />**Examples:**<br />math.abs(-1) // 1` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.sqrt |
제곱근입니다. 서명: math.sqrt(T) -> double (int, uint, double 지원)<br /><br />**Examples:**<br />math.sqrt(9) // 3.0` |
✓ (v0.25.1) | ✓ (v0.12.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
math.bitAnd |
비트 AND입니다. 서명: math.bitAnd(T, T) -> T (int, uint 지원)<br /><br />**Examples:**<br />math.bitAnd(5, 3) // 1` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitOr |
비트 OR입니다. 서명: math.bitOr(T, T) -> T (int, uint 지원)<br /><br />**Examples:**<br />math.bitOr(5, 3) // 7` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitXor |
비트별 XOR입니다. 서명: math.bitXor(T, T) -> T (int, uint 지원)<br /><br />**Examples:**<br />math.bitXor(5, 3) // 6` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitNot |
비트 NOT입니다. 서명: math.bitNot(T) -> T (int, uint 지원)<br /><br />**Examples:**<br />math.bitNot(1) // -2` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitShiftLeft |
비트 왼쪽 시프트입니다. 서명: math.bitShiftLeft(T, int) -> T (int, uint 지원)<br /><br />**Examples:**<br />math.bitShiftLeft(1, 2) // 4` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.bitShiftRight |
비트 오른쪽 시프트입니다. 서명: math.bitShiftRight(T, int) -> T (int, uint 지원)<br /><br />**Examples:**<br />math.bitShiftRight(4, 2) // 1` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.ceil |
올림 서명: math.ceil(double) -> double예: math.ceil(1.2) // 2.0 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.floor |
내림 서명: math.floor(double) -> double예: math.floor(1.8) // 1.0 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.round |
가장 가까운 정수로 반올림합니다. 서명: math.round(double) -> double예: math.round(1.5) // 2.0 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.trunc |
절삭 반올림 (0 방향) 서명: math.trunc(double) -> double예: math.trunc(-1.8) // -1.0 |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.isInf |
double이 양의 무한대인지 음의 무한대인지 확인합니다. 서명: math.isInf(double) -> bool예: math.isInf(1.0/0.0) // true |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.isNaN |
double이 NaN인지 확인합니다. 서명: math.isNaN(double) -> bool예: math.isNaN(0.0/0.0) // true |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.isFinite |
double이 유한한지 확인합니다. 서명: math.isFinite(double) -> bool예: math.isFinite(1.2) // true |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
math.sign |
값의 부호 (-1, 0 또는 1)를 반환합니다. 서명: math.sign(T) -> T (int, uint, double 지원)<br /><br />**Examples:**<br />math.sign(-42) // -1` |
✓ (v0.21.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
사용 설정 방법
- 이동:
ext.Math()을cel.NewEnv()에 전달합니다. - C++:
- 컴파일러:
CompilerBuilder에MathCompilerLibrary()추가 - 런타임:
FunctionRegistry에서RegisterMathExtensionFunctions()호출
- 컴파일러:
- Java:
CelCompiler및CelRuntime빌더에CelExtensions.math()를 추가합니다. - Python:
cel_expr_python.ext.ext_math를 가져오고cel.NewEnv(extensions=[...])에서ExtMath()를 사용합니다.
Protos 라이브러리
| 함수 | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
proto.getExt |
proto2 확장 프로그램 필드를 가져오거나 설정되지 않은 경우 기본값을 가져옵니다. 서명: proto.getExt(msg, extName) -> T예: proto.getExt(msg, google.api.expr.test.int32_ext) |
✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
proto.hasExt |
proto2 확장 프로그램 필드가 설정되었는지 확인합니다. 서명: proto.hasExt(msg, extName) -> bool예: proto.hasExt(msg, google.api.expr.test.int32_ext) |
✓ (v0.13.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
사용 설정 방법
- 이동:
ext.Protos()을cel.NewEnv()에 전달합니다. - C++:
CompilerBuilder에ProtoExtCompilerLibrary()추가 (런타임은 자동으로 처리됩니다.) - Java:
CelCompiler및CelRuntime빌더에CelExtensions.protos()를 추가합니다. - Python:
cel_expr_python.ext.ext_proto를 가져오고cel.NewEnv(extensions=[...])에서ExtProto()를 사용합니다.
목록 라이브러리
| 함수 | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
distinct |
고유한 요소를 반환합니다. 서명: list.distinct() -> list예: [1, 2, 2].distinct() // [1, 2] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
flatten |
중첩된 목록을 평탄화합니다. 서명: list.flatten([depth]) -> list예: [[1], [2, 3]].flatten() // [1, 2, 3] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.7.1) | ✓ (v0.1.1) | ✗ |
lists.range |
정수 목록 [0, ..., n-1]를 반환합니다.서명: lists.range(int) -> list(int)예: lists.range(3) // [0, 1, 2] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
reverse |
목록을 반전합니다. 서명: list.reverse() -> list예: [1, 2].reverse() // [2, 1] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
slice |
하위 목록을 반환합니다 (시작은 포함, 끝은 제외). 서명: list.slice(start, end) -> list예: [1, 2, 3].slice(1, 3) // [2, 3] |
✓ (v0.17.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
sort |
비교 가능한 요소 목록을 정렬합니다. 서명: list.sort() -> list예: [3, 1, 2].sort() // [1, 2, 3] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
sortBy |
표현식에서 평가된 키를 기준으로 목록을 정렬합니다. 서명: list.sortBy(var, expr) -> list예: [{"val": 2}, {"val": 1}].sortBy(x, x.val) // [{"val": 1}, {"val": 2}] |
✓ (v0.22.0) | ✓ (v0.11.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
first |
첫 번째 요소를 선택사항으로 반환합니다. 선택적 확장 프로그램이 필요합니다. 서명: list.first() -> optional예: [1, 2].first() // optional(1) |
✓ (v0.23.0) | ✓ (v0.15.0) | ✓ (v0.11.0) | ✓ (v0.1.2) | ✗ |
last |
마지막 요소를 선택사항으로 반환합니다. 선택적 확장 프로그램이 필요합니다. 서명: list.last() -> optional예: [1, 2].last() // optional(2) |
✓ (v0.23.0) | ✓ (v0.15.0) | ✓ (v0.11.0) | ✓ (v0.1.2) | ✗ |
사용 설정 방법
- 이동:
ext.Lists()을cel.NewEnv()에 전달합니다. - C++:
- 컴파일러:
CompilerBuilder에ListsCompilerLibrary()추가 - 런타임:
FunctionRegistry에서RegisterListsFunctions()을 호출하고MacroRegistry에서RegisterListsMacros()을 호출합니다.
- 컴파일러:
- Java:
CelCompiler및CelRuntime빌더에CelExtensions.lists()를 추가합니다. - Python:
extensions목록에lists를 추가하여cel.EnvConfig를 통해 사용 설정합니다.
세트 보관함
| 함수 | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
sets.contains |
list1에 list2의 모든 요소가 포함되어 있는지 확인합니다. 서명: sets.contains(list1, list2) -> bool예: sets.contains([1, 2], [1]) // true |
✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.6.0) | ✓ (v0.1.1) | ✗ |
sets.equivalent |
목록이 집합 동등인지 (동일한 고유 요소 포함) 확인합니다. 서명: sets.equivalent(list1, list2) -> bool예: sets.equivalent([1, 2], [2, 1, 1]) // true |
✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.6.0) | ✓ (v0.1.1) | ✗ |
sets.intersects |
목록이 하나 이상의 요소를 공유하는지 확인합니다. 서명: sets.intersects(list1, list2) -> bool예: sets.intersects([1, 2], [2, 3]) // true |
✓ (v0.15.0) | ✓ (v0.10.0) | ✓ (v0.6.0) | ✓ (v0.1.1) | ✗ |
사용 설정 방법
- 이동:
ext.Sets()을cel.NewEnv()에 전달합니다. - C++:
- 컴파일러:
CompilerBuilder에SetsCompilerLibrary()추가 - 런타임:
FunctionRegistry에서RegisterSetsFunctions()호출
- 컴파일러:
- Java:
CelCompiler및CelRuntime빌더에CelExtensions.sets()를 추가합니다. - Python:
extensions목록에sets를 추가하여cel.EnvConfig를 통해 사용 설정합니다.
문자열 라이브러리
| 함수 | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
charAt |
색인의 문자를 반환합니다. 서명: string.charAt(int) -> string예: "hello".charAt(1) // "e" |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
indexOf |
부분 문자열이 처음으로 나타나는 위치의 색인을 반환하거나 -1을 반환합니다. 서명: string.indexOf(substr, [start]) -> int예: "hello".indexOf("l") // 2 |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
lastIndexOf |
하위 문자열의 마지막 발생 색인을 반환하거나 -1을 반환합니다. 서명: string.lastIndexOf(substr, [end]) -> int예: "hello".lastIndexOf("l") // 3 |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
join |
문자열을 연결합니다. 서명: list(string).join([separator]) -> string예: ["a", "b"].join("-") // "a-b" |
✓ (v0.10.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
split |
구분자로 문자열을 분할합니다. 서명: string.split(separator, [limit]) -> list(string)예: "a-b".split("-") // ["a", "b"] |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
substring |
하위 문자열을 반환합니다 (시작은 포함, 끝은 제외). 서명: string.substring(start, [end]) -> string예: "hello".substring(1, 3) // "el" |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
trim |
유니코드 공백을 자릅니다. 서명: string.trim() -> string예: " hello ".trim() // "hello" |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
replace |
old를 new로 바꿉니다. 서명: string.replace(old, new, [limit]) -> string예: "hello".replace("l", "w") // "hewwo" |
✓ (v0.4.0) | ✓ (v0.10.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
reverse |
유니코드 코드 포인트를 반전합니다. 서명: string.reverse() -> string예: "abc".reverse() // "cba" |
✓ (v0.18.0) | ✓ (v0.14.0) | ✓ (v0.13.0) | ✓ (v0.1.1) | ✗ |
lowerAscii |
ASCII 문자를 소문자로 변환합니다. 서명: string.lowerAscii() -> string예: "Hello".lowerAscii() // "hello" |
✓ (v0.6.0) | ✓ (v0.11.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
upperAscii |
ASCII 문자를 대문자로 변환합니다. 서명: string.upperAscii() -> string예: "Hello".upperAscii() // "HELLO" |
✓ (v0.6.0) | ✓ (v0.11.0) | ✓ (v0.2.0) | ✓ (v0.1.1) | ✗ |
quote |
안전한 인쇄를 위해 문자열을 이스케이프합니다. 서명: strings.quote(string) -> string예: strings.quote("a\tb") // "\"a\\tb\"" |
✓ (v0.14.0) | ✓ (v0.14.0) | ✓ (v0.13.0) | ✓ (v0.1.1) | ✗ |
사용 설정 방법
- 이동:
ext.Strings()을cel.NewEnv()에 전달합니다. - C++:
- 컴파일러:
CompilerBuilder에StringsCompilerLibrary()추가 - 런타임:
FunctionRegistry에서RegisterStringsFunctions()호출
- 컴파일러:
- Java:
CelCompiler및CelRuntime빌더에CelExtensions.strings()를 추가합니다. - Python:
cel_expr_python.ext.ext_strings를 가져오고cel.NewEnv(extensions=[...])에서ExtStrings()를 사용합니다.
정규 표현식 라이브러리
| 함수 | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
regex.replace |
일치하는 항목을 대체 문자열로 바꿉니다 (역참조 지원). 서명: regex.replace(target, pat, repl, [limit]) -> string예: regex.replace("123-456", r"(\d+)-(\d+)", r"\2-\1") // "456-123" |
✓ (v0.25.1) | ✓ (v0.13.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
regex.extract |
패턴의 첫 번째 일치 항목을 반환합니다 (캡처 그룹이 하나 있어야 함). 서명: regex.extract(target, pat) -> optional(string)예: regex.extract("a123b", r"(\d+)") // optional("123") |
✓ (v0.25.1) | ✓ (v0.13.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
regex.extractAll |
패턴의 모든 일치 항목을 반환합니다 (캡처 그룹이 하나 있어야 함). 서명: regex.extractAll(target, pat) -> list(string)예: regex.extractAll("a1b2", r"(\d+)") // ["1", "2"] |
✓ (v0.25.1) | ✓ (v0.13.0) | ✓ (v0.10.1) | ✓ (v0.1.1) | ✗ |
사용 설정 방법
- 이동:
ext.Regex()을cel.NewEnv()에 전달합니다. - C++:
- 컴파일러:
CompilerBuilder에RegexExtCompilerLibrary()추가 - 런타임:
FunctionRegistry에서RegisterRegexExtensionFunctions()호출
- 컴파일러:
- Java:
CelCompiler및CelRuntime빌더에CelExtensions.regex()를 추가합니다. - Python:
extensions목록에regex및optional를 추가하여cel.EnvConfig를 통해 사용 설정합니다.
2변수 컴프리헨션
| Macro | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
all |
키/색인 및 값에 대한 논리적 AND를 단락 회로로 연결합니다. 서명: list.all(i, v, pred) -> boolmap.all(k, v, pred) -> bool예: [1, 2].all(i, v, v > 0) // true |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
exists |
키/색인 및 값에 대한 논리적 OR을 단락합니다. 서명: list.exists(i, v, pred) -> boolmap.exists(k, v, pred) -> bool예: [1, 2].exists(i, v, v == 2) // true |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
existsOne |
정확히 하나의 쌍이 술어를 충족하는지 확인합니다. 서명: list.existsOne(i, v, pred) -> boolmap.existsOne(k, v, pred) -> bool예: [1, 2].existsOne(i, v, v == 2) // true |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
transformList |
목록/지도를 목록으로 변환/필터링합니다. 서명: list.transformList(i, v, [filter], transform) -> listmap.transformList(k, v, [filter], transform) -> list예: [1, 2].transformList(i, v, v * 2) // [2, 4] |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
transformMap |
목록/맵의 값을 맵으로 변환합니다 (키는 고정됨). 서명: list.transformMap(i, v, [filter], transform) -> mapmap.transformMap(k, v, [filter], transform) -> map예: [1, 2].transformMap(i, v, v * 2) // {0: 2, 1: 4} |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
transformMapEntry |
지도로 변환됩니다. 서명: list.transformMapEntry(i, v, [filter], transform_entry) -> mapmap.transformMapEntry(k, v, [filter], transform_entry) -> map예: [1, 2].transformMapEntry(i, v, {string(v): v * 2}) // {"1": 2, "2": 4} |
✓ (v0.22.0) | ✓ (v0.14.0) | ✓ (v0.11.0) | ✓ (v0.1.1) | ✗ |
사용 설정 방법
- 이동:
ext.TwoVarComprehensions()을cel.NewEnv()에 전달합니다. - C++:
- 컴파일러:
CompilerBuilder에ComprehensionsV2CompilerLibrary()추가 - 런타임:
FunctionRegistry에서RegisterComprehensionsV2Functions()을 호출하고MacroRegistry에서RegisterComprehensionsV2Macros()을 호출합니다.
- 컴파일러:
- Java:
CelCompiler및CelRuntime빌더에CelExtensions.comprehensions()를 추가합니다. - Python:
extensions목록에two-var-comprehensions을 추가하여cel.EnvConfig를 통해 사용 설정합니다.
네이티브 유형 라이브러리
| 기능 | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
| 네이티브 구조체 | CEL에서 호스트 네이티브 유형 (Go 구조체 / Java POJO)을 등록하고 인스턴스화합니다. 예: Account{id: 123} (CEL에서 인스턴스화된 Java POJO) |
✓ (v0.13.0) | ✗ | ✓ (v0.13.0) | ✗ | ✗ |
사용 설정 방법
- Go:
cel.NewEnv()에ext.NativeTypes(...)(리플렉션 유형 제공)을 전달합니다. - C++: 지원되지 않습니다.
- Java: Java 클래스를 제공하는
CelExtensions.nativeTypes()를CelCompiler및CelRuntime빌더에 추가합니다. - Python: 지원되지 않습니다.
네트워크 라이브러리
네트워크 라이브러리는 IP 주소와 CIDR 블록을 파싱, 검증, 조작하는 기능을 제공합니다.
| 함수 | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
ip |
문자열을 IP 주소로 파싱하거나 CIDR에서 IP를 추출합니다. 서명: ip(string) -> IPCIDR.ip() -> IP예: ip("192.168.0.1")cidr("192.168.0.0/24").ip() |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isIP |
문자열이 유효한 IP 주소인지 확인합니다. 서명: isIP(string) -> bool예: isIP("192.168.0.1") // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
ip.isCanonical |
IP 주소 문자열이 표준 형식인지 확인합니다. 서명: ip.isCanonical(string) -> bool예: ip.isCanonical("192.168.0.1") // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
cidr |
문자열을 CIDR 블록으로 파싱합니다. 서명: cidr(string) -> CIDR예: cidr("192.168.0.0/24") |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isCIDR |
문자열이 유효한 CIDR 블록인지 확인합니다. 서명: isCIDR(string) -> bool예: isCIDR("192.168.0.0/24") // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
containsIP |
CIDR 블록에 IP 주소가 포함되어 있는지 확인합니다. 서명: CIDR.containsIP(IP) -> boolCIDR.containsIP(string) -> bool예: cidr("192.168.0.0/24").containsIP(ip("192.168.0.1")) // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
containsCIDR |
CIDR 블록에 다른 CIDR 블록이 포함되어 있는지 확인합니다. 서명: CIDR.containsCIDR(CIDR) -> boolCIDR.containsCIDR(string) -> bool예: cidr("192.168.0.0/16").containsCIDR(cidr("192.168.1.0/24")) // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
family |
IP 패밀리 (IPv4의 경우 4, IPv6의 경우 6)를 반환합니다. 서명: IP.family() -> int예: ip("192.168.0.1").family() // 4 |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isGlobalUnicast |
IP가 전역 유니캐스트 주소인지 확인합니다. 서명: IP.isGlobalUnicast() -> bool예: ip("192.168.0.1").isGlobalUnicast() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLinkLocalMulticast |
IP가 링크-로컬 멀티캐스트 주소인지 확인합니다. 서명: IP.isLinkLocalMulticast() -> bool예: ip("224.0.0.1").isLinkLocalMulticast() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLinkLocalUnicast |
IP가 링크-로컬 유니캐스트 주소인지 확인합니다. 서명: IP.isLinkLocalUnicast() -> bool예: ip("169.254.0.1").isLinkLocalUnicast() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isLoopback |
IP가 루프백 주소인지 확인합니다. 서명: IP.isLoopback() -> bool예: ip("127.0.0.1").isLoopback() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isMask |
CIDR이 유효한 서브넷 마스크인지 확인합니다. 서명: CIDR.isMask() -> bool예: cidr("255.255.255.0/24").isMask() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
isUnspecified |
IP가 지정되지 않은 주소 (예: 0.0.0.0)인지 확인합니다.서명: IP.isUnspecified() -> bool예: ip("0.0.0.0").isUnspecified() // true |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
masked |
마스크 처리된 CIDR 블록을 반환합니다. 서명: CIDR.masked() -> CIDR예: cidr("192.168.0.1/24").masked() // 192.168.0.0/24 |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
prefixLength |
CIDR 블록의 프리픽스 길이를 반환합니다. 서명: CIDR.prefixLength() -> int예: cidr("192.168.0.0/24").prefixLength() // 24 |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
string |
IP 또는 CIDR을 문자열로 변환합니다. 서명: string(IP) -> stringstring(CIDR) -> string예: string(ip("192.168.0.1")) // "192.168.0.1" |
✓ (v0.29.0) | ✗ | ✗ | ✗ | ✗ |
사용 설정 방법
- 이동:
ext.Network()을cel.NewEnv()에 전달합니다. - C++: 지원되지 않습니다.
- Java: 지원되지 않습니다.
- Python: 지원되지 않습니다.
5. 고급 기능
고급 기능 요약
| 기능 | 설명 | Go | C++ | 자바 | Python | C |
|---|---|---|---|---|---|---|
| 부분 평가 | 입력이 누락된 상태로 평가합니다. 알 수 없는 값이나 단순화된 표현식을 반환합니다. | ✓³ | ✓⁴ | ✓⁴ | ✗ | ✗ |
| 비동기 평가 | 확장 프로그램 함수의 비차단 동시 실행 | ✓⁵ | ✗ | ✓⁶ | ✗ | ✗ |
| AST 검사기 | 정적 분석은 유형 검사 후 검사된 AST에서 실행됩니다. | ✓ | ✓ | ✓ | ✗ | ✗ |
| AST 옵티마이저 | 성능을 개선하기 위해 AST 재작성 (상수 폴딩, 인라이닝, CSE) | ✓ | ✓ | ✓ | ✗ | ✗ |
| CEL 정책 컴파일러 | YAML 기반 정책 구조를 표준 CEL AST로 컴파일합니다. | ✓ | ✓ | ✓ | ✗ | ✗ |
³ Go는 잔여 AST (잘린 AST) 생성을 지원합니다. ⁴ C++ 및 Java는 런타임에 UnknownSet / CelUnknownSet 반환을 지원하지만 잔여 AST 생성을 위한 공개 API를 노출하지는 않습니다. ⁵ Go는 AsyncBinding / AsyncOp를 사용하여 채널을 반환합니다. ⁶ Java는 CelAsyncRuntime를 사용하여 ListenableFuture를 반환합니다.
부분 평가 (알 수 없음)
부분 평가는 입력 변수 (인수)의 하위 집합만 알려진 경우 표현식을 평가할 수 있습니다. 실패하는 대신 평가에서 누락된 항목이나 단순화된 표현식을 나타내는 결과가 생성됩니다.
- Go: 완전 지원 알 수 없는 속성의 패턴으로
PartialActivation를 정의할 수 있습니다. 평가에서types.Unknown값을 반환합니다. Go는 평가할 수 없는 표현식 부분만 포함하는 가지치기되고 간소화된 AST인 잔여 AST (Env.ResidualAst) 생성을 지원합니다. - C++:
Unknown값을 지원합니다. 알 수 없는 속성 패턴은Activation::set_unknown_attribute_patterns을 통해 구성됩니다. 평가에서는UnknownSet을 반환합니다. 공개 API는 현재 잔여 AST 생성을 노출하지 않습니다. - Java:
Program.eval()에 전달된PartialVars를 통해 부분 평가를 지원합니다. 평가에서CelUnknownSet를 반환합니다. 공개 API는 현재 잔여 AST 생성을 노출하지 않습니다. - Python / C: 기본 지원 없음
비동기 평가
비동기 평가를 사용하면 CEL 표현식이 비동기적으로 실행되는 함수 (예: RPC 또는 데이터베이스 쿼리 실행)를 호출하고 결과가 제공될 때까지 평가를 차단하여 기본 실행 스레드를 차단하지 않을 수 있습니다.
- Go:
AsyncBinding및AsyncOp를 통해 비동기 함수 오버로드를 지원합니다. 비동기 함수는 Go 채널 (<-chan ref.Val)을 반환하며 인터프리터는 동시 실행과 동기화를 관리합니다. - Java:
CelAsyncRuntime및AsyncProgram을 통한 비동기 평가를 지원합니다.ListenableFuture를 사용하여 대기 중인 값을 나타내고, 미래가 해결되면 평가가 완료되도록 자동으로 유도합니다. - C++ / Python / C: 기본 지원이 없습니다.
AST 검사기
유효성 검사기는 프로그램이 실행되기 전에 도메인별 제약 조건을 적용하기 위해 유형 검사 후 확인된 AST에 정적 분석을 실행합니다.
- Go:
ASTValidator인터페이스를 지원합니다. 표준 유효성 검사기에는cel.validator.duration,cel.validator.timestamp,cel.validator.matches(정규식),cel.validator.homogeneous_literals,cel.validator.comprehension_nesting_limit이 포함됩니다. - C++:
cel::Validator를 지원합니다. 표준 검증에는AstDepthValidator,ComprehensionNestingLimitValidator,DurationLiteralValidator,HomogeneousLiteralValidator,MatchesValidator,TimestampLiteralValidator이 포함됩니다. - Java:
CelValidator및CelAstValidator을 지원합니다. 표준 검사기에는AstDepthLimitValidator,ComprehensionNestingLimitValidator,DurationLiteralValidator,HomogeneousLiteralValidator,RegexLiteralValidator,TimestampLiteralValidator이 포함됩니다. - Python / C: 직접 지원되지 않습니다.
AST 옵티마이저
최적화 프로그램은 실행 성능을 개선하기 위해 AST를 다시 작성합니다. 최적화 프로그램은 정적 최적화 프로그램과 런타임 최적화 프로그램의 두 가지 카테고리 중 하나에 속합니다. C++, Java, Go는 런타임 최적화를 지원합니다. CEL Java 및 Go는 정적 최적화 프로그램도 지원합니다. 일반적인 최적화에는 상수 폴딩 (상수 입력으로 하위 표현식 사전 평가) 및 공통 하위 표현식 제거 (CSE)가 포함됩니다.
- Go: 컴파일/계획 중에 AST 접기를 지원합니다.
- C++: 계획 시간에
cel::extensions::EnableConstantFolding확장 프로그램을 통해 상수 폴딩을 지원합니다. - Java:
CelOptimizer인터페이스를 지원합니다. 표준 최적화 프로그램에는ConstantFoldingOptimizer(부분 평가를 시뮬레이션하여 단락 회로 분기를 접을 수 있음),InliningOptimizer,SubexpressionOptimizer(CSE)이 포함됩니다. - Python / C: 직접 지원되지 않습니다.
CEL 정책 컴파일러
CEL 정책은 변수, 일치 블록, 조건부 출력, 중첩된 규칙과 함께 여러 CEL 표현식을 구성하기 위한 YAML 기반 형식입니다. 단일 CEL 표현식이 읽을 수 없게 되는 복잡한 정책 엔진 (예: Kubernetes 승인 제어)을 위해 설계되었습니다.
정책 컴파일러는 이러한 YAML 정책을 단일 표준 CEL AST로 컴파일합니다. 즉, 표준 CEL 런타임과 완전히 호환되며 모든 성능 및 안전 보장을 상속합니다.
- Go:
third_party/cel/go/policy를 통해 지원됩니다. - C++:
third_party/cel/cpp/policy를 통해 지원됩니다. - Java:
third_party/java/cel/policy를 통해 지원됩니다. - Python / C: 직접 지원되지 않습니다.