JavaScript readline 사용하기

당근 먹는 쿼카·2022년 11월 15일
20

개발 로그

목록 보기
8/16
post-thumbnail

이 모듈을 처음 만난 건 백준 알고리즘 문제를 풀기 위해서였다. 저런 모듈이 뭔지도 모르고, 문제를 풀기 위해서 백준에서는 꼭 필요한 모듈이었는데 모르는 게 나오니 거부감부터 들었다. 그래서 결국 프로그래머스에서 알고리즘 코딩 테스트 문제를 풀고 있었는데 결국 프로그래머스에서도 만나고 말았다. 그래서 readline에 대한 이해를 하기 위해서 이 블로그를 작성한다.

readline?

Node.js 문서 에서 적힌 개념을 확인해 보자.

The node:readline module provides an interface for reading data from a Readable stream (such as process.stdin) one line at a time.

Readable stream (process.stdin과 같은)에서 데이터를 한 번에 한 줄씩 읽기 위한 인터페이스를 제공한다.

promise를 기반으로 한 API 사용법

import * as readline from 'node:readline/promises'

콜백과 싱크를 이용한 API 사용법

import * as readline from 'node:readline'

기본적인 모듈 사용 예

import * as readline from 'node:readline/promises'
import { stdin as inputm, stdout as output } from 'node:process'

const rl = readline.createInterface({ input, output })
const answer = await rl.question('What do you think of Node.js?')
console.log(`Thank you for your valuable feedback: ${answer}`)
rl.close();

라고 공식 사이트에 사용법이 나와 있지만, 사람들은 이렇게 사용하지 않았다. 그게 나를 가장 혼란스럽게 만든 요소기도 했다.

내가 이해한 바로 간단하게 설명해 보자면 이렇게 정리할 수 있을 것 같다.

readline 모듈을 불러온 후 input, output을 통해서 콘솔에 입력값을 받는 줄과 결과값을 내놓는 줄을 작성할 수 있다.

readline 사용법

1. 모듈 불러오기

const readline = require('readline')

알고리즘 사이트도 그렇고 대부분 readline을 설명하는 블로그 글들을 확인해 보면 공식 문서와는 달리 require() 함수를 통해서 readline 모듈을 불러옵니다.

잠깐 CommonJS?

왜 공식 문서에는 import 키워드를 사용해서 불러오지만 대부분의 사람들은 require()을 사용하는가?

ES6 방식이 아닌 CommonJS 방식으로 작성하기 때문이라고 할 수 있습니다. 자바스크립트 모듈화 명세를 만든 대표적인 그룹 중 CommonJS가 현재 node의 표준인데 그 표준 방식이 require()module.exports이기 때문에 대부분 require() 키워드를 사용하여 불러오고 있었습니다. 그러나 ES6가 나오면서 자바스크립트 자체에서 ES6 Module이라는 개념을 사용하여 모듈화를 지원하기 시작했습니다.

현재는 많이들 import ... from에 익숙해진 것 같지만 readline을 사용하는 대부분 예시에서 require()을 사용하고 있어 잠깐 CommonJS에 대한 설명을 해 보려고 합니다.

  • module.exports
    딱 하나의 객체를 내보낼 경우, module.exports 변수 자체에 할당. 단, 객체를 묶어서 여러 개 값을 export 할 수 있다.
  • exports
    여러 개의 객체를 내보낼 경우, exports 변수의 속성으로 할당.

기존의 module.exports의 숏컷이 exports이다. 그러므로 혼용해서 쓰는 것은 옳지 않다. 사용하는 방법에서 보았듯 module.exports는 변수 자체에 할당하고 exports는 변수의 속성으로 할당한다. exportsmodules.exports를 가리키는 변수로써 그 사용을 도와주는 helper 역할로 참조만 한다.

2. interface 객체 만들기

interface 객체를 이용하여 콘솔에서 표준 입출력 처리를 할 수 있습니다.

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

stdin과 stdout에 대한 짧은 설명을 하자면 standard inputstandard output의 약자입니다.

3. 입출력 코드 작성하기

rl.on('line', (line) => {
  // 입력 받은 값을 처리하는 코드 //
  rl. close();
});
  
rl.on('close', () => {
  // 입력이 끝나고 실행하는 코드 //
  process.exit();
});
  • on() 메서드를 활용하여 이벤트와 콜백함수를 전달.
  • 'line' 입력 받은 값을 한 줄씩 읽어 문자열 타입으로 전달하는 역할을 하는 이벤트.
  • rl.close() 인터페이스를 종료. 무한히 입력 받는 것을 방지합니다. 그 후, 다시 이벤트로 close를 작성하여 입력이 끝난 후 실행되어야 할 함수를 작성합니다.

프로그래머스에서 만난 readline

📢 직각삼각형 출력하기

문제 설명

'*'의 높이와 너비를 1이라고 했을 때, '*'을 이용하여 직각 이등변 삼각형을 그리려고 합니다. 정수 n이 주어지면 높이와 너비가 n인 직각 이등변 삼각형을 출력하도록 코드를 작성해 보세요.

제한 사항

  • 1≤n≤10

입출력 예
입력 #1
3

출력 #1

*
**
***

입출력 예 설명
입출력 예 #1

  • n이 3이므로 첫째 줄에 * 1개, 둘째 줄에 * 2개, 셋째 줄에 * 3개를 출력합니다.

풀이

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

let input = [];

rl.on('line', function (line) {
    input = line.split(' ');
}).on('close', function () {
    for(let i = 1; i <= +input[0]; i += 1) console.log('*'.repeat(i));
});
  1. readline 변수로 readline 모듈을 불러옵니다.
  2. rl 변수로 inputoutput interface를 생성합니다.
  3. rl.on이 연속으로 붙어 있는데 각 라인마다 실행 후 종료, 실행 후 종료를 반복합니다.
  4. 실행하고 종료할 때마다 i값이 증가하게 되고, 각 줄마다 *이 추가로 생성되는 것을 확인할 수 있습니다.

부족하지만 제가 이해한 선 안에서 readline 모듈에 대해서 정리해 보았습니다. 앞으로 알고리즘 코딩 테스트 문제를 풀어가면서 더 익숙해질 모듈이라고 생각을 하고, 더 알게 된 지식이 있다면 추가해 보도록 하겠습니다! 🤗


참고 사이트 1 leenzy - readline 모듈 사용하기
참고 사이트 2 jangws - NodeJS에서 입력받기(콘솔창, 파일)
참고 사이트 3 longlive-jonghan -JavaScript 콘솔에서 값 입출력 (readline 모듈 기초)
참고 사이트 4 Dev Scroll(인파_) - [NODE] 📚 require 모듈 (모듈 관리하기) 정리
참고 사이트 5 leobit - CommonJS

0개의 댓글