[포스코x코딩온] KDT-Web-8 4주차 회고3 - Node.js & 동기, 비동기

Yunes·2023년 7월 30일
0

[포스코x코딩온]

목록 보기
10/47
post-thumbnail

📚 서론

금주동안 Nodejs, express, 동기 비동기에 대해 배우는 시간을 가졌고 수업중 궁금점이 생겼던 부분과 학습했던 내용을 정리하였다.

📘 Node.js

Node.js 는 V8 JS 엔진으로 빌드된 javascript 런타임 환경이다. 즉, 브라우저에서 작동되도록 했던 자바스크립트를 브라우저 이외의 환경에서도 동작할 수 있도록 독립시킨 자바스크립트 실행 환경이라고 보면 된다.

FE, BE 에서 JS 를 사용할 수 있다는 동형성 isomorphic 은 별도의 언어 학습 시간을 단축해주게 한다. 즉, javascript 만 알아도 FE, BE 개발 모두를 할 수 있게 해준다.

자바스크립트는 단일 스레드 언어이기에 메인 스레드에 blocking (대기시간)이 발생시 웹페이지 표시가 지연될 수 있다. Node.js의 모든 API 는 비동기 방식으로 동작하여 Non-blocking I/O 가 가능하며 단일 스레드 이벤트 루프 모델을 사용해 가벼운 환경에서도 높은 Request 처리 성능을 갖고 있다.

react 와 같은 SPA 에 적합하나 CPU 사용률이 높은 애플리케이션에서는 권장되지 않는다.

📗 설치

node.js 공식 docs

혹은 mac 사용시, homebrew 를 통한 설치

  • homebrew 설치
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  • brew 로 node 설치
brew install node

homebrew 는 매우 편리하다. mac 을 사용시 설치가 필요한 부분의 처리가 매우 용이해진다. 다만 인텔칩에서 m1, m2 칩으로 넘어오며 문제가 생긴 것 같다.

zsh: command not found: brew

brew 를 설치했는데 못찾는다. stack overflow 에 찾아본 결과 m1 칩으로 넘어오면서 homebrew 경로가 원래 /usr/local/bin/node 가 아닌 /opt/homebrew 로 설정되었는데 이 경로 문제로 인해 설치가 되었으나 설치된 디렉토리로 접근을 못해서 생기는 것 같다고 한다. 그래서 desktop 에서는 동작이 되도 global 설정이나 다른 이슈로 인해 프로젝트 디렉토리에서 brew 나 node 를 못찾는 현상이 발생하는 것 같다.

그래서 brew 로 설치시 바로 사용할수 있으면 좋지만 안될시

export PATH=/opt/homebrew/bin:$PATH

위의 명령어를 통해 .zshrc 같이 환경변수를 관리하는 곳에 경로를 재설정해주는 등의 추가 작업이 필요하다.

매우 번거롭다.

사실 node 만의 문제는 아니다. 실제로 m1 pro 를 사용해보면서 homebrew 를 통해 라이브러리를 설치시 경로 문제로 굉장히 고생했기에 맥북을 사용한다면 마음편히 공식 홈페이지의 다운로드 파일을 통해 실행하는 것을 지양하는 편이다.

npm 은 node.s 에 포함되어 있어 Node.js 설치시 자동 설치되어 별도의 설치가 필요 없다. 단 npm 보다 자주 업데이트되므로 다음의 명령어를 통해 npm 을 업데이트할 수 있다.

npm i -g npm@latest

📗 npm

npm 사용시 다음의 명령어를 사용한다.

npm init --yes

npm 을 통해 패키지를 설치시 node_modules 가 생성된다.

express, ejs 를 사용하려 하니 다음의 명령어를 통해 설치했다.

npm i express
npm i ejs

패키지는 mac 기준 다음의 경로에 설치된다.

/usr/local/lib/node_modules

📕 package.json vs package-lock.json

