자바스크립트 이벤트 루프를 파이프라인으로 변환
초록
본 논문은 Node.js 기반 단일 스레드 자바스크립트 웹 애플리케이션을 자동으로 파이프라인 형태의 병렬 실행 구조로 변환하는 컴파일러를 제안한다. 함수들을 “플럭션”(fluxion)이라 부르는 독립 실행 단위로 분리하고, 메시지 스트림을 통해 통신하도록 함으로써 다중 코어 환경에서 확장성을 확보한다. 구현 및 실험을 통해 기존 코드의 일부만 병렬화해도 처리량이 크게 향상됨을 보였다.
상세 분석
이 논문은 실시간 웹 서비스가 초기에는 기능 중심의 빠른 MVP 개발 방식으로 시작하지만, 급격한 사용자 증가 시 전통적인 이벤트‑루프 모델이 병목이 된다는 문제를 지적한다. 이를 해결하기 위해 저자들은 기존 자바스크립트 코드를 고수하면서도 데이터플로우와 유사한 병렬 실행 모델을 제공하는 새로운 추상화 레이어를 설계한다. 핵심 아이디어는 함수 단위의 실행 컨텍스트를 “플럭션”이라 명명된 독립적인 실행 컨테이너에 캡슐화하고, 각 플럭션이 자신의 로컬 상태(context)를 유지하도록 하는 것이다. 플럭션 간 통신은 두 종류의 스트림—시작(start)과 포스트(post)—을 통해 메시지 형태로 이루어지며, 이는 비동기 콜백이 발생하는 지점을 ‘파열점(rupture point)’으로 정의한다. 파열점은 비동기 I/O 호출이나 이벤트 리스너와 같은 비동기 함수 호출이며, 이 지점을 기준으로 코드 흐름을 분할한다.
컴파일러는 먼저 Esprima를 이용해 AST를 생성하고, Analyzer 단계에서 파열점을 탐지한다. 파열점 탐지는 미리 정의된 비동기 함수 리스트(예: Express 라우터, 파일 시스템 API)를 기반으로 하며, 콜백 함수가 인라인인지 변수로 전달되는지를 추적한다. 이후 Pipeliner 단계에서는 스코프 분석을 통해 변수 의존성을 파악한다. 변수는 세 가지 경우로 처리된다: (1) 한 플럭션 내부에서만 수정되는 경우, 해당 플럭션의 컨텍스트에 직접 저장한다; (2) 상류 플럭션에서 수정되고 하류 플럭션에서 읽히는 경우, 수정된 값을 메시지에 포함시켜 전달한다; (3) 포스트 체인 내부에서 정의된 변수는 순차적 실행 보장이 있기 때문에 스트림을 통해 자유롭게 전파한다.
플럭션은 동일한 태그(tag)를 공유하면 같은 그룹에 속하게 되며, 그룹 내 플럭션은 동일 이벤트 루프 스레드에서 순차적으로 실행된다. 이는 공유 상태(예: 전역 변수) 접근 시 경쟁 조건을 방지한다. 반면, 태그가 없는 플럭션은 완전 독립적으로 여러 워커 스레드에 배치될 수 있어, CPU 코어 수에 따라 동적으로 복제 및 스케일링이 가능하다.
실험에서는 간단한 파일 읽기와 응답 카운터를 포함한 Express 애플리케이션을 대상으로 변환을 수행했다. 변환 결과, 요청 핸들러 플럭션은 완전 독립적으로 병렬화되었으며, 카운터와 같은 공유 상태를 보유한 플럭션 그룹은 여전히 순차 실행되지만 필요에 따라 복제될 수 있다. 벤치마크 결과는 단일 코어 환경 대비 다중 코어에서 처리량이 2~3배 향상되는 것을 보여준다.
이 접근법의 장점은 기존 코드베이스를 크게 수정하지 않고도 자동으로 병렬화 파이프라인을 생성한다는 점이다. 또한, 플럭션 단위의 추상화는 개발자가 명시적으로 스레드나 프로세스를 관리할 필요 없이, 고수준의 데이터플로우 모델을 통해 확장성을 설계하도록 돕는다. 한계로는 복잡한 공유 상태가 많은 애플리케이션에서 플럭션 그룹이 크게 늘어날 경우, 여전히 병목이 발생할 수 있다는 점과, 비동기 함수 리스트를 수동으로 관리해야 하는 운영상의 부담이 있다. 향후 연구에서는 자동화된 비동기 함수 탐지와 동적 그룹 재구성을 통해 이러한 제약을 완화할 여지가 있다.
댓글 및 학술 토론
Loading comments...
의견 남기기