홈으로

[Node.js] CLI 프로그램 제작기

2020년 01월 23일

포스트 생성의 불편함

Gatsby + React로 블로그를 옮기기 시작하면서 gatsby-starter-lumen 테마를 적용하게 되었다. 굉장히 깔끔하고 군더더기 없었으나 도대체 포스트를 어떻게 생성해야 할지 알 수 없었다. 그래서 계속해서 파일을 직접 만들고 위쪽의 포스트 메타정보를 나타내는 프론트매터(Front-matter)를 직접 입력해왔다. 하지만 역시 포스트를 생성하는 과정 자체가 불편하다보니, 블로그에 정이 점점 떨어지기 시작했다. 그러다가 한국에서 개츠비 스타터로 가장 유명한 테마인 재엽님의 gatsby-starter-bee 가 CLI를 지원한다는 것을 알게 되었다. 그래서 CLI 소스를 보게 되었는데 이 정도면 나도 lumen 테마 만의 CLI를 만들 수 있을 거라고 생각하게 되었고 그렇게 만들게 되었다. 재엽님께 무한 감사를 🙏

요구사항

​내가 원하는 CLI가 충족시켜야할 사항은 아래와 같았다.

  • 카테고리(category)를 기존에서 선택하거나 추가할 수 있어야 한다.
  • 태그(tags)를 기존에서 선택하기도 하고 추가할 수 있어야 한다.
  • 제목(title), 설명(description)을 입력할 수 있어야 한다.
  • 날짜/시간(date), 슬러그(slug), 초안(draft), 템플릿(template) 옵션이 자동으로 생성되어야 한다.

어떻게 구현해야 할까

위와 같은 기능을 구현하기 위해서 필요했던 패키지들은 다음과 같다.

  • fs-extra : 노드의 내장 패키지인 fs에 비해서 편리함과 기능이 확장된 패키지이다. 마크다운 파일들을 읽어들이고 생성하는데 필요하다.
  • gray-matter : 프론트매터의 정보를 파싱해서 쉽게 가져올 수 있게 하는 패키지로 카테고리와 태그를 가져올 때 필요하다.
  • recursive-readdir : 디렉토리는 무시한 채 서브디렉토리를 전부 찾으면서 모든 파일들을 가져오는 패키지로 마크다운 파일을 가져오는데 필요하다.
  • date-fns : 자바스크립트에서 날짜/시간 관련 기능을 기존방식보다 편하게 만든 패키지로 날짜/시간을 프론트매터에 추가할 때 필요하다.
  • signale : CLI 프로그램에서 로깅을 여러가지 방식으로 할 수 있게 해주는 패키지이다.
  • inquirer : CLI 프로그램에서 사용자와 상호작용 할 수 있는 여러가지 방식을 제공해주는 패키지이다.
  • make-dir : 디렉토리를 만들어주는 패키지로 카테고리에 해당하는 디렉토리가 없을 경우 만들어주기 위해 필요하다.

이제 이 패키지들을 활용해서 마크다운 파일들을 모두 가져온 후에 각 파일의 프론트매터에서 카테고리들과 태그들을 읽어들인다. 그 후 사용자와의 상호작용을 통해 위에서 언급한 요구사항들의 정보를 가져오고 날짜/시간 및 슬러그, 초안 등에 대한 옵션을 설정한다. 이제 적절히 원하는 포맷으로 변환시킨 후 프론트매터 포맷에 맞게 문자열로 조합하면 된다. 마지막엔 원하는 카테고리에 속한 디렉토리에 조합한 문자열을 입력시킨 마크다운 파일을 생성해내면 끝난다. 실제 코드는 여기 에서 확인할 수 있다.

실행파일 설정

창천향로님의 나만의 CLI 만들기! 를 보면서 어떻게 하는지 자세히 배울 수 있었다. package.json 파일의 bin 옵션으로 실행파일의 경로를 지정해주면 된다. 나는 bin 폴더를 만들고 lumen-post.js 라는 파일을 만들었기 때문에 다음과 같이 설정해주었다.

{
  "bin": {
    "lumen-post": "./bin/lumen-post.js"
  }
}

그러나 이것이 구현파일은 아니다. 구현파일은 lib/index.js 에 들어있고 여기선 이걸 불러와서 실행만 시켜주는 방식이다. 실제 실행파일을 보면 아주 간단하다는 것을 알 수 있다.

#!/usr/bin/env node

const postGenerator = require('../lib/index');
postGenerator();

여기서 제일 위에 있는 코드는 쉬뱅(Shebang)이라는 것으로 유닉스 계열의 CLI에서 이 스크립트를 실행시켜줄 프로그램의 경로를 지정하는 역할을 한다. Windows는 확장자 기반으로 프로그램을 실행하기 때문에 무시한다고 하지만 npm 환경을 고려할 경우엔 추가해야 한다고 한다. 아주 명확하게 이해되진 않지만 프로그램 실행 환경의 설정으로 보면 적당할 것 같다. 좀 더 엄밀한 정보를 원한다면 What exactly does “/usr/bin/env node” do at the beginning of node files? 를 참고하자.

테스트 및 배포

여기서의 테스트는 유닛/통합 테스트가 아니라 배포하기 전 테스트를 의미한다. npm link 를 통해서 실제로 설치하지 않고도 로컬환경에서 쉽게 테스트할 수 있다.

  • 실제 패키지 디렉토리
npm link
  • 그 패키지를 사용할 테스트 디렉토리
npm link [패키지 이름]

이렇게 테스트 디렉토리에서 패키지를 사용해 볼 수 있다. 이걸 통해 테스트를 성공하면 이제 실제 패키지로 배포하면 끝이 난다.

  • 배포
npm login
npm publish

로그인을 해야 배포할 수 있으니 npmjs 에 가입하지 않았으면 가입하고 오자. 배포를 했을 때 동일한 이름의 패키지가 있을 경우 에러가 발생하니 꼭 중복되는지 확인하도록 하자. 패키지 명은 package.jsonname 값으로 배포된다.

마무리

이렇게 난생 처음으로 CLI 프로그램을 만들어보았고 나 자신의 불편함을 위해서 만들어보니 정말 뿌듯하다. 실제 지금 이 포스트도 내가 배포한 패키지를 설치해서 생성하였다. 앞으로도 불편한 점이 있다면 직접 만들어보려는 노력을 하는 태도를 가지도록 하자 😄

Loading script...