ARCHIVE/DB

[Node.js] 비동기

man_on 2021. 9. 13. 02:00
반응형

 

 

 

비동기 실행 

 : 특정 작업이 완료되었을 때 실행할 콜백을 등록해두고 바로 다음 코드로 실행을 넘기는 것

( 이전 작업의 마무리 여부에 상관없이 그 다음 일을 처리하는 작업 방식 )

 

 

 

> 비동기 실행의 장점

  : '동기 실행'에 비해 '비동기 실행'이 훨씬 더 빠름

 

동기실행 : 순차적으로 진행
비동기 실행 : 멀티테스킹 > 스레드나 프로세스가 여럿 돌고있음

 

 

 

> 프로그램의 실행 흐름

Process 프로세스 : 하나의 실행 흐름

Thread 스레드 : 그 안에있는 더 작은 단위의 실행흐름

 

더보기

ex) chrome 실행 ( 더블클릭 > 실행)

   hard-disk나 SSD에 저장되있던 프로그램 > memory에 올려서 > CPU(central Processing Unit)실행

   하나의 크롬 '프로세스'생성 > 그 안에 하나의 '스레드'가 실행 중 상태

 

   영화다운 (스레드-1) / 음악재생 (스레드-2) / 구글검색 (스레드-3) ----실행의 최소단위

   컴퓨터 에러 시 '프로세스 강제종료'   ----스레드보다 큰 실행흐름

 


 

 

 

 

 1. 비동기 함수 사용

 2. EventEmitter 객체 사용 (event 기반 프로그래밍)

 

 

 

비동기 함수

 

fs . readFile ( path [, options],  callback) 

(1) path : 내용을 읽을 파일의 경로 (필수)

(2) options : 파일의 내용을 읽을 때 적용할 옵션 (선택) - ex) utf8

(3) callback : 파일의 내용을 다 읽었을 때 실행될 콜백 (필수)

      ( 일반적으로 err(error, problem 등의 이름) 인자 첫번째, data(result, output 등) 같이 작업결과 나타내는 인자는 뒤에 ) 

import { readFile } from 'fs';

readFile('/etc/passwd', (err, data) => {
  //함수내용
  if (err) throw err;
  console.log(data);
});

 

 

> 동기 실행 함수

더보기

fs . readFileSync ( path [, options] )   동기 실행함수

import { readFileSync } from 'fs';

// macOS, Linux, and Windows
readFileSync('<directory>');
// => [Error: EISDIR: illegal operation on a directory, read <directory>]

//  FreeBSD
readFileSync('<directory>'); // => <data>

 

 

 

setTimeout(callback, milliseconds)

    : 특정 밀리세컨즈 초 후에 코드실행

      milliseconds(밀리세컨즈, 1000분의 1초) 후에 callback 인자에 설정한 함수를 실행

더보기
let num = 1;           // 1번

setTimeout(() => {     // 2번
  num = 2; // 세번째    // 5번
}, 1000);

num = 3;                // 3번

console.log(num);       // 4번


/*
(1) num 변수에 1을 대입

(2) setTimeout 함수 실행(1초 후에 실행될 콜백 설정)

(3) num 변수에 3을 대입

(4) num 변수의 값 출력

(5) setTimeout에서 설정해둔 콜백 실행
*/

 

 

 

 

> Node.js 개발 시 주의점

 메인 스레드가 작업에 큰 부하를 주지않아야 함.

  ( CPU로 하는 수치 계산 작업 / 네트워크로 들어오는 클라이언트의 요청 받아들이고 응답하는 작업) 

더보기

-Node.js 내부에서의 비동기 실행 구현 방법 중 한 가지-

1) 스레드 1개(이 스레드를 '메인 스레드'라고 합니다) 싱글 스레드

  • 자바스크립트 코드 실행하기
  • 이때 오래 걸리는 작업(작업 A)은 다른 스레드에 넘기기 (ex. fs.readFile('new', callback)에서 파일 읽기는 별도 스레드에 넘기기)
  • 그리고 일단 그다음 작업 B를 시작하기
  • 작업 A가 완료되었다는 알림과 그 작업 결과를 받으면
  • 작업 결과를 가지고 콜백 실행하기(ex. 읽어 들인 파일 내용을 인자로 넣고, callback 실행)

2) 스레드 10개 ( C++ 쓰레드 )

  • 메인 스레드가 요청한 작업 처리하기(ex. 파일 읽기)
  • 작업이 완료되면 끝났다고 메인 스레드에 알려주고, 작업 결과 전달하기 (ex. 파일 내용을 다 읽고, 그 내용을 메인 스레드에 전달)

1. 메인 스레드는 빠르게 처리할 수 있는 작업들을 집중해서 '혼자' 처리하고,

2. 파일 읽기와 같이 시간이 오래 걸리는 작업은 다른 스레드에 맡김

 

 


 

 

EventEmitter

 

> event로 비동기 실행 / core module의 많은 객체들이 EventEmitter 객체.

> 하나의 event관해 여러개의 event handler설정가능

> myEmitter.on ← myEmitter.emit

> callback = listener = event handler

 

 : Much of the Node.js core API is built around an idiomatic asynchronous event-driven architecture in which certain kinds of objects (called "emitters")emit named events that cause Function objects "listeners" to be called.

 

 :  All objects that emit events are instances of the EventEmitter class.

 

> EventEmitter 객체 사용법

더보기
const EventEmitter = require('events');

