Osprey: 규칙 엔진 오픈 소 (새 탭에서 열림)
Discord는 실시간 안전 대응을 위해 개발한 규칙 엔진 Osprey를 ROOST 및 internet.dev 팀과 오픈소스로 공개했다. Osprey는 초당 수천 건의 이벤트를 처리하고, Python 기반 규칙 언어로 탐지 정책을 빠르게 배포하며, 판정 결과와 실행 과정을 추적할 수 있도록 설계됐다. 이를 통해 플랫폼은 새로운 위협에 대응하는 데 필요한 엔지니어링 부담을 줄이고, 탐지 결과를 다음 규칙 개선에 활용할 수 있다.
Osprey를 개발한 배경과 목표
- 온라인 플랫폼은 스팸, 사기, 악성 사용자 등 유사한 안전 문제를 반복적으로 해결해야 한다.
- Osprey는 각 기업이 안전 도구를 처음부터 만들지 않도록 재사용 가능한 규칙 엔진을 제공한다.
- 주요 요구사항은 다음과 같다.
- 대규모 실시간 처리: 초당 수천 건의 이벤트를 처리하고 플랫폼 성장에 맞춰 확장
- 신속한 대응: 표현력 있는 규칙을 작성해 수분 내 적용
- 명확한 판정: 활동을 안전, 의심, 악성 등으로 판단할 수 있는 결과 제공
- 실행 과정 공개: 어떤 규칙이 실행됐고 오류가 발생했는지 확인 가능
- 지속적인 학습: 탐지 결과와 조사 내용을 새로운 규칙 개선에 반영
- 확장성: 앞으로 등장할 새로운 공격 패턴과 기능을 수용
전체 처리 구조
- Osprey는 플랫폼에서 발생한 Action을 입력으로 받는다.
- Action은 다음 방식으로 전달할 수 있다.
- gRPC를 통한 동기 처리
- 메시지 큐를 통한 비동기 처리
- 입력된 Action은 SML로 작성된 Rules를 거친다.
- 규칙은 **UDF(User Defined Function)**로 확장할 수 있다.
- 실행 과정에서 Features와 Effects가 생성된다.
- 일부 Effects인 Verdict는 동기 요청자에게 즉시 판정 결과를 반환한다.
- 모든 출력은 Apache Druid 클러스터로 전송되어 조사용 UI에서 검색·분석된다.
Action: 규칙 엔진의 입력 이벤트
- Action은 Osprey에 전달되는 이벤트이며, 각 이벤트 유형은 고유한 ID와 스키마를 가진다.
- 사실상 호출자가 원하는 데이터를 담은 JSON 객체로 구성된다.
- 예를 들어
user_login_attempted이벤트에는 사용자 ID, 이름, 이메일, IP 주소 등을 포함할 수 있다. - 이벤트 스키마를 애플리케이션에 맞게 정의할 수 있어 로그인, 메시지 전송, 계정 생성 등 다양한 활동을 처리할 수 있다.
Rule과 SML 규칙 언어
- Rule은 Osprey의 핵심 구성 요소로, 특정 조건이 충족됐을 때 수행할 조치를 정의한다.
- SML(Some Made-up Language)은 Python을 기반으로 한 규칙 언어다.
- 기술 지식이 많지 않은 운영·안전 담당자도 작성할 수 있도록 비교적 단순한 문법을 사용한다.
- 규칙은 다른 규칙과 데이터를 참조할 수 있어 복잡한 탐지 로직도 구성 가능하다.
- 정적 검증을 통해 규칙 작성 방식을 강제할 수 있다.
- 변수명 규칙 검사
- 데이터 타입 검사
- 특정 Entity에 적용 가능한 Effect 검사
- 예시에서는 이메일이 특정 값과 일치하면 해당 사용자의 Entity에
spammer라벨을 추가한다.EntityJson으로 사용자 ID를 추출JsonData로 이메일을 추출Rule로 스팸 사용자 조건 정의WhenRules로 조건 충족 시LabelAdd실행
UDF: 규칙 언어를 확장하는 Python 함수
- UDF는 실제 Python으로 작성되며 SML 규칙 어디서든 호출할 수 있다.
Rule,WhenRules,JsonData등 Osprey의 기본 기능도 UDF로 구현되어 있다.- 사용자가 자체 UDF를 추가해 제품별 기능이나 외부 서비스 연동을 구현할 수 있다.
- 예를 들어 외부 머신러닝 서비스에 링크를 전달해 스팸 점수인
0~1범위의 값을 받아 규칙 조건으로 사용할 수 있다. - UDF는 다음과 같은 실행 정보를 정의할 수 있다.
- 어떤 기능 범주에 속하는지
- 비동기 실행 여부
- 외부 서비스 접근 방식
- 실행 결과의 타입
- 따라서 규칙 엔진 자체를 수정하지 않고도 새로운 탐지 모델, 데이터 소스, 내부 서비스를 연결할 수 있다.
Feature: 실행 결과로 생성되는 데이터
- Feature는 Osprey의 전역 네임스페이스에 등록된 변수다.
- 모든 Feature는 고유한 이름을 가져야 한다.
- 변수명 앞에
_를 붙이면 Feature로 외부에 내보내지 않고 현재 파일의 로컬 변수로 유지할 수 있다. - 실행 결과인 Feature는 Druid에 전송·색인된다.
- 이후 조사 UI에서
UserEmail == 'despicable@example.com'처럼 특정 Feature 값을 기준으로 이벤트를 검색할 수 있다. - 예시의
UserId와UserEmail은 모두 Feature다.
Entity: 효과를 적용할 수 있는 지속적 대상
- Entity는 Feature의 특수한 형태다.
- 모든 Entity는 Feature지만, 모든 Feature가 Entity인 것은 아니다.
- Discord에서는 사용자, 서버, 이메일처럼 지속적으로 추적할 수 있는 대상을 Entity로 표현한다.
- Entity에는 라벨, 분류, 신호 등의 Effect를 적용할 수 있다.
- Entity 유형에 따라 적용 가능한 Effect가 달라지며, 이를 정적 검증으로 제한한다.
- Osprey UI에서 Entity를 선택하면 해당 대상의 과거 활동과 처리 이력을 확인하는 Entity View로 이동할 수 있다.
Effect와 Verdict
- Effect는 하나 이상의 Rule이 참으로 평가됐을 때 발생하는 결과 또는 조치다.
- Effect는 실행 전에 검증되며, 실행이 끝난 뒤 집계해 처리된다.
- Entity에 라벨·분류·신호를 부여하는 작업이 대표적인 Effect다.
- 동기 Action의 경우 Verdict Effect를 통해 호출자에게 규칙의 판정 결과를 반환할 수 있다.
- 이를 활용하면 로그인이나 콘텐츠 게시 요청을 즉시 허용·차단하거나 추가 조사를 요구하는 흐름을 만들 수 있다.
실용적인 활용 방향
Osprey는 이벤트 수집, Python 기반 규칙 작성, 외부 탐지 서비스 연동, Druid 기반 조사까지를 하나의 구조로 제공한다. 새로운 위협에 자주 대응해야 하는 플랫폼이라면 규칙을 애플리케이션 코드와 분리하고, 정적 검증과 실행 추적을 갖춘 Osprey 같은 엔진을 활용하는 것이 운영 속도와 투명성을 높이는 방법이 될 수 있다.