티스토리 뷰

항해/주특기 1주차

[node js] 1주차 - 3

타올이 2022. 1. 22. 20:55
반응형

Hoisting(끌어올려진다.)

자바스크립트가 코드를 읽어올 때 각 Scope(구역)에 들어있는 var, function과 같은 키워드로 선언된 코드는 아래와 같이 동작합니다.

  • 실제 코드
더보기

console.log(name); // Print: undefined

var name = '강승현';

  • 위 코드를 실행했을때 선언되지 않은 변수를 미리 참조했기 때문에 첫번째 줄에서 참조 에러가 발생해야 하는데 실제로는 발생하지 않습니다. 어떻게 된것일까요?
  • 바로 Hoisting 이라고 불리우는 동작 때문인데요, var, function 키워드로 선언하면 아래와 같이 동작한다고 이해하시면 됩니다.
  • Hoisting 적용 예시

(실제로 이렇게 변환되는것은 아니며, 대략 아래 코드처럼 동작한다는 의미입니다.)

더보기

var name;

 

0console.log(name); // Print: undefined

name = '강승현';

    • 만약 아직 이해가 어렵다면 var 키워드를 사용하면 호이스팅이 일어나서 안좋다. 라는것만 기억하셔도 충분합니다. TDZ의 보호를 받고 있지 않은 키워드인 var를 사용하는것은 변수의 값이 언제 바뀔지도 모르며 스파게티 코드를 만드는 주범이 될 수 있으므로 절대로 지양해야 합니다 😉

동기(Sync)와 비동기(Async)에 대한 개념

    • 일반적으로 "동기로 실행된다" 라고 함은, 먼저 실행된 코드의 결과가 나올때까지 대기하는것을 말합니다.
      • 놀이기구를 생각하면 쉽습니다.
      • 정원이 30명인 놀이기구가 있다고 가정합니다. 놀이기구를 한번 태우는데 약 5분이 걸린다고 가정하면 놀이기구를 막 태우기 시작한 시점에서는 대기자 모두 5분이 지나 이미 놀이기구에 탑승했던 사람들이 다 내리기 전까지는 탑승을 할 수 없습니다. 이것은 놀이기구 탑승/하차가 동기적으로 관리된다고 볼 수 있습니다.
    • 일반적으로 "비동기로 실행된다" 라고 함은, 실행된 순서와 관계 없이 결과가 나오는것을 말합니다.
      • 정원이 최대 30명인 맛집이 있다고 가정합니다. 입장 순서는 선착순이고 퇴장 순서는 다 먹은 사람이 바로 나올 수 있습니다. 다 먹은 사람이 나오면 나온 사람 수 만큼 다시 입장 할 수 있습니다. 사람마다 먹는 시간은 모두 다릅니다. 이것은 입/퇴장이 비동기적으로 처리된다고 볼 수 있습니다.

Blocking Model & Non-Blocking Model(제어권차이)

    • Blocking Model이란, 코드의 실행이 끝나기 전까지 실행 제어권을 다른곳에 넘기지 않아 다른 작업을 하지 못하고 대기하는 것을 말합니다.
    • Non-blocking Model이란, 코드의 실행이 끝나지 않아도 실행 제어권을 다른곳에 넘겨 다음 코드가 실행될 수 있는것을 말합니다.
    • 동기, 비동기와 뭐가 다른걸까?
      • 제어권을 넘기면(Non-blocking) 다른 코드도 실행될 수 있으므로 비동기 처리가 가능하지만 제어권을 넘기지 않으면(Blocking) 비동기 처리가 가능한 환경이어도 비동기 처리가 불가능합니다.
    • 자바스크립트는 Async + Non-blocking Model을 채용하여 현재 실행중인 코드의 실행이 끝나지 않아도 다음 코드를 호출합니다.
    • 결론적으로 자바스크립트는 Non-blocking model을 가지며 각 명령이 순서대로 실행될 수 있게 구현되어 있지만, Non-blocking model에 의해 명령이 아닌 모든 함수는 비동기적으로 실행됩니다.
    • 예시 (setTimeout은 특정 시간 뒤에 함수를 실행해주는 역할입니다.)
