Search
▪️

CLI 프로그램 만들기

Node CLI 프로그램 만들기

#!/usr/bin/env node는 Windows에서는 그저 주석일 뿐이지만, Linux나 MacOS에서는 해당 경로의 Node.js로 구동하여라 라는 의미이다. 따라서 Windows가 아니라 다른 OS에서 CLI를 만들고자 한다면, 위와 같이 Node.js의 설치 경로를 명시해줘야 한다. (무엇으로 실행시킬 것인지)
또한 작성한 CLI을 구동하기 위해선 Node.js 경로 명시 뿐 아니라, package.json에서 실행 Script에 대해서도 명시를 해야 한다. CLI를 실행하기 위해서 bin이라는 Object에 cli라는 Key에 Script의 상대 경로를 Value로 준다. (무엇을 실행시킬 것인지)
위와 같이 설정 했다면, Key 값에 따라 CLI에서 cli라는 명령어로 실행을 할 수 있어야 한다. 단, 아직 CLI에서는 해당 명령어를 인식하지 못하기 때문에, npm install -g (인자를 주지 않으면 현재 Package를 전역으로 설치하게 된다.)를 통해서, 작성한 프로그램을 전역으로 설정해주면 CLI에서도 cli 명령어를 인식할 수 있다. (어떻게 실행시킬 것인지)
위 세 가지 설정이 끝났다면, 만든 CLI 프로그램을 구동할 수 있게 된다.
process.argv[0]은 Node.js의 설치 경로, process.argv[1]은 File 위치 경로이다.

CLI 프로그램 구현하기

Node.js 내장 Module로 readline이라는 Module이 있다. 해당 Module을 통해 input, output을 stdin, stdout으로 설정한 Instance를 활용한다.
Instance의 question() Method를 통해서 사용자와 Interaction을 하게 된다. 사용자로 부터 Reply를 받으면 question() Method의 Callback Function이 호출된다.
Instance의 Interface를 종료시키기 위해선, Instance의 close() Method를 이용한다. (유용한 console의 Method로 console.clear()를 같이 이용할 수 있다.)
| → Or / [] → Omittable을 의미 한다.
Server 프로그램에서는 Sync() Method 사용 시, Request에 대한 Block이 일어나므로 지양한다. 하지만 CLI의 경우는 Sync() Method를 사용해도 무방한 경우가 많다.
** package.json이 바뀌면 npm install -g를 다시 해야 한다.

CLI 상호작용 추가하기

일련의 흐름으로 readline Module의 createInterface() Instance를 통해서 로직을 펼쳐야 한다. 하지만 이를 돕는 Third Party Package가 있다. (이에 대해 자세히 적은 것들은 아래 작성 내용에 있으니 참고하면 된다.)
작성한 CLI 프로그램의 경우, 삭제하고 싶다면 npm rm -g $applicationName을 통해서 삭제할 수 있다.

commander 사용하기

위에서 언급한 것처럼 CLI Interation을 돕는 Third Party Package가 바로 commander, inquirer, chalk라는 Package이다. (commander와 대체 가능한 Package들이 yargs, meow와 같은 것들이 있다.)
commander Module 이용 시에, — 는 Option, -는 단축 Option을 의미한다. 또한 <>는 필수를 의미하고, []은 선택을 의미한다. 자세한 것들은 Code를 참고하자.
readline Module로 구현한 것에 비해 Option의 순서를 지키지 않게 만들어줄 뿐 아니라, 사용법에 대한 안내를 쉽게 만들어 줘서 유용하다.

inquirer, chalk 사용하기

commander Module을 이용하는 것도 사용법에 대한 작성이 쉬워지기는 하는 것이나, 결국에는 Interaction이 부족하여 일일이 Help를 보면서 Typing 해야 한다.
따라서 Interaction에 대해서 보조 해주는 Third Party Package가 inquirer이다.
inquirer의 경우 triggered라는 값을 사용하며, triggered의 값은 commander의 action 전에는 false 값을 갖다가, commander의 action이 시작되면 true로 바꾸게 만들어 주어 로직을 펼치면 된다.
inquirer.prompt()라는 Method를 이용한다. prompt() Method의 인자는 Arrary로 받으며 Object Type을 갖는다.
Array에 쓰이는 Object의 Key값으로는 type, name, message choices, default를 가질 수 있다.
inquirer도 Promise Type을 지원한다.

스스로 해보기1 (File 복사 명령어 만들기)

createReadStream으로 File을 읽고, pipe()하여 createWriteStream으로 File을 만들어야 하지만, fs Module에 copyFile() Method를 지원하므로 이를 사용한다.

스스로 해보기2 (File 삭제 명령어 만들기)

Path를 입력 받으면 Path가 File이면 fs.unlinkSync()를, Directory라면 하위 File들을 fs.unlinkSync()한 후 fs.rmdir()로 Directory를 삭제한다.

스스로 해보기3 (DB를 연동한 가계부)

MySQL의 timestamps Key의 Value가 True 일 때는 createdAt, updatedAt이 기록되었다면, paranoid Key의 Value가 True일 때는 deletedAt도 기록이 된다.
Sequelize의 sync()를 수행한 후 별도의 close() Method가 없으면 계속 데이터베이스에 연결된 상태로 있게 되는데, Server의 경우는 계속 Listen을 하고 있기 때문에 무방하지만 CLI의 경우 데이터베이스 작업이 끝나면 데이터베이스의 연결을 종료해줘야 한다. (이를 반대로 말하면, 매 CLI 실행마다 데이터베이스의 연결을 열어줘야 한다.)
** Query Log가 Production에서도 찍히는 경우
** sequelize.sync()의 경우 Table 생성 및 데이터베이스 Connection을 돕는다.