JavaScript

동기(sync)와 비동기(async)

이히힣 2022. 12. 26. 04:40

데이터를 받아오는 방식에는 동기식 처리 방법과 비동기식 처리 방법이 존재한다.

 

adrianmejia

 

 

동기(synchronous)

동기는 데이터의 요청과 결과가 한 자리에서 동시에 일어나는것을 말한다.

사용자가 데이터를 서버에게 요청한다면 그 서버가 데이터 요청에 따른 응답을 사용자에게 다시 리턴해주기 전까지 사용자는 다른 활동을 할 수 없으며 기다려야만한다. 순서에 맞춰 진행되는 장점이 있지만,  여러 가지 요청을 동시에 처리할 수 없다.

 

장점: 순서에 맞춰 진행, 설계가 매우 간단하고 직관적이다. 

단점: 여러 가지 요청을 동시에 처리할 수 없음

 

 

비동기(Asynchronous)

비동기는 데이터의 요청과 결과가 동시에 일어나지 않는다는 것을 의미한다.

사용자가 서버에게 데이터를 요청한 후 요청에 따른 응답을 계속 기다리지 않아도 다른 외부 활동을 수행할 수 있고 서버에게 다른 요청사항을 보낼 수 있다.

 

장점 : 요청에 따른 결과가 반환되는 시간 동안 다른 작업을 수행할 수 있다.

단점 : 동기식보다 설계가 복잡하다. 언제 코드가 실행될지 예측할 수 없다.

 

 

 

 

 

자바스크립트는?

자바스크립트는 호이스팅(함수 선언들이 자동적으로 제일 먼저 선언) 된 순서 부터 동기적으로 실행된다.

 

async & await

promise를 깔끔하게 사용하는 방법.

 

1. async

function fetchUser() {
  return new Promise((resolve, reject) => {
  // do network reqeust in 10 secs...
    resolve('hello');
  });
}

const user = fetchUser();
user.then(console.log);
console.log(user);

⬇️

async function fetchUser() {
  // do network reqeust in 10 secs...
  return 'hello';
}

const user = fetchUser();
user.then(console.log);
console.log(user);

 

Promise를 더 간단하게 사용하기 위해서는 async 키워드를 함수 앞에 붙여주면 코드 블록이 자동으로 Promise로 바뀐다.

 

 

 

2. await

 

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function sayHello() {
  await delay(1000); 
  return 'Hello';
}

async function isName() {
  await delay(1000);
  return 'Jake';
}

// Promise. async 사용 전
// funtion isName() {
  // return delay(1000)
  // .then(() => 'Jake');
// }

await을 사용하면 1초가 끝날때까지 기다려 준다. 따라서 1초 후  Hello, 또 1초 후 Jake가 출력된다.

 

 

 

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function sayHello() {
  await delay(1000);
  return 'Hello';
}

async function isName() {
  await delay(1000);
  return 'Jake';
}

function sayHelloJake() {
  return sayHello().then(hello => {
    return isName().then(name => `${Hello} + ${Jake}`);
  });
}

sayHelloJake().then(console.log)

Hello와 Jake를 동시에 출력하고 싶을 때 중첩하여 사용한다.

하지만 Promise도 너무 중첩적으로 사용하면 콜백지옥과 비슷한 문제점 발생한다.

 

⬇️

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function sayHello() {
  await delay(1000);
  return 'Hello';
}

async function isName() {
  await delay(1000);
  return 'Jake';
}

async function sayHelloJake() {
  const hello = await sayHello();
  const name = await isName();
  return `${Hello} + ${Jake}`;
}

sayHelloJake().then(console.log)

async await를 사용하여 깔끔하게 사용 가능하다.

 

 

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function sayHello() {
  await delay(1000);
  throw 'error';
  return 'Hello';
}

async function isName() {
  await delay(1000);
  return 'Jake';
}

async function sayHelloJake() {
  try{
    const hello = await sayHello();
    const name = await isName();
  } catch() {
    console.log('error')
  };
  
  return `${Hello} + ${Jake}`;
}

sayHelloJake().then(console.log)

만약 에러가 발생했다면 try catch를 이용해서 에러 처리를 할 수 있다.

 

 

 

문제점: Hello를 받는데 1초, Jake를 받는데 1초가 걸린다.

2초는 문제점을 못 느낄 수도 있지만 만약 한 데이터를 받아올 때까지 10초가 걸린다고 가정한다면 20초가 걸리는 시간동안

사용자는 빈 화면만 보게 된다. 따라서 이 때 병렬적 구조를 통해 동시에  데이터를 받아오면 시간을 더 단축할 수 있다.

 

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function sayHello() {
  await delay(1000);
  throw 'error';
  return 'Hello';
}

async function isName() {
  await delay(1000);
  return 'Jake';
}

// 1번
async function sayHelloJake() {
  const helloPromise = sayHello();
  const namePromise = isName();
  const hello = await helloPromise();
  const name = await namePromise();
  return `${Hello} + ${Jake}`;
}

// 2번⭐️
funtion sayHelloJake() {
  return Promise.all([sayHello(), isName()])
  .then(name => name.join(' + ')
  );
}

sayHelloJake().then(console.log)

두 가지의 데이터를 받아 올 때 서로 연관되지 않아 동시에 불러올 수 있는 Promise는 1번처럼 사용하지 않는다.

 

 

 

유용한 API

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function sayHello() {
  await delay(2000);
  return 'Hello';
}

async function isName() {
  await delay(1000);
  return 'Jake';
}

function pickName() {
  return Promise.race([sayHello(), isName()]); // 먼저 출력 되는 값만 출력
}

sayHelloJake().then(console.log)

   ⭐️⭐️⭐️중요⭐️⭐️⭐️

  • 동기와 비동기는 어떤 작업 혹은 그와 연관된 작업을 처리하고자 하는 목적의 차이이다.
  • 동기는 추구하는 행위 와 목적이 동시에 이루어지고 여러 가지 요청을 동시에 처리할 수 없다.
  • 비동기는 추구하는 행위 와 목적이 다를 수도 있고, 요청에 따른 결과가 반환되는 시간 동안 다른 작업을 수행할 수 있다.