두 파일은 프로젝트의 종속성(dependency) 와 버전 관리를 도와주는 역할을 한다.

package.json

  • 프로젝트의 기본 정보와 종석성 목록 포함
  • 수동으로 작성하거나 npm init 명령어를 통해 생성
  • 일반적으로 프로젝트 이름, 버전, 작성자, 설명 등의 정보가 포함되며, dependencies devDependencies와 같은 섹션에서 프로젝트가 의존하는 라이브러리와 그 버전 정보를 기록한다.
  • dependencies는 프로덕션 환경에서 필요한 라이브러리들을 기록하고, devDependencies는 개발 환경에서만 필요한 라이브러리들을 기록한다.
  • npm install 명령어 실행시 package.json 에 명시된 종속성들을 자동으로 설치한다. 다만 최신 버전으로 설치하므로 협업시 npm ci (최신 버전이 아닌 명시되어 있는 버전으로 설치) 를 사용하자.
  • script : npm run 을 이용해 정해 놓은 스크립트 명령어

package-lock.json

  • package-lock.json 파일은 package.json에 명시된 종속성들의 정확한 버전과 의존성 트리(dependency tree)를 포함한다.
  • 이 파일은 npm install 명령을 실행했을 때 자동으로 생성된다.
  • package-lock.json 파일은 프로젝트를 다른 환경으로 옮기거나, 다른 개발자와 공유할 때 정확한 종속성 버전을 보장하는 데 도움을 준다.
  • npm은 이 파일을 참조하여 정확히 동일한 버전의 종속성을 설치하도록 보장한다.

📕 자주 쓰는 npm 명령어

# 기본 설정
npm init -y

# 로컬 설치
npm i <package-name>

# 전역 설치
npm i -g <package-name>

# 개발 설치
npm i --save-dev <package-name>

# 로컬/개발 패키지 제거
npm uninstall <package-name>

# 전역 패키지 제거
npm uninstall -g <package-name>

# 패키지 업데이트
npm update <package-name>

# package.json script 프로퍼티의 start 이외의 script 실행
npm run <script-name>

📗 REPL (Read Eval Print Loop: 입력 수행 출력 반복)

node

위의 명령어를 통해 js 파일, script, 브라우저의 콘솔이 아닌 터미널에서 js 를 바로 실행할 수 있었다.

이처럼 대부분의 언어가 제공하는 가상환경으로 간단한 코드를 직접 실행해 결과를 확인할 수 있는 것을 REPL 이라고 부른다.

📗 Node.js 특징

📕 프로세스 & 스레드

스레드 : 프로그램 내의 처리 실행 단위 혹은 CPU 이용 단위, 한 프로세스 내에서 나뉘어진 하나 이상의 실행 단위

일련의 처리를 단일 스레드만으로 직렬 처리하는 프로그래밍 방법을 싱글 스레드 프로그래밍이라 한다.

싱글 스레드는 프로세스 내에서 하나의 메인 스레드만으로 작업을 처리하며 작업을 차례대로 처리한다. 선행 스레드가 길어질 경우 후행 스레드는 선행 스레드가 끝날 때까지 기다려야 한다.

프로세스 : 실행중에 있는 프로그램을 의미한다.

프로세스 내부에는 최소 하나의 스레드를 갖고 있으며 스레드 단위로 스케줄링을 한다.


아직 이해가 잘 안된 것 같다. 용어 정리부터 다시 해보자.

✏️ 실행 단위 : 스레드, 프로세스 모두에서 사용하는 용어. cpu core 에서 실행하는 하나의 단위로 프로세스와 스레드를 포괄하는 개념이며 한 cpu core 에 한순간에 한개씩 적재되는 것을 말한다.
✏️ (부연 설명이 없는) 프로세스 : 하나의 스레드만 가지고 있는 단일 스레드 프로세스
✏️ 동시성 : 한순간에 여러가지 일이 아니라 짧은 전환으로 여러가지 일을 동시에 처리하는 것처럼 보이는 것

