기존에 Web으로 만들고 있던 tool을 exe 실행파일로 만들었으면 좋겠다는 요구사항이 추가되어, node js를 사용하여 exe파일을 만드는 방법을 이것 저것 찾아보다가 UI로 보여주는 desktop app을 만들 수 있는 Framework인 Electron 과 js 파일을 exe 실행파일로 컴파일 해주는 패키지인 pkg 라는 것을 알게 되었다.
인턴기간이 앞으로 길게 남지 않은 만큼 가장 간단한 pkg 패키지를 사용하여 exe 실행 파일을 만들고자 하는데 여러 에러 사항에 부딪혔다. 아직 해결하지 못한 에러 사항들도 존재하지만 해결하면 바로 본 포스트에 기록할 예정이다.
pkg
pkg 패키지에 대한 자세한 내용은 아래 링크에서 알 수 있다.
pkg를 사용하면 node js가 설치 되어 있지 않은 환경에서도 실핼할 수 있는 exe 실행파일을 생성할 수 있다.
Make a commercial version of your application without sources
sources 없이 나의 application의 사용 버전 만들 때
Make a demo/evaluation/trial version of your app without sources
sources 없이 나의 app의 demo/evaluation/trial 버전을 만들 때
Instantly make executables for other platforms (cross-compilation)
다른 플랫폼을 위한 실행 파일을 즉시 만들 때 ( 크로스 컴파일 )
Make some kind of self-extracting archive or installer
자체 풀림 압축 파일 ( 자동 압축 풀림 파일 ) 또는 설치 프로그램을 만들 때
No need to install Node.js and npm to run the packaged application
Node js, npm 설치가 필요 없이 패키지된 application을 실행하기 위해
No need to download hundreds of files vianpm installto deploy your application. Deploy it as a single file
나의 application을 배포하기 위해서 [ npm install ] 로 몇 백개의 파일들을 다운로드 할 필요 없이 단일 파일로 배포할 때
Put your assets inside the executable to make it even more portable
휴대성/이식성을 높이기 위해 assets을 실행파일 안에 넣는다.
Test your app against new Node.js version without installing it
app 설치 없이 새로운 Node.js 버전에 대해 나의 app을 Test할 때
사용법 ( Usage )
$ npm install -g pkg
설치 후에 pkg --help 를 통해서 pkg의 옵션 리스트를 확인할 수 있다.
pkg [options] <input>
Options:
-h, --help output usage information // 결과 : 사용법 정보
-v, --version output pkg version // 결과 : pkg 버전
-t, --targets comma-separated list of targets (see examples) // 쉼표로 구분된 타겟의 리스트
-c, --config package.json or any json file with top-level config // package.json 또는 최상위 ( top - level )구성이 있는 모든 json 파일
--options bake v8 options into executable to run with them on // v8 옵션을 실행할 실행파일 굽기
-o, --output output file name or template for several files // 결과 : 파일 이름 또는 여러(몇몇개의) 파일들의 템플릿
--out-path path to save output one or more executables // 하나 또는 여러개의 실행 파일 output을 저장할 경로
-d, --debug show more information during packaging process [off] // packaging process 동안 더 많은 정보를 보여준다.
-b, --build don't download prebuilt base binaries, build them // 미리 빌드된 기본 바이너리를 다운로드 하지 않고, 빌드
--public speed up and disclose the sources of top-level project // 최상위 프로젝트의 속도를 높이고, sources를 공개
--public-packages force specified packages to be considered public // 지정된 package를 public으로 고려되도록 강제
--no-bytecode skip bytecode generation and include source files as plain js // bytecode 변환을 skip하고 일반 js file을 포함한다.
--no-native-build skip native addons build // native addons 빌드를 skip
--no-dict comma-separated list of packages names to ignore dictionaries. Use --no-dict * to disable all dictionaries //
-C, --compress [default=None] compression algorithm = Brotli or GZip // 압축 알고리즘 지정
Examples:
– Makes executables for Linux, macOS and Windows
$ pkg index.js
– Takes package.json from cwd and follows 'bin' entry
$ pkg .
– Makes executable for particular target machine
$ pkg -t node14-win-arm64 index.js
– Makes executables for target machines of your choice
$ pkg -t node12-linux,node14-linux,node14-win index.js
– Bakes '--expose-gc' and '--max-heap-size=34' into executable
$ pkg --options "expose-gc,max-heap-size=34" index.js
– Consider packageA and packageB to be public
$ pkg --public-packages "packageA,packageB" index.js
– Consider all packages to be public
$ pkg --public-packages "*" index.js
– Bakes '--expose-gc' into executable
$ pkg --options expose-gc index.js
– reduce size of the data packed inside the executable with GZip
$ pkg --compress GZip index.js
현재 나의 개발 환경은 Mac M1으로 Mac OS 환경에서 작업을 하고 있다. 인턴 업무로 주어진 프로그램을 Mac 환경에서만 주로 테스트를 하다가 최종적으로 Mac OS 환경에서 정상작동하는 것을 확인하고, Windows 환경에서 돌아가는지 확인을 해 본 결과 exe 파일을 실행하면 command 창이 켜졌다가 바로 꺼지는 현상이 발생했다.
sleep을 걸어보았으나 같은 현상이 발생하였고, mac os 환경에서는 잘 되던게 갑자기 Windows에서는 동작하지 않아 많이 .. 당황스러웠다. 이 에러사항을 해결하기 위해 열심히 구글링을 해보았으나 아직 해결하지 못하였다. ( 08. 17 ~ ing )
해결하게 된다면 해결방법을 작성하러 다시 오ㅏ...야지
08. 24. WED
엄청나게 삽질을 하다가 돌아왔다.
function sleep(sec) {
return new Promise(resolve => setTimeout(resolve, sec * 1000));
}
...
// 코드 끝자락
sleep(100).then( r =>{ console.log(r);});
위와 같은 코드를 통해서 코드 끝부분에 setTImeout으로 구현한 sleep을 걸어주었더니 실행파일이 바로 꺼지는 현상이 사라졌다.
그러나 이번에는 경로 오류가 나를 기다리고 있었다.
코드에서 fs.readFileSync의 모든 경로를 절대경로로 설정해주었는데, 왜 파일을 읽어오지 못하지 ? 라는 의문이 생겼고, 열심히 구글링을 한 결과 어떤 한 블로그에서 node js 는 현재 node가 실행중인 경로를 기준으로 파일을 읽어온다는 사실을 알게 되었다.
그래서 모든 읽어와야하는 파일을 실행파일과 같은 위치에 두고 읽어오는 방식을 상대경로로 수정을 하였다.