표현식 언어의 유연성 확보: cel-go 매크로 시스템 소개
cel-go는 고속, 이식 가능하며 비튜링 완전성을 갖춘 점진적 타입 시스템을 제공하는 표현식 평가 라이브러리입니다. 그 핵심 기능 중 하나인 매크로 시스템은 사용자가 표현식 문법을 확장할 수 있게 하여, 복잡한 로직을 간결하고 직관적인 형태로 표현할 수 있도록 합니다. 본 문서에서는 매크로 시스템의 작동 원리와 실제 적용 방법을 단계별로 설명합니다.
매크로의 개념과 역할
매크로는 컴파일 시점에 특정 구문을 더 복잡한 표현식으로 변환하는 메커니즘입니다. cel-go에서는 이를 문법적 당근(구문 캡슐화)으로 활용하여, 반복적인 코드 작성이나 난이도 높은 표현을 쉽게 처리할 수 있습니다. 기본적으로 parser/macro.go 파일에서 정의된 Macro 인터페이스를 통해 매크로의 행동을 규명합니다.
type Macro interface {
Function() string
ArgCount() int
IsReceiverStyle() bool
MacroKey() string
Expander() MacroExpander
}
이 인터페이스는 매크로의 이름, 인자 개수, 호출 스타일(수신자 기반 여부), 매칭 키, 그리고 확장 로직을 포함합니다.
내장 매크로 기능 분석
cel-go는 일반적인 데이터 조작 작업을 위한 여러 내장 매크로를 제공합니다.
집합 조건 검사 매크로
all: 모든 요소가 조건을 만족하는지 확인합니다. 예:[1, 2, 3].all(x, x > 0)→trueexists: 최소 하나의 요소만 조건을 만족하면true반환. 예:[1, 2, 3].exists(i, i % 2 == 1)→truefilter: 조건에 부합하는 요소들만 추출. 예:[1, 2, 3, 4].filter(x, x % 2 == 0)→[2, 4]
필드 존재 여부 확인 매크로
has 매크로는 프로토콜 버퍼 메시지의 필드 존재 여부 또는 맵의 키 존재 여부를 검사합니다.
has(user.profile) // user 객체에 profile 필드가 있는지 확인
has({'name': 'Alice'}.name) // name 키가 존재하는지 확인
사용자 정의 매크로 구현 방법
기존 매크로로 충족되지 않는 경우, 직접 매크로를 생성할 수 있습니다. 핵심은 MacroExpander 함수를 정의하고, 이를 등록하는 것입니다.
type MacroExpander func(eh ExprHelper, target ast.Expr, args []ast.Expr) (ast.Expr, *common.Error)
예시: 제곱 연산 매크로
func MakePowerSqr(eh ExprHelper, target ast.Expr, args []ast.Expr) (ast.Expr, *common.Error) {
if len(args) != 1 {
return nil, eh.NewError(args[0].ID(), "square requires exactly one argument")
}
return eh.NewCall(operators.Mul, args[0], args[0]), nil
}
// 매크로 생성 및 등록
SquareMacro := NewGlobalMacro("square", 1, MakePowerSqr,
MacroDocs("숫자의 제곱을 계산"),
MacroExamples("square(5) // 25"))
env, err := cel.NewEnv(cel.Macros(SquareMacro))
if err != nil { /* 에러 처리 */ }
등록 후 사용:
square(5) // 25
square(3 + 4) // 49 (3+4 먼저 계산 후 제곱)
고급 기능 활용
변수 길이 인자 매크로를 통해 동적 인자 처리가 가능합니다.
MaxMacro := NewGlobalVarArgMacro("max", MakeMax,
MacroDocs("주어진 인자 중 최대값 반환"),
MacroExamples("max(1, 5, 3) // 5"))
또한, 문서화와 예제를 함께 추가함으로써 다른 개발자들이 쉽게 이해하고 사용할 수 있도록 할 수 있습니다.
실천 팁과 권장 사항
- 명명 규칙: 명확하고 의미 있는 이름을 사용하세요. 예:
isEmailValid보다는isValidEmail가 더 적절합니다. - 오류 처리: 잘못된 인자 조합에는 구체적인 오류 메시지를 반환하세요.
- 성능 최적화: 매크로 확장 로직이 너무 복잡하지 않도록 주의하세요. 자주 사용되는 매크로는 결과 캐싱을 고려할 수 있습니다.
cel-go의 매크로 시스템은 표현식 언어의 표현력을 획기적으로 향상시킬 수 있는 강력한 도구입니다. 내장 기능을 활용하거나, 필요에 따라 자체 매크로를 설계함으로써, 코드의 가독성과 유지보수성을 크게 개선할 수 있습니다.
시작하려면 다음 명령어로 레포지토리를 클론하세요:
git clone https://gitcode.com/gh_mirrors/ce/cel-go
그 후, 필요한 패키지를 가져옵니다:
import (
"github.com/google/cel-go/cel"
"github.com/google/cel-go/parser"
)
이제 표현식 언어를 더욱 유연하게 확장할 준비가 되었습니다.