저장을 습관화

230612 TIL 본문

공부/TIL

230612 TIL

ctrs 2023. 6. 12. 18:20

- REPL
입력받은 코드를 읽어(Read)들여 메모리에 저장하고,
평가(Evaluate)된 값을 출력(Print)한다.
특정 신호를 입력받기 전까지 위의 과정을 반복(Loop)한다.

쉽게 말해 입력한 코드의 결과값을 즉시 확인할수 있기 때문에 간단한 문법 등의 테스트에 적합한 환경이라는 의미이다.


Node.js가 이 REPL환경을 제공하고 있다.
상식으로 알고 있자


 - 동기(sync)와 비동기(async)
'동기로 실행된다' = 먼저 실행된 코드의 결과가 나올때까지 대기한다.

'비동기로 실핸된다' = 실행된 순서와 관계없이 결과가 나온다.

 


- Blocking Model과 Non-Blocking Model
Blocking Model은 코드의 실행이 끝나기 전까지 실행 제어권을 다른 곳에 넘기지 않아 다른 작업을 하지 못하고 대기한다.
자바, C 등이 이에 해당된다.

Non-Blocking Model은 코드의 실행이 끝나지 않아도 실행 제어권을 다른 곳에 넘겨 다음 코드가 실행된다.
자바스크립트 등이 이에 해당된다.

제어권을 넘기면(Non-Blocking) 다른 코드도 실행될 수 있으므로 비동기 처리가 가능하지만, 
제어권을 넘기지 않으면(Blocking) 비동기 처리가 가능한 환경이어도 비동기 처리가 불가능하다는 차이가 있다.

자바스크립트는 Async + Non-Blocking Model을 채용하여 현재 실행중인 코드의 실행이 끝나지 않아도 다음 코드를 호출한다.
다시말해 각 명령들이 순서대로 실행될 수 있게 구현되어 있지만, Non-blocking model에 의해 동기적 명령이 아닌 모든 함수는 비동기적으로 실행된다.


예시

async function main() {
  function first() {
    console.log("set time out이 실행되었습니다.");
  }
  console.log("코드가 실행되었습니다.");
  setTimeout(first, 1000); // 1초 뒤에 first 함수를 실행하라
  console.log("코드가 종료되었습니다.");

  // 일반적인 동기적(sync) blocking model의 경우
  // 코드를 위에서부터 읽어 내려오기 때문에
  // 1. '코드가 실행되었습니다.'
  // 2. 1초 대기 후, 'set time out이 실행되었습니다.'
  // 3. '코드가 종료되었습니다.'가 출력되나

  // Async + Non-blocking model인 자바스크립트는
  // 1. '코드가 실행되었습니다.'
  // 2. '코드가 종료되었습니다.'
  // 1초 대기 후, 'set time out이 실행되었습니다.'가 출력된다.
}

main();

 

[참고] 이 내용에 대해서 잘 정리한 블로그를 찾았다. 읽어보자

https://etloveguitar.tistory.com/140

 

blocking I/O, non-blocking I/O에 대하여 (sync, async와의 차이)

Blocking I/O / Non Blocking I/O, synchronous / asynchronous 는 개발을 하다보면 자주 접하게 되는 용어다. 특히 파이썬, NodeJS와 같이 싱글스레드로 동작하는 언어에서는 성능을 위해 필수적으로 알아두어야

etloveguitar.tistory.com

 

 

- Promise

자바스크립트에서 비동기 처리(Async)를 동기(sync)로 처리할 수 있게 돕는 객체 유형이다.

콜백지옥을 처리하는 데에도 도움이 된다.

 

Promise 생성자 인터페이스 executor에는 함수만 올 수 있으며 인자로 resolve, reject가 주입된다.

Promise가 정상적으로 완료되었을때는 resolve가, 에러가 발생했을때는 reject가 실행된다.

 

executor는 Promise의 실행 함수이며 Promise가 만들어질 때 자동으로 실행된다.