우아한테크 10분 테코톡 코다의 Process vs Thread 에서는 피자와 레시피를 예시로 들면서 레시피를 프로그램, 피자를 실행이 되어 사용할 수 있는 무언가인 프로세스에 비유했다.

하나의 CPU 를 2개의 프로세스가 실행을 위해 점유하려고 하는 상황이다. 실행중인 프로세스는 실행, 대기중인 프로세스는 준비 상태에 있는데 동시에 사용하기 위해서는 이 두 프로세스가 실행과 중비 상태를 반복하며 하나의 CPU 를 마치 동시에 점유하는 듯이 컨텍스트 스위칭 과정을 거친다. 매우 복잡한 과정이다.

그래서 등장한게 경량화된 프로세스 버전인 스레드 이다.

경량화된 프로세스 버전인 까닭은 하나의 프로세스 내에 다수의 스레드가 있을 때 공유되는 자원이 있기 때문이다.

프로세스의 메모리 구조 :

  • Code : 실행 명령을 포함하는 코드
  • Data : Static 변수 혹은 Global 변수
  • Heap : 동적 메모리 영역
  • Stack : 지역변수, 매개변수, 반환 값 등의 일시적인 데이터

이중 스레드는 Code, Data, Heap 영역을 공통된 자원으로 사용한다. 따라서 각 스레드는 Stack 부분만 따로 갖는다. 이로 인해 컨텍스트 스위칭 이 일어날 때 캐싱 적중률이 올라간다.

멀티 프로세스 : 한 애플리케이션에 여러 사용자의 로그인을 처리한다고 할때 프로세스는 한번에 하나의 로그인만 처리할 수 있으니 부모 프로세스가 자식 프로세스를 여럿 생성하여 각자 별개의 메모리 영역을 지닌채 로그인을 처리

멀티 스레드 : 한 프로세스 내에서 구분지어진 실행 단위. 공유된 자원으로 메모리 효율적, Context Switching 비용 적다.

멀티 스레드는 서로 긴밀히 연결되어 있기 때문에 전체 프로세스에 영향을 끼친다.


영상에서는 위의 내용처럼 프로세스와 스레드, 멀티 프로세스와 멀티 스레드 등의 개념을 소개하나 자바스크립트는 그 무엇도 아닌 싱글스레드 언어이다. 자바스크립트는 동시성같은 동작을 위해 멀티 프로세스도 멀티 스레드도 아닌 이벤트 루프를 통해 비동기 처리를 한다.

📕 Non-blocking I/O

  • 동기 : 데이터의 요청과 결과가 한 자리에서 동시에 발생, 한 요청에 서버의 응답이 이루어질 때까지 계속 대기

  • 비동기 : 동시에 일어나지 않음. 요청한 후 응답을 기다리지 않고 다른 활동을 한다.

📕 Event-Driven

  • Event-Driven : 이벤트 발생시 미리 지정해둔 작업 수행
  • 이벤트 리스너 : 이벤트 등록 함수
  • 콜백 함수 : 이벤트 발생시 실행되는 함수

📗 모듈

ES6 에서 Client-Side JS 에서도 동작하는 모듈 기능을 추가했다. 단 현재 대부분의 브라우저가 ES6의 모듈을 지원하지 않고 있으므로 ES6 모듈을 현재의 브라우저에서 사용하기 위해서는 SystemJS, RequireJS 등의 모듈 로더 또는 Webpack 등의 모듈번들러를 사용하여야 한다. ES6 모듈은 키워드 export, import를 제공한다.

모듈은 module.exports 또는 exports 객체를 통해 정의하고 외부로 공개한다. 그리고 공개된 모듈은 require 함수를 사용하여 임포트한다.

const a = '1';

module.exports = {a}

module.exports 에는 하나의 값(원시 타입, 함수, 객체)을 할당할 수 있다.

const a = require('./module.js');

