JavaScript Stored Routines in Percona Server for MySQL: A New Era for Database Programmability

 

수십 년 동안 우리는 고통스러운 타협을 받아들여 왔습니다. 데이터베이스 안에서 로직을 구현하려면 SQL/PSM(Persistent Stored Modules)을 작성해야 했습니다. 이는 다루기 불편하고 디버깅이 어렵우며, 선언적(declarative) 성격을 띠기 때문에 알고리즘 처리에는 매우 부적합했습니다.

이 상황은 Percona Server 8.4.7-7 에서 끝납니다.

우리는 JS Stored Programs 를 Tech Preview 로 도입합니다. 엔터프라이즈 에디션이나 Oracle Cloud 로 제한되는 오라클의 구현과 달리, 우리는 오픈소스인 Google V8 엔진(Chrome 과 Node.js 를 구동하는 바로 그 엔진)을 통합했습니다.

그 결과, 완전히 오픈소스 환경에서 현대적인 프로그래밍 기능을 사용할 수 있게 되었습니다.

percona


 

기술 프리뷰로 출시를 준비하는 과정에서, JS 가 SQL 을 압도하는 가장 즉각적이고 영향력이 큰 활용 사례 세 가지를 먼저 강조하고자 합니다.

 

  1. 복잡한 데이터 검증 (“데이터 방화벽”)

SQL 의 CHECK 제약 조건은 유용하지만 한계가 있습니다. 이메일, URL, 국제 전화번호와 같은 복잡한 문자열을 검증해야 할 경우, SQL 에서는 SUBSTRING 과 REPLACE 를 끝없이 조합한 난잡한 코드에 빠질 수밖에 없습니다.

V8 엔진을 사용하면 자바스크립트의 네이티브 정규 표현식을 그대로 활용할 수 있습니다. 이를 통해 불필요하거나 잘못된 데이터가 디스크에 기록되기 전에 차단하는“데이터 방화벽”을 구축할 수 있습니다.

활용 사례: 잘못된 데이터 유입을 방지하기 위해, 데이터베이스 내부에서 이메일 주소의 유효성을 검증합니다.

 

CREATE FUNCTION validate_email_js(email VARCHAR(255))
RETURNS BOOLEAN LANGUAGE JS AS $$
  // Native JS Regex is powerful and readable
  const emailRegex = /^[^s@]+@[^s@]+.[^s@]+$/;
  return emailRegex.test(email);
$$;

mysql> SELECT validate_email_js("good@email.com");
+-------------------------------------+
| validate_email_js("good@email.com") |
+-------------------------------------+
|                                   1 |
+-------------------------------------+
1 row in set (0.01 sec)

mysql> SELECT validate_email_js("bad.email.com");
+------------------------------------+
validate_email_js("bad.email.com") |
+------------------------------------+
|                                  0 |
+------------------------------------+
1 row in set (0.02 sec)

 

  1. 네이티브 JSON 처리

MySQL 은 수년 전부터 JSON 타입을 지원해 왔지만, SQL 함수(JSON_EXTRACT, JSON_SET 등)를 사용해 JSON 을 조작하는 방식은 장황하고 직관적이지 않습니다. 반면 자바스크립트는 JSON 의 네이티브 언어입니다.

Percona Server 8.4.7-7 에서는 MySQL 의 JSON 타입을 자동으로 JS 객체로 마샬링합니다. 문자열 blobs 을 직접 파싱할 필요 없이, 객체 자체를 그대로 다루면 됩니다.

활용 사례: API 응답 가공(API Response Shaping). 필터링을 위해 거대한 JSON 데이터를 애플리케이션으로 가져오는 대신, 데이터베이스 안에서 필요한 형태로 가공함으로써 네트워크 비용을 절감할 수 있습니다.

 

CREATE FUNCTION normalize_order(raw_json JSON)
RETURNS JSON LANGUAGE JS AS $$
  // raw_json is already a JS object here
  return {
    id: raw_json.id,
    total: raw_json.items.reduce((acc, item) => acc + item.price, 0),
    tags: raw_json.metadata.tags.map(t => t.toLowerCase())
  };
$$;

