간단한 콘솔 명령어 만들기(5)
이를 위해 CLI 프로그램이 사용자가 원하는 것을 단계별로 질문하게 하겠습니다. 먼저 템플릿을 생성할지를 묻고, 그 다음에 파일명과 경로를 물어봅니다. cli 명령어만 입력했을 때는 단계적으로 질문하도록 만들어보겠습니다.
template.js
#!/usr/bin/env node
const fs = require("fs");
const path = require("path");
const readline = require("readline");
let rl;
let type = process.argv[2];
let name = process.argv[3];
let 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 (e) {
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 dirAnswer = (answer) => {
// 경로 설명
directory = (answer && answer.trim()) || ".";
rl.close();
makeTemplate();
};
const nameAnswer = (answer) => {
// 파일명 설명
if (!answer || !answer.trim()) {
console.clear();
console.log("name을 반드시 입력하셔야 합니다.");
return rl.question("파일명을 설정하세요.", nameAnswer);
}
name = answer;
return rl.question(
"저장할 경로를 설정하세요. (설정하지 않으면 현재 경로) :",
dirAnswer,
);
};
const typeAnswer = (answer) => {
// 템플릿 종류 설정
if (answer != "html" && answer !== "express-router") {
console.clear();
console.log("html 또는 express-router만 지원합니다.");
return rl.question("어떤 템플릿이 필요하십니까? ", typeAnswer);
}
type = answer;
return rl.question("파일명을 설정하세요. ", nameAnswer);
};
// ❷
const program = () => {
if (!type || !name) {
rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
console.clear();
rl.question("어떤 템플릿이 필요하십니까? ", typeAnswer);
} else {
makeTemplate();
}
};
program(); // 프로그램 실행부
다시 readline 모듈을 사용합니다. question 메서드가 비동기 방식으로 동작하므로 새로운 함수들을 만들었습니다.
❶ dirAnswer, nameAnswer, TypeAnswer는 각각 디렉터리, 파일명, 템플릿 종류에 대해 사용자 입력을 받는 함수입니다. 코드의 순서가 역순으로 되어 있으므로 typeAnswer, nameAnswer, dirAnswer가 실질적인 실행 순서라고 생각하면 됩니다.
❷ 명령어에서 템플릿 종류(type)나 파일명(name)을 입력하지 않았을 때 상호작용할 수 있는 입력 창의 띄우는 부분입니다.
콘솔에서 직접 이 프로그램을 사용해봅니다.
$ npx cli
어떤 템플릿이 필요하십니까? html
파일명을 설정하세요. test
저장할 경로를 설정하세요. (설정하지 않으면 현재 경로) :public
public\test.html 생성 완료
'프로그래밍 언어 > NODE JS' 카테고리의 다른 글
| commander, inquirer 사용하기(2) (0) | 2026.03.31 |
|---|---|
| commander, inquirer 사용하기(1) (0) | 2026.03.28 |
| 간단한 콘솔 명령어 만들기(4) (0) | 2026.03.22 |
| 간단한 콘솔 명령어 만들기(3) (0) | 2026.03.19 |
| 간단한 콘솔 명령어 만들기(2) (0) | 2026.03.16 |