Node.js 가 기본적으로 포함하는 모듈을 코어 모듈이라 한다. npm 을 통해 설치한 외부 패키지 또한 패스를 명시하지 않아도 된다.

const http = require('http');
const mongoose = require('mongoose');

만약 package.json 에 type: module 을 추가하면 require 대신 import 를 사용한다.


이때 export 와 export default 의 차이는 다음과 같다.

  • export 는 이름을 그대로 살려서 보내는 것이고 default export 는 default 로 내보낸다. export default 사용시 import 할때 아무 이름으로 받아올 수 있다.
  • 한 모듈 안에 여러가지 export 시 export 를 , 한 모듈 내에 export 대상이 하나면 export default 를 사용한다.

📗 HTTP 상태코드

클라이언트가 보낸 요청의 처리 상태를 응답에서 알려주는 기능

1xx Informational : 요청이 수신되어 처리중


2xx Successful : 요청 정상 처리

  • 200 : OK
    • GET
  • 201 : Created
    • POST
  • 202 : Accepted
    • 요청이 접수되었으나 처리가 완료되지 않음
  • 204 : No Content
    • 요청 성공적, 응답 페이로드 본문에 보낼 데이터가 없다.

3xx Redirection : 요청을 완료하려면 추가 행동이 필요
웹 브라우저는 3xx 응답 결과에 Location 헤더가 있으면, Location 위치로 자동 이동한다. ( 리다이렉트 )

  • 300 Multiple Choices
    • 안씀
  • 301 Moved Permanently ( 리소스 URI 영구적 이동 )
    • 리다이렉트시 요청 메서드가 GET 으로 변하고, 본문이 제거될 수 있다. (may)
  • 302 Found (리소스 URI가 일시적으로 변경)
    • 리다이렉트시 요청 메서드가 GET 으로 변하고, 본문이 제거될 수 있다.
  • 303 See Other (리소스 URI가 일시적으로 변경)
    • 302 와 기능 동일
    • 리다이렉트시 요청 메서드가 GET 으로 변경 (must)
  • 304 Not Modified
    • 캐시를 목적으로 사용
    • 클라이언트에게 리소스가 수정되지 않았음을 알려준다. 따라서 클라이언트는 로컬 PC 에 저장된 캐시를 재사용한다. ( 캐시로 리다이렉트 )
  • 304 응답은 응답에 메시지 바디를 포함하면 안된다. (로컬 캐시를 사용해야 하므로 )
    • 조건부 GET, HEAD 요청시 사용한다.
  • 307 Temporary Redirect (리소스 URI가 일시적으로 변경)
    • 302와 기능 동일
    • 리다이렉트시 요청 메서드와 본문 유지(요청 메서드를 변경하면 안된다.)
  • 308 Permanent Redirect ( 리소스 URI 영구적 이동 )
    • 리다이렉트시 요청 메서드와 본문 유지(처음 POST를 보내면 리다이렉트도 POST 유지)

PRG : POST/Redirect/Get

  • 일시적인 리다이렉션 - 예시
    • POST 로 주문후에 웹 브라우저를 새로고침하면?
    • 새로고침은 다시 요청
    • 중복 주문이 될 수 있다.
  • POST 로 주문후에 새로 고침으로 인한 중복 주문 방지
  • POST 로 주문후에 주문 결과 화면을 GET 메서드로 리다이렉트
  • 새로고침해도 결과 화면을 GET 으로 조회
  • 중복 주문 대신에 결과 화면만 GET 으로 다시 요청

4xx Client Error : 클라이언트 오류, 잘못된 문법등으로 서버가 요청을 수행할 수 없음

  • 클라이언트의 요청에 잘못된 문법 등으로 서버가 요청을 수행할 수 없음

  • 오류의 원인이 클라이언트에 있다.

  • 클라이언트가 이미 잘못된 요청, 데이터를 보내고 있기 때문에, 똑같은 재시도가 실패한다.

  • 400 Bad Request : 잘못된 문법으로 인해 서버의 요청을 이해할 수 없다.

  • 401 Unauthorized : 미승인

  • 403 Forbidden : 클라이언트가 콘텐츠에 접근할 권리를 갖고 있지 않다.

  • 404 Not Found : 서버가 요청받은 리소스를 찾을 수 없다.