const myEmitter = new EventEmitter();

/*
myEmitter.emit('test');           

myEmitter.on('test',() => {        //test이벤트 이미 발생되어서 callback함수 실행안됨
 console.log('success!');
});
*/

myEmitter.on('test',() => {        //event발생전에 콜백함수 실행되어야됨
 console.log('success!');
});

myEmitter.emit('test');

 

 

 

> on 메소드

 : event handler를 설정하는 메소드 ( = emitter.addlistener(eventName, listener) 동일기능의 메소드/짧은 on 선호)

const EventEmitter = require('events');

const myEmitter = new EventEmitter();

const obj = {type : 'text', data:'hello world', date: '2021-09');

myemitter.on ('test', (info) => {
 console.log(info);
});

myEmitter.emit('test', obj);

//출력
{type : 'text', data:'hello world', date: '2021-09')

 

 

 

> emit 메소드

 : 인위적으로 event 발생시킴 ( 보통 코어모듈 사용하므로 자주사용 x / 나만의 eventemiiter객체 사용시 )

const EventEmitter = require('events');     //events라는 코어모듈 / eventemitter라는 class

const myemitter = new EventEmitter();       //class를 객체에 담아줘야 사용가능

myemitter.on('test', () => {                //test라는 이벤트발생 시 callback으로 success출력
 console.log('Sucess!');
});

myEmitter.emit('test');                     //emit으로 test라는 이벤트 발생시킴

 

> once 메소드

 : on과 유사하지만 해당 event대해서 딱 한번만 반응해서 실행

 

 

> listeners 메소드

 : 특정 event대한 event handler를 출력

   코드 작성시 특정 event에 지금 어떤 event handler들 설정되어 있는지 조회하고 싶을때

더보기
const EventEmitter = require('events');

const myEmitter = new EventEmitter();

myEmitter.once('test', () => {
  console.log('A');
});

myEmitter.once('test', () => {
  console.log('B');
});

myEmitter.once('test', () => {
  console.log('C');
});

console.log(myEmitter.listeners('test'));

// [ [fuction], [fuction], [fuction], ] 출력

> off 메소드

  : event handler해제 / 해제할 이벤트 핸들러 정확히 지정

const EventEmitter = require('events');

const myEmitter = new EventEmitter();

const callback = () => {        //event handler를 변수에 할당해서 off에서 참조될 수 있게
  console.log('Success!');
};

myEmitter.on('test', callback);

myEmitter.off('test', callback);

myEmitter.emit('test');

https://nodejs.org/api/events.html#events_class_eventemitter

 

 

Events | Node.js v16.9.1 Documentation

Events# Source Code: lib/events.js Much of the Node.js core API is built around an idiomatic asynchronous event-driven architecture in which certain kinds of objects (called "emitters") emit named events that cause Function objects ("listeners") to be call

nodejs.org

 

 

 

 

 

 


 

 

 

 

 

🔻  비동기 함수의 callback 실행원리

 

  Event Loop

  : 각종 콜백들의 실행 조건(특정 시간이 경과했는지 등)을 확인하고, 실제로 콜백을 실행하는 로직

    Event Loop는 특정 콜백의 실행 조건이 만족된 것을 확인하면 Queue라는 곳에 콜백(callback)들을 삽입

 

  Queue 큐

 : 데이터간 순서관계를 유지

   맨 뒤 데이터 추가  / 맨 앞 데이터 삭제 / 맨 앞 데이터 접근

 : callback이 저장되는 저장소

 : FIFO (First-in-first-out) 가장먼저 들어온 데이터가 가장먼저 삭제됨.

더보기

> 콜백이 여러개 일대 각 콜백의 실행조건이 충족될 때, 차례대로 Queue에 들어감

> 콜백들은 Queue에 들어간 순서대로 event loop에 의해 실행

 

> node로 js파일 실행

    1. 하나의 스레드가 js코드를 실행

    2. 그 후, 그 스레드가 event loop라는 로직에서 각각의 콜백들에 대한 실행여부 판단, Queue에 넣은 후,

       Queue에 담긴 콜백들을 실행

Node.js의 내부 구현

    > 여러종류의 Queue존재, 각 콜백들은 그것을 등록한 함수에따라 서로다른 Queue에 담김

    > Event loop가 각 Queue의 callback판단하고 처리하는 방식에도 조금씩 차이

 

https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/

 

The Node.js Event Loop, Timers, and process.nextTick() | Node.js

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org


 

 

JavaScript 런타임 환경

 : JavaScript 로 짜여진 소스코드를 CPU가 이해할 수 있는 기계어(ex. 0과 1로 이루어진 bytecode)로 변환시키고

   프로그램의 메모리를 관리하는 시스템

 > 이런 환경을 가능하게끔 하는 것이 Chrome V8 엔진 - 비동기 이벤트-기반의 처리를 이 Chrome V8 엔진이 담당

   ( 우리가 알고 있는 구글의 크롬 웹브라우저에서 작동하는 엔진.

     이 엔진이 브라우저 없이 작동할 수 있도록 만든 환경이 바로 노드)

 

 

 

반응형

'ARCHIVE > DB' 카테고리의 다른 글

[DB] MySQL  (0) 2021.09.15
[DB] Database 기초  (0) 2021.09.14
[Node.js] express  (0) 2021.09.13
[Node.js] Protocol / Port / URL  (0) 2021.09.13
[Node.js] Node.js 기본  (0) 2021.09.12