Sciter는 내장형 데스크톱 UI 엔진으로, 경량화와 높은 성능을 필요로 하는 애플리케이션 개발에 적합합니다. 하지만 JavaScript 실행에 대해 20초의 하드코딩된 타임아웃이 존재하며, 이를 초과하면 실행이 강제로 중단됩니다. 설정을 통해 변경할 수 없는 구조적 제약입니다.
문제 발생 상황
프론트엔드 JavaScript에 무거운 연산 로직을 작성하고, 해당 함수를 C++ 백엔드 스레드로 전달하여 실행할 때, 처리 시간이 20초를 초과하면 Sciter가 내부적으로 타임아웃을 트리거하여 실행을 실패 처리합니다.
프론트엔드 코드 예시:
const payload = { id: 'user001' };
Window.this.mainWindow.dispatchTask(payload, function(receivedData, taskContext) {
// receivedData: 프론트엔드 -> C++ -> 현재 스레드로 전달된 데이터
// taskContext: C++에서 래핑한 컨텍스트 객체
// 20초 이상 소요되는 무거운 연산 수행
});
C++ 백엔드 코드 예시:
SOM_PASSPORT_BEGIN(mainWindow)
SOM_FUNCS(
SOM_FUNC(dispatchTask),
)
SOM_PASSPORT_END
bool dispatchTask(sciter::value input, sciter::value callback) {
std::thread worker([input, callback]() {
std::wcout << L"스레드 시작" << std::endl;
sciter::value ctx = sciter::value::wrap_asset(&taskContext);
ctx.isolate();
// 20초 초과 시 Sciter가 자동으로 실패 처리하며 변수가 해제됨
callback.call(input, ctx);
ctx.clear();
std::wcout << L"스레드 종료" << std::endl;
});
worker.detach();
return true;
}
해결 방법
1. QuickJS 기반 독립 실행 환경 구축
QuickJS++ 프로젝트를 활용하여 Sciter 내장 엔진과 별도로 JavaScript를 실행하는 환경을 구성합니다. 구현 난이도는 높지만 가장 안정적인 접근 방식입니다.
2. DLL 바이너리 데이터 직접 수정
Sciter DLL 파일의 바이너리에서 타임아웃 값을 찾아 수정하는 방식입니다. 빠르고 간단하지만, 부작용으로 다른 스크립트의 타임아웃 동작에 영향을 줄 수 있습니다.
HxD와 같은 헥스 에디터를 사용하여 작업합니다. 대상 파일은 sciter-js-sdk/bin/windows.d2d/x32/sciter.dll로, 바이너리 크기가 작아 수정 시 영향 범위를 최소화할 수 있습니다.
수정 절차:
- 현재 버전(v6.0.2.28)에서 타임아웃 기본값은 20초입니다.
- 20초의 바이너리 표현은
20 4E 00 00이며, 리틀 엔디언 바이트 순서로 인해 HxD에서 역순으로 표시됩니다. - 6000초로 변경하려면
5B 8D 80 00으로 교체합니다. - HxD에서
Ctrl+R을 눌러 바이트 시퀀스 검색 및 치환을 수행한 뒤Ctrl+S로 저장합니다.
현재 버전에서는 20000에 해당하는 데이터가 8개 존재하므로, 개별적으로 테스트하며 정확한 위치를 특정하는 것을 권장합니다.
3. 상용 소스코드 라이선스 구매
Sciter 상용 라이선스를 구매하면 소스코드가 제공되므로, 타임아웃 로직을 직접 수정하여 빌드할 수 있습니다. 가장 근본적인 해결책입니다.