5xx Server Error : 서버 오류, 서버가 정상 요청을 처리하지 못함

📘 Express, ejs

Express : Node.js 환경에서 동작하는 웹 애플리케이션 프레임워크. 웹 애플리케이션 구성에 필요한 Routing, View Helper, Session 등의 기능 제공

npm i express
const express = require('express');
const app = express();

app.get('/', function(req, res) {
	res.send('hello express');
});

app.listen(3000, () =>
  console.log('Example app listening on port 3000!')
);

  • express 가 지원하는 라우팅 메소드 : get, post, put, head, delete, options, trace, copy, lock, mkcol, move, purge, propfind, proppatch, unlock, report, mkactivity, checkout, merge, m-search, notify, subscribe, unsubscribe, patch, search, connect.

  • express() : express 모듈이 export 하는 최상위 함수로 express application 을 만든다.

  • app 객체 : express() 함수를 호출함으로써 만들어진 express application

📗 Response method

메소드설명
res.download()다운로드될 파일을 전송한다.
res.end()응답 프로세스를 종료한다.
res.json()JSON 응답을 전송한다.
res.jsonp()JSONP 지원을 통해 JSON 응답을 전송한다.
res.redirect()요청 경로를 재지정한다.
res.render()view template을 렌더링한다.
res.send()다양한 유형의 응답을 전송한다.
res.sendFile()파일을 옥텟 스트림(이메일이나 http에서 사용되는 content-type에서 application의 형식이 지정되어 있지 않은 경우에 octet-stream이라고 한다)의 형태로 전송한다.
res.sendStatus()응답 상태 코드(response status code)를 설정한 후 해당 코드를 문자열로 표현한 내용을 응답 본문으로서 전송한다.

📗 정적 파일 제공

정적 파일을 제공하기 위해 express 기본 제공 미들웨어 하수인 express.static 를 사용한다.

index.js

app.use("/public", express.static("./public")); // - 1
app.use(express.static("public")); // - 2

app.use("/public", express.static("./public"));

  • /public 경로로 오청이 오면 해당 파일을 ./public 폴더 내의 정적 파일로 연결한다.

app.use(express.static("public"));

  • 애플리케이션 루트 경로에서 바로 정적 파일을 제공한다.

📗 템플릿 엔진

Express 는 handlebars, pug, ejs 와 같은 템플릿 엔진을 사용할 수 있다.

템플릿은 views 디렉토리에 작성

npm i ejs
// 뷰엔진
app.set("view engine", "ejs");
app.set("views", "./views");

<html>
  <head>
    <title>Document</title>
  </head>
  <body>
    <h1><%= data %>단</h1>
    <% for (var j = 1; j < 10;j++) { %>
      <% console.log(`${data} x ${j} = ${data * j}`); %>
      <p><%= data %> x <%= j %> = <%= data * j %></p>
    <% } %> 
  </body>
</html>

데이터를 불러올때 <%= %>
js script 실행하는 줄일때 <% %>
이때 %% 사이에 한칸이 띄어져 있어야 한다.

📘 Promise

비동기 작업을 조금 더 편하게 처리 할 수 있도록 ES6 에 도입된 기능이다. 이전까지 콜백함수로 비동기 작업을 처리했으나 콜백 지옥과 같은 문제가 있어 Promise 를 사용시 코드의 깊이가 깊어지는 현상을 방지할 수 있다.

📗 Promise 만들기

const myPromise = new Promise((resolve, reject) => {
	setTimeout(() => {
    	resolve();
      	// reject(new Error("에러 발생!"));
    }, 1000);
})

