[SOPT] # 2nd Seminar - NodeJS , Module, 비동기 흐름제어

✨New Wisdom✨·2020년 10월 18일
0

📗 Nodejs 📗

목록 보기
18/20
post-thumbnail
post-custom-banner

Nodejs

  • 서버 ❌
  • 프레임 워크 ❌
  • 프로그래밍 언어 ❌

🚩 특징

  • Non-Blocking I/O
  • Single Thread
  • Event Driven

🚩 Blocking vs Non-Blocking

제어권에 대한 이야기가 있다하면 blocking, non-blocking 얘기.

Blocking

파일 쓰기 요청 (제어권 획득) -> 대기 -> 파일 쓰기 완료 (제어권 return)
호출된 함수가 자신의 작업을 모두 끝날 때까지 제어권을 가지고 있어서 호출한 함수가 대기하도록 한다.
그동안 프로그램 처리 진행 불가

Non-Blocking

파일 쓰기 요청 (제어권 획득과 거의 동시에 제어권 return) -> 파일 쓰기 완료
호출된 함수가 바로 다음 호출한 함수에게 제어권을 주어 다음 작업을 바로 수행

🚩 Single Thread

Process

운영 체제에서 할당하는 작업의 단위로 프로세스 간에는 자원 공유를 하지 않는다.

Thread

일꾼.
프로세스 내에서 실행되는 흐름의 단위로 부모 프로세스의 자원을 공유할 수 있다.

노드를 실행하면 프로세스가 하나 생성된다.
생성된 프로세스는 여러개의 스레드를 생성하지만 제어 가능한 스레드는 단 1️⃣개이다. (Single Thread)

🤔 싱글 스레드 보다 멀티 스레드가 더 좋은거 아냐❓
context switching 시간도 있기 때문에 오히려 싱글 스레드가 더 빠르기도 함.
노드는 멀티 스레딩 보다는 멀티 프로세싱을 관리한다. ex) pm2

🚩 Event Driven

이벤트가 발생할 때 미리 지정해 놓은 작업을 수행하는 방식
노드는 이벤트 리스너에 콜백 함수를 지정해서 동작

JS 엔진은 Memory Heap과 Call Stack으로 이루어져있다.
JS는 Single Thread 프로그래밍 언이이므로, 단일 호출 스택이 있다.
= 한번에 하나의 Task만 처리할 수 있다.

Memory Heap

객체는 힙, 구조화 되지 않은 메모리 영역에 할당된다.
변수와 객체에 개한 모든 메모리 할당이 여기서 발생된다.

Call Stack

코드가 실행될 때 호출 스택이 쌓인다.
최재 Maximum size가 있어서 무한 호출?이 되면 에러가 난다.
처음 실행 시 전역 컨텍스트를 의미하는 Anonymous 함수가 호출 스택에 쌓인다.

function wakeUp(){
   wash();
}
function wash(){
    breakfast();
}
function breakfast(){
    throw new Error('콜스택에서 에러 찾기~!');
}

wakeUp();


오 이렇게 예외가 던져질 때 스택 호출이 어떤 순서로 일어나는지 볼 수 있는건 처음 알았다...

단일 콜스택의 문제점
콜스택이 하나라 하나의 함수 작업 시간이 엄청 길어서 다른 함수 실행에 지장을 준다면..?
-> 비동기 콜백 : 특수한 시점에 실행된다.

콜백 함수를 관리하는 법

Background
타이머나 이벤트 리스너들이 대기하는 곳, 여러 작업이 동시에 실행될 수 있다.
이벤트 발생 후 콜백 큐로 콜백 함수를 보낸다.
콜백 큐
이벤트 발생 후 콜백 함수들이 기다리는 공간으로 이벤트 루프가 콜 스택에 전달한다.
콜백큐에 있는 콜백 함수들은 콜스택이 비워지길 기다린다.
이벤트 루프
콜백 큐의 콜백 함수를 콜 스택에 전달하며 콜 스택이 비어있을 때만 가져온다.

비동기 흐름제어

🚩 동기 vs 비동기

동기 (Synchronous)

요청하는 시기와 응답을 받는 시기가 같다.
요청이 오면 응답이 완료될 때까지 프로그램이 정지하고, 응답을 받으면 다시 진행

비동기 (Asynchronous)

요청과 응답 결과가 동시에 일어나지 않는다.
요청에 대한 수행을 넘기고 응답을 기다리지 않고 바로 다음 작업을 수행

JS 코드 실행은 기본적으로 호이스팅이 완료되면 동기적으로 실행된다.
🤔 비동기적으로 실행하고 싶은 코드는 ❓

🚩 JS에서 비동기 처리 방법

Callback Function

