본문으로 건너뛰기
피드

Lexega — SQL을 정적 분석해서 위험 시그널을 잡아내는 가드레일 도구

backend 약 5분
vote
0
댓글
북마크

SQL을 결정론적으로 파싱해서 시맨틱 시그널을 추출하고, 정책 기반으로 block/warn/allow를 판단하는 도구. CTE 경계를 넘는 컬럼 리니지 분석, Jinja/dbt 템플릿 지원, 커스텀 YAML 룰 등이 특징.

  • 1

    SQL → AST → 시맨틱 추출 → 시그널 → 룰 매칭 → 정책 평가의 결정론적 파이프라인

  • 2

    CTE 경계를 넘는 컬럼 리니지로 LEFT JOIN이 INNER로 변환되는 흔한 버그 탐지

  • 3

    Jinja/dbt 템플릿 자동 렌더링 후 분석, 변수별 다른 리스크 프로파일 감지

  • 4

    YAML로 커스텀 룰 정의, 빌트인 룰 오버라이드, 환경별 정책 분리

뭘 하는 건지

  • SQL PR 리뷰할 때 "diff가 화면보다 큰" 상황, 다들 겪어봤을 거임. 테스트는 통과하는데 위험한 구문 하나가 슬쩍 빠져나가는 그 실패 모드를 잡기 위한 도구가 Lexega
  • 핵심 컨셉은 SQL을 실행하기 전에 결정론적(deterministic)이고 실행 가능한 "시그널"로 변환한 뒤, 정책(policy)으로 판단하는 것. SQL 가드레일 레이어라고 보면 됨

파이프라인 구조

  • SQL 텍스트 → 렉서/파서 → 시맨틱 추출 → 시그널(카테고리/표면/조건) → 룰 매칭 → 정책 평가 → decision.json (allow/warn/block)
  • 파이프라인의 어떤 부분도 확률적이지 않음. 같은 입력이면 항상 같은 시그널이 나옴. AI 생성 SQL이 늘어나는 상황에서 이 결정론성이 핵심 셀링 포인트임

인상적인 예시: CTE 경계를 넘는 컬럼 리니지 분석

  • 멀쩡해 보이는 쿼리에서 LEFT JOIN + CTE 조합의 흔한 버그를 잡아냄:
    • CTE 안에서 LEFT JOIN으로 customers를 붙이고
    • 바깥 쿼리에서 WHERE tier = 'enterprise' 필터를 걸면
    • tier가 nullable 컬럼(customers 측)이라 LEFT JOIN이 사실상 INNER JOIN으로 변환
  • 이걸 잡으려면 CTE 안의 LEFT JOIN에서 nullable 사이드 파악 → SELECT 리스트의 컬럼 출처 추적 → CTE 경계를 넘어 외부 쿼리까지 리니지 추적이 필요함. 단순 패턴 매칭으로는 불가능한 수준

💡

> 이건 분석 코드에서 가장 흔한 SQL 버그 중 하나임. LEFT JOIN과 필터가 같은 스코프에 있지도 않아서 사람이 리뷰로 잡기 매우 어려움.

시맨틱 Diff

  • 텍스트 diff로는 "한 줄 바뀜"인 변경이 실제로 뭘 의미하는지 알려줌
  • 예: JOIN 조건에서 customer_idbilling_customer_id로 바뀌면 → "ORDERS와 CUSTOMERS 간 조인 조건이 변경됨"이라는 시맨틱 시그널을 뱉음

Jinja/dbt 지원

  • dbt 프로젝트 안에서 실행하면 자동으로 Jinja 템플릿을 렌더링해서 분석함. ref(), source(), config() 해석 포함
  • 같은 템플릿이라도 변수에 따라 리스크가 완전히 달라지는 걸 잡아냄:
    • safe_mode=falseDELETE FROM production.users; (WHERE 없음) → CRITICAL 시그널
    • safe_mode=trueDELETE ... WHERE created_at < ... → 시그널 없음

커스텀 룰 & 정책

  • 빌트인 룰 수백 개 + YAML로 커스텀 룰 정의 가능. 플러그인이나 코딩 필요 없음
  • 예: ANALYTICS.ORDERS ↔ ANALYTICS.CUSTOMERS 간 JOIN 타입이 INNER에서 LEFT/CROSS로 바뀌면 prod에서 차단하는 룰을 YAML 한 줄로 정의
  • 빌트인 룰도 오버라이드 가능 — 예를 들어 swap-and-drop 패턴 쓰는 팀이면 SCHEMA-DROP 룰을 Critical에서 Low로 낮출 수 있음
  • 정책은 환경별로 다르게 적용 가능: prod는 block, staging은 warn, dev는 allow

CI/CD 통합

  • lexega-sql analyze로 CI에 게이트로 연결 가능. 환경 컨텍스트 + 정책 파일로 decision.json 산출
  • 시그널(감지) → 룰(심각도) → 정책(조치) → 예외(감사 가능한 시간 범위 오버라이드)로 계층이 깔끔하게 분리되어 있음

AI 생성 SQL이 늘어나면서 사람이 모든 PR을 리뷰하기 어려워지는 상황에서 결정론적 가드레일의 가치가 커지고 있음.

댓글

댓글

댓글을 불러오는 중...

backend

Go에서 Rust로 옮길 때 진짜로 바뀌는 것들

이 글은 Go 백엔드 서비스를 Rust로 옮길 때 속도보다 컴파일 타임 보장, 런타임 트레이드오프, 개발자 경험이 더 중요하다고 설명한다. nil 패닉, 데이터 레이스, 에러 처리, 제네릭, 비동기 모델, 마이그레이션 전략까지 실무 관점에서 Go와 Rust를 길게 비교한다.

backend

Python 3.15에서 헤드라인은 못 탔지만 꽤 쓸만한 기능들

Python 3.15에는 lazy imports나 Tachyon profiler 같은 큰 기능 말고도 실무에서 바로 체감될 만한 작은 개선들이 들어가. TaskGroup 취소, 컨텍스트 매니저 데코레이터 개선, 스레드 안전 이터레이터처럼 평소 애매하게 불편했던 지점들이 꽤 깔끔해졌어.

backend

심평원, DUR부터 의료영상 심사까지 클라우드로 갈아엎는다

심평원이 정보시스템 클라우드 전환과 함께 병·의원 업무에 직접 닿는 DUR, 의료영상 AI 심사, 요양급여내역 조회 시스템을 고도화한다. 핵심은 설치형 프로그램 중심이던 연계를 웹과 API 기반으로 넓히고, 진료·청구 과정에서 실시간 확인과 자동 판독을 강화하는 쪽이다.

backend

윈도우 에러 코드 7번 ‘ERROR_ARENA_TRASHED’는 어디서 왔을까

ERROR_ARENA_TRASHED는 Win32에서 실제로 쓰이는 현대적 에러라기보다 MS-DOS 시절 메모리 관리 구조에서 넘어온 잔재야. MS-DOS가 메모리 블록 앞의 arena 시그니처를 훑다가 예상한 값이 아니면 ‘arena가 망가졌다’고 보고 이 에러를 냈다는 이야기야.

backend

C/C++ 컴파일러의 느슨한 메모리 동시성 버그를 자동으로 잡는 박사논문

C와 C++ 컴파일러에서 relaxed memory 동시성 버그를 찾는 자동 테스트 프레임워크를 다룬 박사논문이 공개됐어. Téléchat, Atomic-mixer 같은 도구로 소스 수준 동작과 컴파일된 프로그램 동작을 비교하고, LLVM과 GCC 툴체인에서 실제 버그를 찾아낸 내용이 핵심이야.