myPromsie
  .then(  // 성공시
	result => alert(result), // 성공시
    error => alert(error) // 실패시 Error: 에러 발생! 출력
  )
  .catch( (error) => { // 실패시
	console.log(error);
  })
  .finally( () => { // 성공이든 실패든 항상 실행
	console.log();
  })
  • resolve(value) : 일이 성공적으로 끝날시 그 결과를 나타내는 value 와 함께 호출
  • reject(error) : 에러 발생 시 에러 객체를 나타내는 error 와 함께 호출
  • then : 첫번째 인수는 promise 가 이행시 실행되는 함수, 실행 결과를 받는다. 두번째 인수는 promise 가 거부되었을때 실행되는 함수, 에러를 받는다.

프로미스를 보면 resolve 에서 콜백함수를 통해 value 를 전달하는 것을 볼 수 있다. 그렇다면 then 이 resolve 시 실행되는데 그 내부에 콜백함수를 사용하고 있으니 이 콜백함수의 parameter 가 Promsie resolve 로 전달하는 것과 같다.

프로미스 체이닝 은 result 가 .then 핸들러의 체인을 통해 전달된다는 점에서 착안한 아이디어이다. 앞의 프로미스에서 반환한 값은 다음 .then 핸들러에 전달되는 과정이 계속 이어진다.

📗 Promise.all

Promise.all 메서드는 여러 개의 비동기 처리를 병렬 처리할 때 사용한다. 또한 Promise.all 메서드는 프로미스가 담겨 있는 배열 등의 이터러블을 인자로 전달받는다. 모든 프로세스의 처리가 종료될 때까지 기다린 후 모든 처리 결과를 resolve 혹은 reject 한다.

모든 프로세스의 처리가 성공시 각각의 프로미스가 resolve 한 처리 결과를 배열에 담아 resolve 하는 새로운 프로미스를 반환한다. 순서가 보잔된다.

프로미스의 처리가 하나라도 실패하면 가장 먼저 실패한 프로미스가 reject 한 에러를 reject 하는 새로운 프로미스를 즉시 반환한다.

Promise.all([
  new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
  new Promise(resolve => setTimeout(() => resolve(3), 1000))  // 3
]).then(console.log) // [ 1, 2, 3 ]
  .catch(console.log);
Promise.all([
  new Promise((resolve, reject) => setTimeout(() => reject(new Error('Error 1!')), 3000)),
  new Promise((resolve, reject) => setTimeout(() => reject(new Error('Error 2!')), 2000)),
  new Promise((resolve, reject) => setTimeout(() => reject(new Error('Error 3!')), 1000))
]).then(console.log)
  .catch(console.log); // Error: Error 3!

📗 Promise.race

Promise.race 메소드는 Promise.all 메소드와 동일하게 프로미스가 담겨 있는 배열 등의 이터러블을 인자로 받는다. 그리고 Promise.race 메소드는 Promise.all 메소드처럼 모든 프로미스를 병렬 처리하는 것이 아니라 가장 먼저 처리된 프로미스가 resolve한 처리 결과를 resolve하는 새로운 프로미스를 반환한다.

Promise.race([
  new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
  new Promise(resolve => setTimeout(() => resolve(3), 1000))  // 3
]).then(console.log) // 3
  .catch(console.log);

에러 처리는 Promise.all 과 같이 하나라도 실패하면 가장 먼저 실패한 프로미스가 reject 한 결과를 reject 하는 새로운 프로미스를 즉시 반환한다.

📘 Async/Await

async/await 문법은 ES8 에 해당하는 문법으로 Promise 를 더욱 쉽게 사용할 수 있게 한다.

async/await 는 프로미스를 기반으로 동작하며 async/await 를 사용시 프로미스의 then/catch/finally 후속 처리 메서드에 콜백 함수를 전달해서 비동기 처리 결과를 후속 처리할 필요 없이 마치 동기 처리처럼 프로미스를 사용할 수 있다.

