교육 (Today I Learned)/Hanaro

[Hanaro] 16일차 / JavaScript (Module, 비동기 프로그래밍)

Bay Im 2024. 2. 6. 12:57

JavaScript - 모듈(Module)

  • ESM을 써야하는 이유(nodejs)
    • require시에 destructuring(구조 해제)가 된다. → module의 변수 값을 변경할 수 있다. (보안 취약)
  • tree-shaking & bundling
    • Tree shaking (ESM)
      • 죽은 코드 제거의 한 형태 (사용하지 않는 코드 제거)
      • 정적(구문) 분석을 통해 대상 선별 가능
        • 대상: 최상위 코드, 함수 내부와 동적 import에서 사용되지 않는 코드
    • Bundling : Babel + Webpack/Rollup
      • Bundling
        • 여러 개로 흩어져 있는 파일들을 하나의 파일로 모아주는 역할
      • Babel
        • JS의 컴파일러이며, 최신 버전의 JS가 실행되지 않는 구 버전의 브라우저에서 정상적으로 실행되도록 변환해준다.
          • $> npm i -D @babel/core @babel/cli @babel/preset-env
          • $> npm i @babel/polyfill
      • Webpack
        • 모듈 번들러라고 하며, 웹 애플리케이션을 구성하는 HTML, CSS, JavaScript, Image 등을 각각의 모듈로 보고 이를 조합해서 하나의 결과물로 만드는 도구
          • $> npm i -D webpack webpack-cli babel-loader

 

JavaScript - 비동기 프로그래밍

  • 동기(Synchronous) vs 비동기(Asynchronous)
    • Synchronous
      • 한번에 하나의 함수만 실행, 실행되는 동안 blocking → Single Thread in Single Process
      • Runtime → Execution Context → Execution Context Stack → Lexical Enviroment
    • Asynchronous
      • 한번에 하나의 함수만 실행
      • I/O를 수행하는 비동기 함수는 Background에 넘긴다. (non-blocking) → Single Thread But Multi Process
      • Runtime → Execution Context → Callstack → Background → OS → Task Queue → CallStack
    • CallStack (호출 스택)
      • 실행되는 함수가 등록되는 Stack
    • TaskQueue
      • 실행되어야 할 콜백 함수가 대기하는 Queue
    • Event Loop
      • TaskQueue에 있는 함수를 차례로 Callstack 으로 이동
    • Background
      • 별도 Process로 I/O 처리 후 콜백함수를 TaskQueue로 이동
  • 전통적인 비동기 Callback Pattern
    • JavaScript Asynchronous Programming History
      • Callback
      • Promise
      • Generator
      • Async / Await
  • Promise - ES6 표준 Built-in 객체(function)
    • Callback pattern의 단점을 극복하기 위해 출현
    • 안전하고 유지보수가 쉬운 코드 작성 가능 (exception safe)
    • 호출 시 Promise instance 반환 후 resolve & reject
    • Promise instance를 전달할 수 있어 편리
      • const p = new Promise(resolveFn, rejectFn){};
    • Promise 객체는 성공(fulfiled) 또는 실패(rejected) 상태를 갖는다.
    •   
      • Promise - basic pattern
    • try { setTimeout(() => { console.log(new Date()); throw new Error('어디로?'); }, 1000); } catch(err) { console.error('잡히나?', err); }​
const promi = new Promise((resolve, reject) => {
  setTimeout(() => {
    const now = Date.now();
    if (now % 2 === 0) resolve(console.log('fulfill', now));
    else reject(new Error('어디로?'));
  }, 1000);
});

console.log(promi);

promi.then(
  succ => console.log('Resolve!'),
  fail => console.log('Reject!', fail)
);

 

  • Promise Class Methods
    • Promise.resolve
      • 이미 존재하는 값
      • Promise.resolve(x).then(val ⇒ console.log(val));
      • new Promise(resolve ⇒ resolve(x)).then(console.log);
    • Promise.reject
      • Promise.reject(new Error(’…’)).catch(console.error);
      • new Promise((_, reject) ⇒ reject(new Error(’…’))).catch(console.error);
  • Promise Class Methods (Cont’d)
    • Promise.all
      • 여러 Promise Fn을 동시실행(concurrency)
      • 모두 성공(fulfilled) 시 시간과 무관하게 순서 보장
      • 하나라도 실패(rejected) 시 바로 catch로
      • Promise.all(iterables).then().catch(…
      • new Promise.all([p1, p2]).then(arr ⇒ console.log(arr));
    • Promise.race
      • 여러 Promise Fn 중 가장 빠른 것 하나만
      • 하나라도 실패(rejected) 시 바로 catch로
      • Promise.race(iterables).then().catch(..
      • new Promise.race([p1, p2]).then(arr ⇒ console.log(arr));
    • Promise.any
      • 여러 Promise Fn 중 제일 빨리 성공한 하나
      • 하나라도 성공(resolve) 시 바로 then으로
      • Promise.any(iterables).then().catch(…
      • new Promise.any([p1, p2]).then(…
    • Promise.allSettled
      • 여러 Promise Fn이 성공이건 실패건 모두 settled 될 때
      • 순서 보장
      • Promise.allSettled(iterables).then().catch(…
      • new Promise.allSettled([p1, p2]).then(…
  • async 함수
    • async / wait
      • Promise를 생성하고 소비하기 위한 문법적 설탕
      • 비동기 함수에서 콜백을 사용하는 대신 단순한 논리적 흐름(sync 동기처럼, 직렬)을 완성
      • Promise의 then, catch, finally를 사용할 필요 없음
      • async는 Promise를 반환, await는 resolve, reject와 매핑
      • 예외(erro)는 거부(reject)고, 거부(reject)는 예외(throw)다.
      • 반환(성공)은 확정(resolve)이고, 완료(resolve)는 결과(result)다.
      • ES2020부터는 최상위 수준 await 사용가능
  • async 함수의 병렬 처리
    • only Promise & then
      • 각각이 별도(OS) thread로 실행되므로 병렬이다.
    • async / await
      • 차례로 단일 thread가 실행되므로 직렬이다.
      • 연관이 없는 비동기 함수 실행에 async/await을 남발하지 말기
  • 비정상 await
    • map에서의 실수
      • 각각이 별도 Promise(thread)로 실행 (async는 Promise를 반환한다.)
    • filter에서의 실수
      • 각각이 Promise(thread) 반환 (never false)
  • fetch 함수
    • fetch()는 첫번째 인자로 URL, 두번째 인자로 옵션 객체를 받고 Promise 타입의 객체 반환
      • 옵션 객체: method, headers, body
    • 반환된 객체는 API 호출이 성공했을 경우에는 응답(response) 객체를 resolve하고 실패했을 경우에는 예외(erro) 객체를 reject
      • 응답 객체: status, headers, body
    fetch(url, options)
      .then((response) => console.log("response:", response))
      .catch((error) => console.log("error:", error));