mysql> SELECT normalize_order('{"id": 101, "items": [{"price": 10}, {"price": 20}], "metadata": {"tags": ["SALE"]}}');
+-------------------------------------------------------------+
| normalize_order(...)                                        |
+-------------------------------------------------------------+
| {"id": 101, "tags": ["sale"], "total": 30}                  |
+-------------------------------------------------------------+
1 row in set (0.01 sec)

 

  1. 연산 오프로딩(차원이 다른 성능 향상)

SQL 엔진은 데이터 조회(IO)에 최적화되어 있으며, 무거운 연산(CPU) 작업을 위한 구조는 아닙니다. SQL 로 수학 연산, 반복문, 암호화 해시 등을 처리하려 하면 오버헤드로 인해 성능이 크게 떨어집니다.

V8 엔진은 JIT(Just-In-Time) 컴파일을 사용하기 때문에, 연산 집약적인 작업을 기존 SQL stored procedures 보다 몇 배에서 수십 배 이상 빠르게 실행할 수 있습니다.

활용 사례: 레벤슈타인 거리(Levenshtein distance)를 이용한 Fuzzy Matching. 이 알고리즘을 SQL 로 구현하는 것은 느리고 복잡하지만, JS 로 구현하면 매우 효율적으로 처리할 수 있습니다.

 

CREATE FUNCTION levenshtein_js(s1 VARCHAR(255), s2 VARCHAR(255))
RETURNS INT LANGUAGE JS AS $$
  // Efficient algorithms run natively in V8
  // ... standard JS implementation of Levenshtein ...
$$;

 

그런 다음 이를 SELECT 문에서 직접 호출하여 검색 결과의 순위를 즉시 매길 수 있습니다.

 

 

Current Status & The Roadmap

 

기대치를 관리하는 것이 중요합니다. 현재 이는 기술 프리뷰(Tech Preview) 단계입니다.

현재 우리 구현과 Oracle 구현의 가장 큰 차이점은, JS routine 내부에서 아직 SQL 쿼리(SELECT, UPDATE 등)를 실행할 수 없다는 점입니다. 현재 기술 프리뷰에서는 순수 데이터 처리(Input→계산→Output)를 위한 JS Stored Routines 만 지원합니다.

우리는 SQL 실행 기능의 공백을 메우고 모듈 지원을 추가하기 위해 적극적으로 작업 중입니다. 그러나 데이터 검증, JSON 조작, 연산 집약적인 작업의 경우에는 지금 바로 실험해 볼 수 있을 만큼 이 기능은 준비되어 있습니다.

우리의 미션은 언제나 커뮤니티 에디션과 엔터프라이즈 에디션 간의 격차를 줄이는 것입니다. 이 기능은 오픈소스 버전에 JS 기능을 제공하여 상용 라이선스의 필요성을 제거합니다. 메인 저장소에서 컴포넌트 패키지를 설치하고 활성화한 뒤, 여러분의 의견을 들려주시길 바랍니다.

참고: 이 프리뷰에서는 외부 모듈 로딩(예: import)을 지원하지 않으며, 라이브러리 코드는 Routines 본문에 직접 포함해야 합니다.

 

 

Learn More

 

Architecture, type mapping, 구체적인 제한 사항에 대해 자세히 알아보려면 공식 문서를 읽어보세요.( https://docs.percona.com/percona-server/8.4/js-lang-overview.html)

이 기능은 Percona Server 8.4.7-7 의 메인 저장소에서 사용할 수 있습니다.

  1. 패키지 설치: RPM/Deb 사용자는 별도의 컴포넌트 패키지를 설치하세요: sudo apt-get install percona-server-js (또는 yum install …) (참고: Tarball 사용자는 메인 패키지에 이미 포함되어 있습니다.)
  2. 컴포넌트 활성화: MySQL 에 로그인한 뒤 다음을 실행합니다. INSTALL COMPONENT ‘file://component_js_lang’;

 

블로그 원문 : https://www.percona.com/blog/javascript-stored-routines-in-percona-server-for-mysql-a-new-era-for-database-programmability/

 

 

자유롭게 댓글을 달아주세요! 언제나 환영합니다.
기타 문의:  info@neoclova.co.kr
네오클로바 기술블로그 홈 바로가기: https://neoclova.net
네오클로바 홈페이지: http://neoclova.co.kr

 

Similar Posts

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다