async/await 문법 사용시 함수 선언할때 함수 앞에 async 키워드를 붙이고 Promise 앞부분에 await 를 넣어주면 해당 프로미스가 끝날 때까지 기다렸다가 다음 작업을 수행할 수 있다.

일반 함수엔 await 를 사용할 수 없다.

함수 앞에 async 를 붙이면 해당 함수는 항상 프로미스를 반환한다.
await 는 프로미스가 처리될 때까지 함수 실행을 기다리게 만든다. 프로미스가 처리시 그 결과와 함께 재개된다. 프로미스가 처리되기 기다리는 동안 엔진이 다른 스크립트를 실행하거나 이벤트를 처리할 수 있기에 CPU 리소스가 낭비되지 않는다.

async function f() {
	await awaitfunc();
}

async 함수에서 에러 발생시 throw 를 사용하고 에러를 잡아낼 때는 try/catch 문을 사용한다.

async function makeError() {
  await sleep(1000);
  const error = new Error();
  throw error;
}

async function process() {
  try {
    await makeError();
  } catch (e) {
    console.error(e);
  }
}

Promise 를 async await 으로 변환하는 실습 코드

function call(name) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      console.log(name);
      resolve(name); // resolve 콜백함수 파라미터에 name 값 전달
    }, 1000);
  });
}
function back() {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      console.log("back");
      resolve("back"); // resolve 콜백함수 파라미터에 "back" 값 전달
    }, 1000);
  });
}
function hell() {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      resolve("callback hell"); // // resolve 콜백함수 파라미터에 "callback hell" 값 전달
    }, 1000);
  });
}

call("kim")
  .then(function (result) { // call 의 resolve 로 전달된 name 과 result 가 같다.
    console.log(result + "반가워");
    return back();
  })
  .then(function (result) { // back 의 resolve 로 전달된 "back" 과 result 가 같다.
    console.log(result + "을 실행했구나");
    return hell();
  })
  .then(function (result) { // hell 의 resolve 로 전달된 "callback hell" 과 result 가 같다.
    console.log("여기는" + result);
  });

// async await 로 변환시

async function exec() {
  let user = await call("kim"); // kim 은 call 의 parameter, user 는 resolve 의 argument 로 전달된 값
  console.log(user + "반가워");

  let back_result = await back(); // back_result 는 back 의 resolve 에 argument 로 전달된 값
  console.log(back_result + "을 실행했구나"); 

  let hell_result = await hell(); // hell_result 는 hell 의 resolve 에 argument 로 전달된 값
  console.log("여기는" + hell_result);
}

exec();

📔 레퍼런스

docs
mdn - HTTP 상태코드
blog
poiemaweb 웹 프로그래밍
JAVASCRIPT.INFO
벨로퍼트 모던 자바스크립트
course
우아한테크 10분 테코톡 코다의 Process vs Thread
book
모던 자바스크립트 Deep Dive

📓 결론

  • Node.js 는 브라우저 기반의 자바스크립트를 어디서든 실행할 수 있도록 해주는 런타임 환경이다.
  • Node 를 설치하여 npm 을 통해 여러 패키지를 사용할 수 있다.
  • express 는 node.js 기반 웹 애플리케이션 프레임워크이다.
  • 자바스크립트는 비동기 처리를 더 수월하게 하기 위해 Promise 를 도입하였고 가독성 측면의 향상과 함께 Promise 를 async/await 로 변환해서 사용할 수 있다.

앞으로 API 를 다루면서 비동기 처리를 async await 과 try catch 를 매우 자주 사용하게 될 것이다. 그 기반이 되는 내용이라 더 관심있게 조사해봤던 것 같다. 팀 프로젝트가 끝나고 개인 프로젝트를 준비하는 와중에 학습 내용도 정리하려니 정신이 없다.. 🫠

profile
미래의 나를 만들어나가는 한 개발자의 블로그입니다.

0개의 댓글