readline module은 Node.js의 한 줄 단위로 readable stream을 처리할 수 있게 해주는 모듈이다.
다른 많은 사람들이 그렇듯이 JavaScript 코딩 테스트를 준비하며 이 모듈을 처음 접하게 되었고, 사용법을 정리해놓을 필요가 생겼다.
# 공식 문서
https://nodejs.org/api/readline.html
# readline 사용법
모듈 불러오기 및 인터페이스 생성
공식문서에서는 CommonJS와 ES modules 방법을 제시해주고 있으나, 현재 사용중인 프로그래머스에서는 ESM, 즉 'import'를 사용하는 방법을 지원하지 않는다.
따라서 CommonJS 방식만 살펴보겠다.
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
주요 이벤트
'line': input stream이 end-of-line input (\r, \n, \r\n)을 받을 때 이 이벤트가 발생한다.
'close': 다음과 같은 경우에 이벤트가 발생한다.
- rl.close() method 호출 시
- input stream이 'end' 이벤트를 받은 경우
- input stream이 EOT를 받은 경우 (Ctrl + D)
- 인터페이스에 SIGINT의 이벤트 리스너가 등록되지 않은 상태로 input stream이 SIGINT를 받은 경우 (Ctrl + C)
이벤트 처리
인터페이스의 'on' method를 통하여 처리한다.
첫 번째 parameter로는 이벤트 타입을 나타내는 string, 두 번째 parameter로는 이벤트 발생 시 실행할 callback function을 전달하면 된다.
rl.on('line', line => {
// do something
rl.close();
});
rl.on('close', () => {
// do something
process.exit();
});
혹시 조금 더 간결하게 코드를 작성하고 싶은 경우에는 다음과 같이 on method를 chaining하여 사용할 수 있다.
rl.on('line', line => {
// do something
rl.close();
}).on('close', () => {
// do something
process.exit();
});
여기서 주의할 점은 'line' 이벤트 처리 시 rl.close()를 호출하지 않으면 무한히 입력을 받는 문제가 발생할 수 있다는 것이다.
의문점
프로그래머스에서는 딱히 rl.close()를 호출하지 않아도 잘 동작한다.
close event 발생 조건을 생각해보면 "input stream이 'end' 이벤트를 받은 경우"가 가장 의심스럽다.
아마 프로그래머스 채점 시스템에서 내부적으로 input 마지막에 end event를 발생시키거나 하지 않을까 싶다.
혹은 내가 작성한 코드가 무언가의 method로 실행되고 끝날 때 인터페이스가 삭제되면서 end event를 발생시키나...?
이 부분은 정확히 알 수 있는 방법은 당장 안보인다.
일단은 불안하니 왠만하면 close를 쓰자!