Promise가 연산을 언제 종료하는지에 상관없이 resolve, reject 중 하나를 무조건 호출해야한다.

new Promise(executor);

// 예제
new Promise((resolve, reject) => {
	//명령문
});

 

Promise는 반드시 3가지 상태를 지니며, 대기(Pending) 상태가 아니라면 Promise의 연산이 끝난 상태로 볼 수 있다.

대기(Pending)

이행하거나 거부되지 않는 초기 상태, Promise 내부에서 코드가 실행되고 연산하고 있을때

 

이행(Fulfilled)

연산이 성공적으로 완료됨, 연산이 모두 끝나고 성공적으로 반환되었을때

 

거부(Rejected)

연산이 실패함, 연산 도중 에러가 발생하거나, 잘못된 값으로 에러가 발생 되어야할 때

 

 

- Promise.then

Promise 안에서 resolve가 실행 된 경우 then 메소드에 작성된 함수가 실행된다.

예시

async function main() {
  const resolvePromise = new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("First");
      resolve("Resolve!"); // "Resolve!"를 전달인자로서 .then의 내용을 불러온다. 
    }, 1000);
  });

  resolvePromise.then((data) => {
    // data에 resolve의 내용 "Resolve!"가 들어간다.
    console.log("Middle");
    console.log("Last");
    console.log(data);
  });
}
main();

// 실행 결과
// First
// Middle
// Last
// Resolve!

 

- Promise.catch

Promise 안에서 에러가 발생하거나 reject가 실행되면 catch 메소드에 작성한 함수가 실행된다.

async function main() {
  const errorPromise = new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("First");
      reject("Error!!"); // 직접 reject를 실행하면 프로미스에서 에러가 발생한것으로 간주됩니다.
      // "Error!!"를 전달인자로서 .catch의 내용을 불러온다.
    }, 1000);
  });

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

// 실행 결과
// First
// 에러 발생! Error!!

 

- 응용

const firstPromise = new Promise((resolve, reject) => {
  resolve('First');
});

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

// 실행 결과
First

/////////////////////////////////////////////////////////////////

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

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

// 실행 결과
First

/////////////////////////////////////////////////////////////////

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

firstPromise.then(console.log);

// 실행 결과
First

/////////////////////////////////////////////////////////////////

 

- 비동기 함수(Async Function)

일반적인 함수나 화살표 함수와 비슷하지만 두가지 차이가 있다.

1) 비동기 함수의 결과 값은 항상 Promise 객체로 resolve 된다.

2) 비동기 함수 안에서만 await 연산자를 사용할 수 있다.

// 비동기 + 일반 함수
async function 함수이름() {
	// 명령문
}

// 비동기 + 익명 함수
async function() {
	// 명령문
}

// 비동기 + 화살표 함수
async () => {
	// 명령문
}

 

- 응용

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

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

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

함수이름();
// 실행결과: Promise { '값' }

함수이름2();
// 실행결과: Promise { '값' }

 

- await 

1) Promise가 fulfill 상태가 되거나 reject될 때까지 함수의 실행을 중단하고 기다린다.

2) Promise의 연산이 끝나면 함수에서 반환된 값을 얻을 수 있다.

3) await 연산자는 async 함수 안에서만 사용할 수 있다.

function setTimeoutFunc(time) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(time, "에 해당하는 시간이 지났습니다.");
      resolve();
    }, time);
  });
}

async function main() {
  console.log("시작되었습니다.");
  await setTimeoutFunc(1000);
  console.log("종료되었습니다.");
}

main();

// 실행 결과
// 시작되었습니다.
// 1000 에 해당하는 시간이 지났습니다.
// 종료되었습니다.

 

'공부 > TIL' 카테고리의 다른 글

230621 TIL  (0) 2023.06.21
230618 TIL  (0) 2023.06.18
230608 TIL - parentNode  (0) 2023.06.08
230608 TIL - 로컬 스토리지와 JSON과 unexpected token  (0) 2023.06.08
230607 TIL  (0) 2023.06.08