관리 메뉴

진취적 삶

14 CLI 프로그램 만들기 본문

개발 도서/Node.js 교과서

14 CLI 프로그램 만들기

hp0724 2023. 7. 14. 11:49

CLI 는 콘솔 창을 통해 프로그램을 수행하는 환경을 뜻한다.

이와 반대되는 개념은 GUI 가 있다.

14.1 간단한 콘솔 명령어 만들기

콘솔에서 입력해 어떤한 동작을 수행하는 문장을 콘솔 명령어 라고 한다.

{
  "name": "node-cli",
  "version": "0.0.1",
  "description": "nodejs cli program",
  "main": "index.js",
  "author": "suhaHwang",
  "license": "ISC",
  "bin": {
    "cli": "./index.js"
  }
}
#!/usr/bin/env node
console.log("hello CLI");
npx cli //hello CLI

package.json 에서 bin 속성에 cli 명령어와 index.js를 연결했으니 cli 명령어가 호출될 때마다 index.js 파일이 실행

#!/usr/bin/env node
const readline = require("readline");

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

rl.question("예제가 재밌나요 (y/n)", (answer) => {
  if (answer === "y") {
    console.log("감사합니다");
  } else if (answer === "n") {
    console.log("죄송합니다!");
  } else {
    console.log("y또는 n 만 입력하세요 ");
  }
  rl.close();
});
#!/usr/bin/env node
const readline = require("readline");

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});
console.clear();

const answerCallback = (answer) => {
  if (answer === "y") {
    console.log("감사합니다");
    rl.close();
  } else if (answer === "n") {
    console.log("죄송합니다!");
    rl.close();
  } else {
    close.clear();
    console.log("y또는 n 만 입력하세요 ");
    rl.question("예제가 재미있습니까 (y/n)", answerCallback);
  }
};
rl.question("예제가 재밌나요 (y/n)", answerCallback);

파일 만들기 명령어

  • fs.constants.F_OK: 파일이 존재하는지 확인하기 위한 조건입니다. fs.access() 메서드에서 사용됩니다.
  • fs.constants.R_OK: 파일을 읽을 수 있는지 확인하기 위한 조건입니다. fs.access() 메서드에서 사용됩니다.
  • fs.constants.W_OK: 파일에 쓸 수 있는지 확인하기 위한 조건입니다. fs.access() 메서드에서 사용됩니다.
  • fs.constants.X_OK: 파일을 실행할 수 있는지 확인하기 위한 조건입니다. fs.access() 메서드에서 사용됩니다.
  • fs.constants.O_RDONLY: 파일을 읽기 전용으로 열기 위한 옵션입니다. fs.open() 메서드에서 사용됩니다.
  • fs.constants.O_WRONLY: 파일을 쓰기 전용으로 열기 위한 옵션입니다. fs.open() 메서드에서 사용됩니다.
  • fs.constants.O_RDWR: 파일을 읽기/쓰기 모드로 열기 위한 옵션입니다. fs.open() 메서드에서 사용됩니다.
  • fs.constants.O_CREAT: 파일이 없는 경우 새로 생성하기 위한 옵션입니다. fs.open() 메서드에서 사용됩니다.
  • fs.constants.O_TRUNC: 파일을 열 때 내용을 잘라내고 비어 있는 파일로 만드는 옵션입니다. fs.open() 메서드에서 사용됩니다.
  • fs.constants.O_APPEND: 파일의 끝에 추가하기 위한 옵션입니다. fs.open() 메서드에서 사용됩니다.
#!/usr/bin/env node
const fs = require("fs");
const path = require("path");

const type = process.argv[2];
const name = process.argv[3];
const directory = process.argv[4] || ".";
const htmlTemplate = `
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Template</title>
  </head>
  <body>
    <h1>Hello</h1>
    <p>CLI</p>
  </body>
</html>
`;

const routerTemplate = `
const express = require('express');
const router = express.Router();
 
router.get('/', (req, res, next) => {
   try {
     res.send('ok');
   } catch (error) {
     console.error(error);
     next(error);
   }
});
 
module.exports = router;
`;

const exist = (dir) => {
  //폴더 존재확인 함수
  try {
    fs.accessSync(
      dir,
      fs.constants.F_OK | fs.constants.R_OK | fs.constants.W_OK
    );
    return true;
  } catch (error) {
    return false;
  }
};

const mkdirp = (dir) => {
  //경로 생성 함수
  const dirname = path
    .relative(".", path.normalize(dir))
    .split(path.sep)
    .filter((p) => !!p);
  dirname.forEach((d, idx) => {
    const pathBuilder = dirname.slice(0, idx + 1).join(path.sep);
    if (!exist(pathBuilder)) {
      fs.mkdirSync(pathBuilder);
    }
  });
};

const makeTemplate = () => {
  //템플릿 생성 함수
  mkdirp(directory);
  if (type === "html") {
    const pathToFile = path.join(directory, `${name}.html`);
    if (exist(pathToFile)) {
      console.error("이미 해달 파일이 존재합니다 ");
    } else {
      fs.writeFileSync(pathToFile, htmlTemplate);
      console.log(pathToFile, "생성 완료");
    }
  } else if (type === "express-router") {
    const pathToFile = path.join(directory, `${name}.js`);
    if (exist(pathToFile)) {
      console.error("이미 해당 파일이 존재합니다");
    } else {
      fs.writeFileSync(pathToFile, routerTemplate);
      console.log(pathToFile, "생성 완료");
    }
  } else {
    console.error("html 또는 express-router 둘 중 하나를 입력하세요");
  }
};

const program = () => {
  if (!type || !name) {
    console.error("사용 방법 : cli html|express-router 파일명 [생성 경로]");
  } else {
    makeTemplate();
  }
};

program();