어떤 이벤트가 발생하거나 특정 시점에 도달했을 때 시스템에서 호출되는 함수.
특정 함수의 인자로 넘겨서 코드 내부에서 호출되는 함수다.
⛔️ 문제점
callback Hell : 콜백함수 안에 또 콜백함수의 반복...

Promise

ES6에서 비동기 처리를 위해 도입한 패턴.
비동기 시점을 명확히 표현할 수 있다.

✔️ Promise의 3가지 상태

  • Pending : 최초 생성돼서 비동기 작업을 수행중인 상태
  • Fullfilled : 비동기 작업이 성공적으로 완료된 상태
  • Rejected : 비동기 작업이 실패한 상태 ex) 네트워크 오류, 파일 읽기 오류 등...

Pending

const promise = new Promise((resolve, reject){
	
})
  • new Promise(executor)
  • excutor : resolve와 reject를 파라미터로 갖는 콜백함수

Fullfilled
작업이 성공적으로 완료된 상태.
resolve()를 호출하면 fufilled 상태가 된다.
then()을 통해 결과를 전달한다.

Rejected
작업이 실패한 상태.
reject()로, catch()를 통해 전달된다.

Promise Chaining은 여러 개의 프로미스를 연결해 사용하는 것을 의미한다.

Async / Await

ES7부터 지원하는 JS 비동기 패턴.

함수 앞에 async 키워드를 붙이면 암묵적으로 Promise를 반환한다.
await 키워드는 async로 정의된 함수에서만 사용이 가능하다.

모듈

코드를 여러개의 파일로 분리하여 재활용성을 높이고 유지보수를 쉽게 할 수 있는 방법.

  • 내보내기 : module.exports = 객체 또는 함수 or export default 객체 또는 함수
  • 불러오기 : require() or import func1 from ''

🚩 File System

fs 모듈은 파일 시스템에 접근하는 모듈
파일 생성, 삭제, 읽기 / 폴더 생성, 삭제

  • 동기적 (Sync)
const fs = require('fs');
const numArr = [1, 2, 3, 4, 5];
const fileCommonName = ‘syncText';
numArr.forEach((num) => {
  const fileName = fileCommonName + num;
  const data = `reserved message for the '${fileName}'`;
  fs.writeFileSync(`${fileName}.txt`, data);
  console.log(`file[${fileName}] write complete`);
})
  • 비동기적 (Async)
onst fs = require('fs');
const numArr = [1, 2, 3, 4, 5];
const fileCommonName = 'asyncText';
numArr.forEach((num) => {
  const fileName = fileCommonName + num;
  const data = `reserved message for the '${fileName}'`;
  fs.writeFile(`${fileName}.txt`, data, () => {
  	console.log(`file[${fileName}] write complete`);
  }); 
});

🚩 Crypto

다양한 방식의 암호화를 도와주는 모듈.
단방향 암호화 방식으로 주로 hash 기법 이용.

const crypto = require('crypto');

const password = '123123';
const password2 = '12312';
const base64 = crypto.createHash('sha512').update(password).digest('base64');
const base64_ = crypto.createHash('sha512').update(password2).digest('base64');
const hex = crypto.createHash('sha512').update(password).digest('hex');
  • createHash() : 사용할 해시 알고리즘 입력. (주로 sha512 사용)
  • update() : 변환할 문자열을 넣어줌
  • digest() : 인코딩할 알고리즘을 넣어줌. (주로 base64 사용)

PBKDF2 (Password-Based Key Drivation Function)

가장 많이 사용되는 Key Driveation function으로
해시 함수의 컨테인너인 pbkdf2는 salt를 적용한 후 해시 함수의 반복 횟수를 임읠로 선택한다.
아주 가볍고 구현이 쉬우며 sha와 같이 검증된 해시 함수만 사용한다.

Hash
해시 알고리즘은 문자열을 특정 규칙을 이요해 다른 문자열로 치환한다.

Salt
해시 알고리즘으로 암호화 전 평문 암호에 salt라고 불리는 임의의 문자열을 붙인 후 암호화한다.

Key stretching
평문 암호에 salt 치고 해시 암호화 하는 작업을 수십만번 반복
내부적으로 멀티스레딩으로 동작한다.

const crypto = require('crypto');

crypto.randomBytes(64, (err, buf) => {
    const salt = buf.toString('base64');
    console.log(`salt : ${salt}`);
    crypto.pbkdf2('비밀번호', salt, 100000, 64, 'sha512', (err, key) =>{
      console.log(`password: ${key.toString('base64')}`);
    });
  });
  • crypto.pbkdf2(pw, salt, iterations, keylen, digest, callback)
profile
🚛 블로그 이사합니다 https://newwisdom.tistory.com/
post-custom-banner

0개의 댓글