2024. 7. 16. 12:18ㆍ카테고리 없음
Node.js에서는 일반적으로 readline 모듈을 사용해서 입력을 받고 console.log를 사용해서 출력을 한다.
모듈을 사용하기 전에 표준 입출력 스트림을 활용해서 입출력을 해보자.
process.stdin, process.stdout
노드 기본 모듈인 process의 stdin과 process의 stdout을 사용해서 입출력을 할 수 있다.
process.stdin은 이벤트와 그 이벤트가 발생했을 때 실행할 콜백 함수를 정의 할 수 있다.
- data 이벤트 : 입력 이벤트
- end 이벤트 : 입력 종료 이벤트
node:process 모듈에서 stdin과 stdout을 가져와서 사용해보자.
const { stdin, stdout } = require('node:process');
// 입력 이벤트
stdin.on('data', function(data) {
stdout.write(data);
});
// 입력 종료 이벤트
stdin.on('end', function() {
stdout.write('종료');
});
참고로 process는 전역으로 사용할 수 있기 때문에 따로 모듈을 가져오지 않아도 된다.
// 입력 이벤트
process.stdin.on('data', function(data) {
process.stdout.write(data);
});
// 입력 종료 이벤트
process.stdin.on('end', function() {
process.stdout.write('종료')
});
process의 표준 입출력을 사용해도 입출력을 구현할 수 있지만 다양한 기능을 제공해주는 readline 모듈을 사용해서 라인 단위의 입력을 받을 수 있다.
참고로 console.log는 내부적으로 process.stdout을 사용하지만 출력 끝에 \ n(newline)을 붙인다.
모듈 사용
- node:readline : 콜백 기반 readline 모듈
- node:readline/promises : 프로미스 기반 readline 모듈
노드 버전 22.4.1 기준으로 프로비스 기반보다 콜백 기반 readline 모듈이 안정성이 높다.
콜백 기반 readline 모듈을 사용하여 Node.js에서 표준 입력을 받는 방법을 알아보자.
모듈 가져오기
모듈을 가져올 때 commonJS 방식과 esModule 방식이 존재한다.
1. commonJS
const readline = require('node:readline');
2. esModule
import readline from 'node:readline';
보통 commonJS 방식이 default이기 때문에 commonJS 방식으로 해보려고 한다.
참고로 현재 node:readline 모듈을 가져오고 있는데 node가 붙은 것은 기본 모듈을 의미한다.
기본 모듈은 앞에 “node:”를 붙이지 않아도 되지만 붙이면 명시적으로 기본 모듈을 의미하기 때문에 혹시 모를 모듈 이름 충돌에 대비할 수 있다.
const readline = require('readline');
readline.createInterface
readline.createInteface 메소드를 사용하여 InterfaceConstructor 인스턴스를 생성할 수 있다.
모든 인스턴스는 하나의 input readable stream과 하나의 output writable stream을 가지고 있다.
node:process 모듈에서 stdin과 stdout을 가져와서 InterfaceConstructor 인스턴스의 input readable stream과 output writable stream으로 사용해보자.
createInterface에 input과 output 키 값에 input readable stream과 output writable stream을 넣어주면 된다.
코드는 공식 문서를 참고했다.
const readline = require('node:readline');
const { stdin: input, stdout: output } = require('node:process');
const rl = readline.createInterface({ input, output });
rl.question('What do you think of Node.js? ', (answer) => {
// TODO: Log the answer in a database
console.log(`Thank you for your valuable feedback: ${answer}`);
rl.close();
});
여기서 process를 보면 역시 노드 기본 모듈임을 알 수 있다.
참고로 process는 전역으로 사용할 수 있기 때문에 직접 명시하여 가져오지 않아도 되지만 직접 가져오면 역시 명시적으로 표현할 수 있다는 장점이 있다.
위 코드를 아래처럼 간단하게 표현할 수 있다.
const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
rl.question('What do you think of Node.js? ', (answer) => {
// TODO: Log the answer in a database
console.log(`Thank you for your valuable feedback: ${answer}`);
rl.close();
});
readline은 다양한 이벤트를 등록하고 해당 이벤트가 발생했을 때 실행할 콜백 함수를 등록할 수 있다.
표준 입력을 위한 이벤트 몇 가지만 알아보자.
line 이벤트
line 이벤트는 input stream이 줄의 끝을 의미하는 \\n \\r \\r\\n 을 받았을 때 발생한다.
참고로 \n \r \r\n은 모두 줄바꿈을 나타내지만 운영체제 별로 다르게 사용한다.
주로 유닉스 계열은 \n, 윈도우는 \r\n을 사용한다.
즉 줄 하나를 읽을 때마다 발생하는 이벤트라고 보면 된다.
close 이벤트
close 이벤트는 다음과 같은 상황에서 발생한다.
- rl.close 메소드가 호출
- input stream이 end 이벤트를 받았을 때 (input stream 종료)
- input stream이 Ctrl + D를 받았을 때
- input stream이 Ctrl + C를 받고 SIGINT 이벤트가 등록되어 있지 않을 때
이제 콘솔로부터 총 4 줄을 입력받아서 배열에 저장하는 코드를 작성해보자.
readline 사용 표준 입력 예시
const readline = require("readline"); // node 기본 모듇 readline
const rl = readline.createInterface({
input: process.stdin, // global node 기본 모듈 process input stream
output: process.stdout, // global node 기본 모듈 process output stream
});
const lines = [];
// 줄 바꿈을 만날 때마다 배열에 넣는다.
rl.on("line", (input) => {
lines.push(input);
// 총 4줄을 입력받으면 close 이벤트를 발생시킨다.
if (lines.length === 4) {
rl.close();
}
});
// close 이벤트가 발생하면 배열 출력
rl.on("close", () => {
console.log(lines);
});
혹시 모를 모듈 충돌을 피하기 위해 명시적으로 모듈을 불러오는 코드도 작성해보자.
const readline = require("node:readline"); // node 기본 모듇 readline
const { stdin: input, stdout: output } = require('node:process');
const rl = readline.createInterface({
input, // global node 기본 모듈 process input stream
output, // global node 기본 모듈 process output stream
});
const lines = [];
// 줄 바꿈을 만날 때마다 배열에 넣는다.
rl.on("line", (input) => {
lines.push(input);
// 총 4줄을 입력받으면 close 이벤트를 발생시킨다.
if (lines.length === 4) {
rl.close();
}
});
// close 이벤트가 발생하면 배열 출력
rl.on("close", () => {
console.log(lines);
});
readline의 입출력 변경
지금은 표준 입출력을 바탕으로 콘솔에서 입력받고 콘솔에 출력하는 방법을 알아보았다.
이번에는 콘솔에서 입력받고 파일에 출력하는 방법을 알아보자.
이름을 입력받아서 그 이름을 파일에 출력해보자.
입력 스트림은 표준 입력 스트림을 사용하고 출력 스트림은 파일 출력 스트림을 사용하자.
const fs = require('fs');
const readline = require('readline');
// 파일 출력 스트림 생성
const outputFileStream = fs.createWriteStream('output.txt');
const rl = readline.createInterface({
input: process.stdin, // 표준 입력
output: outputFileStream // 파일로 출력
});
rl.question('이름을 입력하세요 ', (answer) => {
outputFileStream.write(`당신의 이름은 ${answer}입니다.`);
rl.close();
});
표준 출력 스트림을 사용했을 때 rl.question의 첫 번째 파라미터 문자열이 콘솔에 출력되었지만 지금은 파일 출력 스트림을 사용했기 때문에 “이름을 입력하세요”가 output.txt에 출력된다.