더보기

function first() {

console.log('First');

}

 

setTimeout(first, 1000); // 1000ms(1초) 뒤에 first 함수를 실행해준다.

 

console.log('Middle');

console.log('Last');

 

// Print: Middle

// Last

// First

    • 만약 자바스크립트가 Non-blocking model이 아니었다면 위 코드는 1초를 기다려서 first 함수를 먼저 호출하여 'First'를 출력한 뒤, 'Middle', 'Last' 순서로 출력해야 합니다.

Promise

    • 자바스크립트에서 비동기 처리를 동기로 처리할 수 있게 돕는 객체 유형입니다.
    • 이 객체를 이용하면 여러분은 Non-blocking model을 가진 자바스크립트에서도 비동기 처리를 아주 손쉽게 할 수 있습니다.
    • Promise 생성자 인터페이스
    • executor에는 함수만 올 수 있으며 인자로 resolve, reject가 주입됩니다.
더보기

new Promise(executor);

 

// 예제

new Promise((resolve, reject) => {

// 명령문

});

    • 프로미스의 상태
    • 프로미스는 반드시 3가지 상태를 지니며, 대기(Pending) 상태가 아니라면 Promise의 연산이 이미 끝난 상태로 볼 수 있습니다. 
      • 대기(Pending): 이행하거나 거부되지 않은 초기 상태.
      • 이행(Fulfilled): 연산이 성공적으로 완료됨.
      • 거부(Rejected): 연산이 실패함.

프로미스가 만들어 질 때 executor가 실행되며, executor에서 resolve 함수가 호출되기 전까지 firstPromise.then(...) 안에 있는 코드를 실행하지 않습니다. 

이렇게 executor 가 실행되어 resovle된 프로미스를 Fulfilled Promise라고도 부릅니다.

더보기

const timerPromise = new Promise((resolve, reject) => { // 이곳에 정의된 함수가 executor

setTimeout(() => {

console.log('First');

resolve();

}, 1000);

});

 

// 이 시점에서 timerPromise는 Fulfilled Promise라고 부를 수 있다.

 

timerPromise.then(() => {

console.log('Middle');

console.log('Last');

});

 

// Print: First

// Middle

// Last

Promise.catch

프로미스 안에서 에러가 throw 되거나 reject되면 catch 메서드에 작성한 함수가 실행됩니다.

const errorPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
	  console.log('First');
		reject('Error!!'); // 직접 reject를 실행하면 프로미스에서 에러가 발생한것으로 간주됩니다.
	}, 1000);
});

errorPromise.then(() => {
	console.log('Middle');
	console.log('Last');
}).catch((error) => {
	console.log('에러 발생!', error);
});

// Print: '에러 발생! Error!!'

 

    • Promise.then 더 알아보기

1. Promise에서 resolve 된 값 이용하는 방법

더보기

const firstPromise = new Promise((resolve, reject) => {

resolve('First');

});

 

firstPromise.then((value) => {

console.log(value);

});

 

// Print: 'First'

2. Promise.resolve 함수 이용

프로미스가 값을 반환하는 경우 반환되는 값은 항상 프로미스로 감싸져 있습니다!

const firstPromise = Promise.resolve('First');

firstPromise.then((value) => {
	console.log(value);
});

// Print: 'First'

3. Promise.then으로 함수형 프로그래밍 체험하기

이것이 가능한 이유는 console.log라는 함수 뒤에 괄호를 사용해서 함수를 호출하지 않고, 함수를 그대로 then에 넘겼기 때문입니다.

const firstPromise = Promise.resolve('First');

firstPromise.then(console.log);

// Print: 'First'

4. Promise.then으로 함수형 프로그래밍 체험하기 2

더보기

const countPromise = Promise.resolve(0);

 

function increment(value) {

return value + 1;

}

 

const resultPromise = countPromise.then(increment).then(increment).then(increment);

resultPromise.then(console.log);

 

// Print: 3

 

Promise.race() - JavaScript | MDN

Promise.race() 메소드는 Promise 객체를 반환합니다. 이 프로미스 객체는 iterable 안에 있는 프로미스 중에 가장 먼저 완료된 것의 결과값으로 그대로 이행하거나 거부합니다.

