Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Archives
Today
Total
관리 메뉴

아보카도 Blog

TIL 21일차: Node.js 입문 시작 (비동기 논블로킹, 프로미스, 객체 리터럴, 프로퍼티, 메소드, 클래스, 인스턴스, 생성자, npm, Express.js, Router) 본문

개발일지

TIL 21일차: Node.js 입문 시작 (비동기 논블로킹, 프로미스, 객체 리터럴, 프로퍼티, 메소드, 클래스, 인스턴스, 생성자, npm, Express.js, Router)

수수 아보카도 2022. 12. 13. 03:19

오늘은 내배캠 Node.js의 4주차 첫날이자, 주특기 Node.js 입문 강의가 시작된 날이다.

너무 많은 걸 배워서 이것들을 다 내 것으로 만들 수 있을까 싶지만... 여러번 반복하다보면 나아지겠지.

오늘 시간순서대로 배운 걸 짚어보자면,

 

1. Node.js 의 개념과 특징

Node.js란 Chrom V8 JS 엔진으로 빌드된 JS 런타임으로,

쉽게 말해 자바스크립트가 브라우저없이 실행될 수 있게 도와주는 환경을 말한다.

Node.js의 특징으로 세 가지를 꼽을 수 있다. 1. 논블로킹 2. 싱클스레드 3. 이벤트 루프

논블로킹 인풋/아웃풋으로 함수가 실행되는 중에도 다른 작업을 동시에 진행할 수 있으며,

스레드를 하나만 사용해서 서버 확장에 자유롭다는 강점으로 웹서버에 특화했다.

이벤트루프에 대한 설명은 훈남 오빠가 설명해주는 것을 참고...

 

2. 동기 Sync 와 비동기 Async

동기와 달리 비동기는 실행된 코드의 순서와 관계없이 결과가 나오는 것을 말한다.

JS와 연관해서 말하자면, JS는 비동기이자 논블로킹 모델을 채택하여

현재 실행중인 코드의 실행이 끝나지 않아도 다음 코드를 호출한다.

즉, 동기적 명령이 아닌 모든 함수는 비동기적으로 실행된다.

우리는 setTimeout이라는 함수를 예로 들어 비동기 논블로킹 JS를 살펴보았다.

 

동기, 비동기, 블로킹, 논블로킹에 관해 잘 정리되어있는 글

 

블로킹과 논블로킹, 동기와 비동기

블로킹과 논블로킹의 차이를 말하기 앞서 제어권이라는 개념을 아는 게 중요하다. 제어권을 가진 함수는 코드 실행 중에 전체적인 흐름을 제어할 수 있다고 말할 수 있다.함수 A에서 함수 B가 호

velog.io

 

3. 프로미스 Promise

프로미스는 JS에서 비동기처리를 동기로 처리할 수 있게 돕는 빌트인(미리 내부적으로 정의됨) 객체유형이다.

이때 프로미스는 걸그룹 이름을 떠올리게 하는데... 의미는 언제 진행할지를 약속해놓는 것으로,

그 언제는 바로 비동기 명령의 실행이 완료된 이후라 할 수 있다.

프로미스가 콜백보다 선호되는 이유로는, 콜백으로는 매번 비동기 실행해야지 그 값을 사용할 수 있는 반면

프로미스는 .then 메소드로 저장된 값을 원할때 사용할 수 있기 때문이다.

 

executor는 프로미스의 생성자 인터페이스로, 인자로 resolve, reject가 주어진다.

new Promise(executor)
new Promise ((resolve, reject) => {})

 

프로미스는 3가지 상태를 지닌다. 대기(Pending), 이행(Fulfilled), 그리고 거부(Rejected)다.

프로미스가 만들어질 때 executor가 실행되며,

executor에서 resolve 함수가 호출되기 전까지 .then(...) 안의 ... 값을 실행하지 않는다.

executor가 실행되어 resolve된 프로미스를 fulfilled promise라고 한다.

 

Promise.then은 프로미스 안에서 resolve가 실행된 경우 then 메소드에 작성된 함수를 실행하는 것이다.

Promise.catch는 프로미스 안에서 에러가 throw되거나 reject가 실행되면 catch 메소드에 작성된 함수를 실행하는 것이다.

 

4. 비동기 함수에서만 실행되는 await 연산자

비동기 함수는 결과값이 항상 프로미스 객체로 resolve되며,

오직 비동기 함수안에서만 await 연산자가 사용된다.

await를 통해 프로미스가 fulfill 또는 reject 될때까지 함수의 실행을 중단하고 기다릴 수 있다.

