Ruby 정규 표현식 엔진 Exreg

Kevin Newton | A Ruby Regular Expression Engine

작성자
발행일
2026년 01월 06일

핵심 요약

  • 1 Exreg는 순수 Ruby로 구현된 유니코드 정규 표현식 엔진으로, Thompson 스타일 NFA 가상 머신을 채택하여 ReDoS 공격으로부터 안전합니다.
  • 2 기존 백트래킹 엔진과 달리 Exreg는 모든 경로를 병렬 처리하여 입력 크기에 선형적인 실행 시간을 보장하며, Onigmo와의 기능적 동등성을 목표로 합니다.
  • 3 Exreg는 파서, 컴파일러, VM으로 구성되며, 유니코드 데이터베이스, USet, ByteSet, 단일 인코딩(UTF-8) 처리 등 고유한 구현 방식을 특징으로 합니다.

도입

최근 순수 Ruby로 구현된 유니코드 정규 표현식 엔진인 exreg gem이 공개되었습니다. 이 엔진은 Ruby의 기존 정규 표현식 엔진인 Onigmo와 거의 동일한 기능을 지원하면서도, Thompson 스타일 NFA(비결정적 유한 오토마타) 가상 머신을 사용하여 치명적인 백트래킹으로 인한 ReDoS(정규 표현식 서비스 거부) 공격에 면역성을 가집니다. 본 글은 exreg의 개발 배경, 핵심 구현 방식, 그리고 향후 계획에 대해 상세히 설명합니다.

Exreg는 Russ Cox의 연구를 기반으로, 기존 백트래킹 엔진의 ReDoS 취약점(지수적 시간 복잡도)을 해결합니다. Thompson 스타일 NFA 엔진은 모든 경로를 병렬 시뮬레이션하여 입력 크기에 선형적인 실행 시간을 보장, 안정성을 제공합니다.

아키텍처는 파서(AST), 컴파일러(바이트코드), 가상 머신으로 구성됩니다. 주요 구현 특징은 다음과 같습니다.

유니코드 및 내부 데이터베이스

UCD 파일에서 바이너리 데이터베이스를 생성하고, 필요 시 코드포인트 집합을 로드합니다. 효율적인 처리를 위해 pack/unpack을 사용한 커스텀 바이너리 포맷을 적용했습니다.

USet 및 ByteSet을 통한 효율성

코드포인트는 USet 객체(반개 구간 컬렉션)에 저장되어 집합 연산을 효율적으로 처리하며, 컴파일 단계에서 제거됩니다. 바이트코드 실행 시에는 ByteSet 객체(8개의 32비트 정수 배열)를 활용, 비트 연산으로 빠른 바이트 멤버십 테스트를 지원합니다.

단순화된 인코딩 처리

Exreg는 Onigmo와 달리 유니코드 인코딩만 지원하며 (?u)를 기본으로 합니다. 명시적 인코딩이 없으면 UTF-8을 가정하고, 문자열을 바이트 단위로 처리하여 VM 내부에 바이트 표현을 인코딩함으로써 API를 단순화합니다.

결론

오랜 기간 구상해온 이 프로젝트를 마침내 공개하게 되어 기쁩니다. Onigmo 엔진과의 기능적 동등성을 달성하기 위해 역참조(backreferences) 및 룩어라운드(lookaround assertions)와 같이 백트래킹이 필요한 기능들을 추가할 계획입니다. 사용자 관점에서는 주어진 정규 표현식에 어떤 전략이 사용되는지 파악하여 신뢰할 수 없는 입력에 대한 안전성을 판단할 수 있도록 하는 것이 중요합니다. 또한, 현재 순수 인터프리터 방식인 VM에 JIT(Just-In-Time) 컴파일러를 도입하여 성능을 크게 향상시킬 가능성도 탐색할 예정입니다. 이 프로젝트에 대한 기여나 질문은 언제든지 환영합니다.

댓글 0

로그인이 필요합니다

댓글을 작성하거나 대화에 참여하려면 로그인이 필요합니다.

로그인 하러 가기

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!