js에서 비동기 I/O를 처리하는 방법을 보통 리액터 패턴으로 처리하고 있다.
Node.js는 이 패턴을 사용해 네트워크 요청, 파일 I/O, 데이터베이스 쿼리 등 작업을 비동기적으로 처리한다.
- 비동기 작업 등록 : 비동기 작업이 등록됨
- 이벤트 루프가 작업 대기 : 이벤트 루프는 이벤트 디멀티플렉서를 통해 비동기 작업이 완료되기를 기다림
- 작업 완료 시 콜백 실행 : 비동기 작업이 완료되면 이벤트 루프가 콜백함수를 실행해 결과를 처리함
const fs = require('fs')
fs.readFile('file.txt', 'utf8', (err, data)=>{
if(err){
return;
}
console.log('file : ', data)
})
console.log('it runs before readFile')
- fs.readFile은 비동기 파일 읽기 작업을 수행한다. 이 함수는 리액터 패턴의 예시로, 파일을 읽고 그 결과를 비동기적으로 처리한다.
- 파일을 읽는 동안 다른 작업은 차단되지 않고 계속 진행된다. 즉, readFile 함수는 바로 리턴되고, 이벤트 루프는 작업이 완료될 때까지 기다린다.
- 파일 읽기가 완료되면, 등록된 콜백 함수가 실행되어 파일의 내용을 출력한다. 이 부분이 리액터 패턴의 핸들러(콜백) 역할이다.
- console.log('it runs before readFile')는 파일 읽기가 완료되기 전에 실행된다. 이는 자바스크립트의 비동기 처리 방식을 보여주려고 작성되었다.
애플리케이션은 특정 시점에 리소스로(블로킹 없이) 접근하고 싶다는 요청과 동시에 작업이 완료되었을 때 호출된 핸들러를 제공한다.
- 이벤트 루프가 모든 작업을 관리하며, 비동기 작업이 완료될 때마다 콜백 함수를 실행한다. 이 과정이 리액터 패턴의 핵심이다.
- 블로킹 없이 I/O 작업을 처리할 수 있으며, 다른 작업이 완료될 때까지 대기하지 않고 다음 작업을 진행한다는 것이다.
- nodejs app은 이벤트 디멀티플렉서에 더 이상 작업이 없고 이벤트 큐에 더 이상 처리 중인 작업이 없을 경우에 종료된다.
- 즉, Reactor 패턴은 일련의 관찰 대상 리소스에서 새 이벤트를 사용할 수 있을 때 블로킹하여 I/O를 처리하고, 각 이벤트를 관련된 핸들러에 전달함으로써 반응하는 구조이다.
- 높은 성능: I/O 작업을 블로킹하지 않으므로, 많은 비동기 작업을 동시에 처리할 수 있어 성능이 우수하다.
- 효율적인 리소스 사용: 한 번에 하나의 작업을 블로킹하지 않고, 이벤트 루프를 통해 여러 작업을 효율적으로 처리할 수 있다.
리액터 패턴은 비동기 프로그래밍을 구현하는 핵심 디자인패턴이다.
이 방식 덕분에 Node.js는 높은 성능과 효율적인 리소스 관리를 가능하게 하며, 많은 사용자가 동시에 접근하는 대규모 서버 애플리케이션에서도 좋은 성능을 발휘할 수 있게 된다.
Node.js 디자인패턴바이블 책