이 문서는 Common Expression Language (CEL)의 통합 API 문서 참조 역할을 합니다. 공식 CEL 스택 전반에서 시그니처, 동작, 지원 상태를 나타내는 모든 매크로, 연산자, 표준 함수를 나열합니다.
언어 동작 및 사양에 대한 자세한 내용은 CEL 언어 정의를 참고하세요.
스택 버전
이 참조 문서는 다음 버전의 CEL 스택을 기반으로 합니다.
- CEL Go:
v0.30.0이상 - CEL C++:
v0.16.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) |
목록의 요소 중 정확히 하나가 조건자를 충족하는지 테스트합니다. 서명: 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임)예: 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 지원)예: 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 지원)예: 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 지원)예: 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 지원)예: 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 지원)예: 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 지원)예: 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 지원)예: 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 지원)예: 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 지원)예: 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 지원)예: 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) | ✗ |
format |
printf 스타일 자리표시자를 사용하여 문자열의 형식을 지정합니다. 서명: string.format(list) -> string예: "str: %s, int: %d".format(["a", 1]) // "str: a, int: 1" |
✓ (v0.14.0) | ✓ (v0.11.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 승인 제어)을 위해 설계되었습니다.
공식 언어 정의, 문법, 적합성 평가 도구는 CEL 정책 사양을 참고하세요.
정책 컴파일러는 이러한 YAML 정책을 단일 표준 CEL AST로 컴파일합니다. 즉, 표준 CEL 런타임과 완전히 호환되며 모든 성능 및 안전 보장을 상속합니다.