developer.mozilla.org

비동기 함수 (Async Function)

    • 특징

비동기 함수는 일반 함수나 화살표 함수와 아주 비슷하지만 딱 두가지만 다릅니다. 

  1. 비동기 함수의 결과 값은 항상 Promise 객체로 resolve된다.
  2. 비동기 함수 안에서만 await 연산자를 사용할 수 있다. (바로 아래에서 배웁니다!)

이 두가지 특징을 제외하면 기존처럼 일반 함수나, 화살표 함수처럼 사용할 수 있습니다. 아래처럼요. 아래 세가지 함수 모두 결과 값은 Promise로 받습니다.

// 비동기 + 일반 함수

더보기

async function 함수이름() {

// 명령문

}

 

// 비동기 + 익명 함수

async function() {

// 명령문

}

 

// 비동기 + 화살표 함수

async () => {

// 명령문

}

    • 이러한 특징은 마치 아래처럼 작성하는것과 굉장히 비슷합니다.
더보기

function 함수이름() {

return Promise.resolve('값');

}

 

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

 

async function 함수이름2() {

return '값';

}

 

함수이름();

// Print: Promise { '값' }

 

함수이름2();

// Print: Promise { '값' }

    • 그럼 비동기 함수는 왜 쓸까요?

아래에서 배울 await 연산자를 비동기 함수 안에서만 사용할 수 있는데요, 이를 활용하면 문법이 훨씬 간결해질 수 있습니다.

덕분에 비동기 함수는 여러분이 비동기 프로그래밍을 하게 되면 즐겨 사용하는 함수 유형중 하나가 될 것 입니다. 😇

  • new Promise(executor) 코드로 프로미스를 직접 생성하면 executor가 바로 실행되는것과 달리, 비동기 함수는 함수가 실행되기 전까지 프로미스를 생성하지 않습니다.
더보기

 🔥 자바스크립트가 실제로 비동기처럼 실행될 수 있는 원리는 상당히 복잡하며 설명이 너무x10 길어지기 때문에 생략합니다. 궁금하시다면 Callback, Event loop, Call stack에 대해 알아보시는것이 좋습니다.

await 연산자

    • await 연산자를 사용하면 Promise가 fulfill되거나 rejected될 때 까지 함수의 실행을 중단하고 기다릴 수 있습니다. Promise의 연산이 끝나면 함수에서 반환한 값을 얻을 수 있습니다.
    • await 연산자는 async 함수 안에서만 사용할 수 있습니다.
    • 인터페이스
더보기

const result = await 값;

    • "값" 에는 Promise가 아닌 다른 값도 들어갈 수 있습니다. 아래처럼요! Promise가 아니라면 기다리지 않고 해당 값 자체를 그대로 반환합니다.
더보기

async function 함수이름() {

const result = await 'Test!';

console.log(result);

}

 

함수이름();

// Print: 'Test!';

모든 비동기 함수는 promise를 반환한다.

await 함수는 뒤에 값이 promise인지 애매할때 넣어주면 된다.

 

async 함수의 반환 값은 무엇일까요?

🚀 정답

async 함수의 결과값은 항상 Promise 객체로 resolve 되기 때문에 값은 동일합니다.

async 함수 안에서 Promise 객체를 반환하면 어떤 결과가 나올까요?

🚀 정답

async 함수 안 어딘가에서 에러가 발생하지 않았다면 async 함수의 반환 값은 무조건 Promise 객체입니다!

async function getMyName() {
  return Promise.resolve('강승현');
}

const result = getMyName();

result.then((myName) => {
  console.log(myName);
});

강승현이 리턴됨

반응형

'항해 > 주특기 1주차' 카테고리의 다른 글

[node js] 2주차 - 2  (0) 2022.01.23
[node js] 2주차 - 1  (0) 2022.01.22
[node js] 1주차 - 마음가짐  (0) 2022.01.22
[node js] 1주차 - 2  (0) 2022.01.22
[node js] 1주차 - 1  (0) 2022.01.21
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/12   »
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
링크
글 보관함