// 비동기함수
function 함수이름() {
	return Promise.resolve('값');
}

// 위와 아래의 함수는 같은 동작을 보여준다.

async function 함수이름2() {
	return '값';
}

함수이름();
// Print: Promise { '값' }

함수이름2();
// Print: Promise { '값' }
// await
async function 함수이름() {
	const result = await 'Test!';
	console.log(result);
}

함수이름();
// Print: 'Test!';

 

4. JS function의 특별한 성질

프로그래밍 언어는 표현 expression과 문 statement로 구분할 수 있는데,

함수는 복합문인 동시에 어떤 변수에 할당할 수 있다는 점에서 표현의 특징을 띈다.

예를 들면 if나 for은 인자로 또 다른 함수를 넣을 수 없지만 function은 가능하다.

let functionStatement = function ( ) { } 이런 식으로.

 

5. 객체 리터럴 Object literal, 프로퍼티 Property, 메소드 Method

객체는 0개 이상의 property로 구성된 집합이고, property는 key와 value로 구성된다.

객체리터럴은 객체를 생성하기 위한 표기법으로, 일반적인 숫자, 문자열을 만드는 것과 유사하게 객체를 생성할 수 있다.

메소드는 프로퍼티를 조작할 수 있는 동작으로, 객체의 프로퍼티 값이 함수로 구성되어 있을 때를 말한다.

// 객체리터럴
let objectLiteral = {
    key: 'Value',
    helloWorld: function () {
        return "Hello world";
    }
};

//프로퍼티
const human = {
  // 프로퍼티 키: 'name', 프로퍼티 값: '이용우' 
  name: '이용우',
  // 프로퍼티 키: 'human age', 프로퍼티 값: 28 
  'human age': 28
}

//메소드
let objectLiteral = {
    key: 'Value', // 프로퍼티
    helloWorld: function () { // 메서드
        return "Hello world";
    }
};

console.log(objectLiteral.helloWorld()); // Hello world

 

6. Error Handling: try, catch, throw, finally

예외처리를 try와 catch로 하며, 프로그램을 멈추지 않고 에러를 기록할 수 있다.

const users = ["Lee", "Kim", "Park", 2];

try {
  for (const user of users) {
    console.log(user.toUpperCase());
  }
} catch (err) {
  console.error(`Error: ${err.message}`);
}

// LEE
// KIM
// PARK
// Error: user.toUpperCase is not a function

 

throw: 고의로 에러 발생 ex. 은행 출금. 실행중인 함수 즉시 멈춤.

function withdraw(amount, account) {
  if (amount > account.balance)
    throw new Error("잔고가 부족합니다.");
  account.balance -= amount;
	console.log(`현재 잔고가 ${account.balance}남았습니다.`); // 출력되지 않음
}

const account = { balance: 1000 };
withdraw(2000, account);

// Error: 잔고가 부족합니다.

 

finally: 자원 삭제함.

function errorException(isThrow) {
  try {
    console.log('자원을 할당하였습니다.');
    if (isThrow) throw new Error();
  } catch (error) {
    console.log('에러가 발생했습니다.');
  } finally {
    console.log('자원을 제거하였습니다.');
  }
}

errorException(false);
// 자원을 할당하였습니다.
// 자원을 제거하였습니다.
errorException(true);
// 자원을 할당하였습니다.
// 에러가 발생했습니다.
// 자원을 제거하였습니다.

 

7. 클래스 Class 와 인스턴스 Instance, 생성자 Constructor

클래스로 미리 정의해놓으면 필요할 때마다 동일한 틀 가진 객체를 만들 수 있다. 이때 이 객체들을 인스턴스라고 한다.

class User { 
}

const user = new User();
user.name = "이용우";
user.age = 28;
user.tech = "Node.js";

console.log(user.name); // 이용우
console.log(user.age); // 28
console.log(user.tech); // Node.js

 

생성자는 클래스 내부에서 constructor()로 정의한 메소드로,

미리 정의한 클래스를 기반으로 인스턴스를 생성할 때 JS 내부에서 호출되는 메소드를 말한다.

class User {
  constructor(name, age, tech) { // User 클래스의 생성자
    this.name = name;
    this.age = age;
    this.tech = tech;
  }
}

const user = new User("이용우", 28, "Node.js"); // user 인스턴스 생성

console.log(user.name); // 이용우
console.log(user.age); // 28
console.log(user.tech); // Node.js

이때 this.는 클래스를 사용해 만들어진 객체 자신이고, 그 뒤에 나오는 name이나 age 등은 property이다.

 

클래스의 인스턴스는 선언한 클래스이 기능을 모두 상속한다.

부모 클래스는 메소드, 내부 변수 등의 정보를 자식 클래스에게 할당할 수 있다.

class User { // User 부모 클래스
  constructor(name, age, tech) { // 부모 클래스 생성자
    this.name = name;
    this.age = age;
    this.tech = tech;
  }
  getTech(){ return this.tech; } // 부모 클래스 getTech 메서드
}

class Employee extends User{ // Employee 자식 클래스
  constructor(name, age, tech) { // 자식 클래스 생성자
    super(name, age, tech);
  }
}

const employee = new Employee("이용우", "28", "Node.js");
console.log(employee.name); // 이용우
console.log(employee.age); // 28
console.log(employee.getTech()); // 부모 클래스의 getTech 메서드 호출: Node.js

 

8. HTTP, Package Manager (npm), Express.js, API Client (Thunder Client) , Router

HTTP는 서버와 클라이언트끼리 의사소통 가능하게 만들어주는 통신 규약이다.

http의 역사는 이곳을 참조

 

그림으로 쉽게 보는 HTTP 변천사

웹과 함께 시작된 0.9부터 따끈하게 등장한 3.0까지 | 시리즈 초기에 우린 인터넷 상에서 컴퓨터와 컴퓨터가 서로 데이터를 주고받기 위한 규약인 HTTP에 대해 알아봤습니다. 그리고 다른 네트워

brunch.co.kr

npm (node package manager)은 파이썬의 pip과 비슷하게 Node,js에서 필요한 패키지를 설치, 관리, 제거하게 도와준다.

package.json, package-lock,json

배운 명령어는 다음과 같다.

npm init

npm install ...

npm install -D

npm install -y

 

Express.js는 Node.js로 서버를 빠르고 간편하게 만들 수 있게 도와주는 웹 프레임워크다.

실습해서 한 활동은 다음과 같다.

VS Code에서 app.js 생성 -> 터미널에 npm init -y 입력 -> package.json 파일 생성됨.

Express.js 설치: npm install express -> 터미널에서 spa_mall의 경로에서 node app.js 실행 -> "3000 포트로 서버 열림!" ->

브라우저로 localhost:3000 들어가면 GET Method로 작성된 코드를 통해 Hello World 확인할 수 있다.

 

또한 실습에서 API Client로 Thunder Client를 설치해서 이용했다. 사용방법은 다음과 같다.

Thunder Client 아이콘 클릭 -> New Request -> GET, localhost:3000/ 입력 후 send.

덧붙여 Collections는 특별한 프로젝트마다 API 목록을 정리해서 사용하는 곳이고,

Env는 여러번 사용되는 값들을 환경변수로 설정할 때 사용하는 곳이다.

 

Router는 클라이언트의 요청을 쉽게 처리하게 도와주는 Express.js의 기본기능이다.

router. METHOD (PATH, HANDLER)

method에는 get, post등을 써주고, path는 실제 API 주소, handler에는 라우트가 일치할 때 실행되는 함수를 적는다.

실습에서는 goods.js와 app.js 각각에 다음과 같은 코드를 적고 localhost:3000에서 url을 늘려가며 확인했다.

// routes/goods.js

const express = require('express');
const router = express.Router();

// localhost:3000/api/ GET
router.get("/", (req, res) => {
  res.send("default url for goods.js GET Method");
});

// localhost:3000/api/about GET
router.get("/about", (req, res) => {
  res.send("goods.js about PATH");
});

module.exports = router;
// app.js

const goodsRouter = require("./routes/goods");

// localhost:3000/api -> goodsRouter
app.use("/api", [goodsRouter]);

 

 

오늘 참 많은 걸 배웠는데, 그 중 가장 인상깊었던 건 node.js를 깔고 터미널처럼 이용하는 것과,

함수의 메소드를 사용하는 것이 익숙하지 않은데, router를 이용하는 방식도 메소드 사용방식과 비슷하다는 걸 알았다.

 

프로미스, 동기와 비동기, 블로킹과 논블로킹, 객체리터럴은 처음 배우는 개념이라 새롭고 재미있었다.

코드스니펫을 단순히 복사해서 붙여넣고, 강의 설명 들으며 주석을 써넣는 것이 전부였던 오늘...

과연 이 길고 복잡한 코드를 나 혼자 쓸 수 있을까? 한 주 동안 열심히 하다보면 그래도 오늘 배운 건 소화할 수 있겠지...