[4차 세미나] Part 2 : 비동기 프로그래밍

_dodo_hee·2021년 7월 17일
0

CS

목록 보기
4/6
post-thumbnail

비동기 프로그래밍

브라우저에서 비동기 프로그래밍은 주로 통신과 같이 오래 걸리는 작업들을
브라우저에 위임할 때 이루어진다.

비동기 프로그래밍 방식은 프로그램의 성능과 응답성을 높이는 데 도움을 주지만,
코드가 실제로 실행되는 순서가 뒤죽박죽이라 코드의 가독성을 해치고 디버깅을 어렵게 만든다.

하지만! 단점을 보완하기 위해 만든 프로그래밍 기법이 생겼다.

비동기 프로그래밍의 필요성

웹페이지가 발전하면서 웹과 모바일에서는 사용자 인터렉션이 많아지게 되었다.
다양한 이벤트요소들이 생겨나고
여러 통신들이 일어나야하고,
다양한 애니메이션도 나타나게 해야했다.

하지만 이러한 것들로 인해 사용자는 자연스럽게 대기시간을 겪게 된다.
대기시간이 잦고 길어질수록 사용자들은 불편을 겪을 것이고,
결국엔 웹에서 이탈하게 되고 웹 이용률 하락까지 불러온다.

프론트엔드 영역에선 비동기 처리는 피할 수 없는 문제.

call back

다른 함수의 인수로 넘기는 함수를 말한다. 그리고 그 콜백함수는 함수를 전달받은 함수안에서 호출된다.
특정 함수의 동작이 끝남과 동시에, 다른 여러 가지 함수를 호출해야 할 경우에 사용된다.

콜백사용법

const test = (callback) => {
  console.log("테스트함수 안에 있는거야!");
  callback()
};

test(()=> {console.log("이게바로 콜백")});

//테스트 함수 안에 있는거야!
//이게바로 콜백

비동기 콜백

const coffee = (callback, delay) => {
  callback();
};
console.log("주문 도와드리겠습니다.");

setTimeout(() => {
  console.log("음료 나왔습니다!");
}, 0);

console.log("다음 고객님!");

// 주문 도와드리겠습니다!
// 다음 고객님!
// 음료 나왔습니다!

call back 문제점

  1. 가독성이 떨어진다.
  2. 코드를 수정하고 만들기도 어렵다.
  3. 콜백지옥

call back 지옥

비동기 처리 로직을 위해 콜백 함수를 연속해서 사용할 때 발생하는 문제이다.

그렇다면 왜 우리가 콜백 지옥에 빠지게 되는 걸까?

콜백 함수는 비동기인데 그 안에 동기적인 코드를 넣으려고 하다보니
자연스럽게 중첩함수가 많이 생기고,
자연스럽게 콜백지옥에 빠지게 되는 것이다.

콜백지옥 코드

delay 첫번째 함수안에 비동기를 위해서 중첩시키고 계속 중첩시키다보면
중첩 함수들이 엄청 늘어나면서 콜백지옥에 빠지게 된다.

const delay = (sec, callback) => {
  setTimeout(() => {
    callback(new Date().toISOString());
  }, sec * 1000);
};

console.log("start", new Date().toISOString());

delay(1, (result) => {
  console.log(1, result);

  delay(1, (result) => {
    console.log(2, result);

    delay(1, (result) => {
      console.log(3, result);
    });
  });
});

이런 콜백지옥을 해결하는 방법은 Promise와 Async 방법이 있다.

Promise

콜백지옥을 탈출을 사용하는 자바스크립트 문법

  • ES6부터 추가 된 자바스크립트 문법
  • 미래에 값을 반환할 수도 있는 함수를 캡슐화한 객체
  • 제어의 재역전
  • 비동기 요청 수행에 대한 세 가지 (성공,실패,대기)의 상태를 가지고 있다.
  • 내부에서 비동기 요청이 끝나고 나면 결과값을 연결된 콜백으로 보내준다.

1. Promise 만들기

resolve 사용해보기 (할일 완료했을때 호출!)

const promise = new Promise((resolve,reject)=> {
  //네트워크 통신이나 파일 읽어오는 기능이 들어오는 것이 좋음
  console.log("이번엔 프로미스다!")
  setTimeout(()=>{
    resolve('dohee!');
  },2000);
});

reject 사용해보기 (예외처리나, 에러처리 났을때 호출!)

const promise = new Promise((resolve,reject)=> {
  //네트워크 통신이나 파일 읽어오는 기능이 들어오는 것이 좋음
  console.log("이번엔 프로미스다!")
  setTimeout(()=>{
  	reject(new Error('no network'));
},2000);
});

2. Promise 사용하기

  • then :
    promise가 정상적으로 잘 수행되어 최종적으로 resolve라는
    콜백함수를 통해 전달한 값이 인자값으로 들어오게 됨.
  • catch :
    에러가 발생했을때 어떻게 처리할건지 콜백함수를 등록해줌.
  • finally:
    성공 실패 상관없이 마지막에 기능을 수행하고 싶을때 사용.
promise.then((value) =>{
  	console.log(value);
}).catch(error => {
  	console.log(error);
}).finally(()=> {
	console.log("마지막에 떠야함");
})

3. Promise 연결하기

const fetchString = new Promise((resolve, reject) => {
  setTimeout(() => resolve("가"), 1000);
});

fetchString
  .then((str) => str + "나")
  .then((str) => str + "다")
  .then((str) => str + "라")
  .then((str) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => resolve("바보"), 1000);
    });
  })
  .then((str) => {
    return console.log(str);
  });

//바보

Promise 문제점

promise를 만드는 순간 우리가 전달한 executer 콜백함수가 바로 실행됨.
만약 우리가 네트워크를 통신하는 코드를 작성했다면 promise가 만들어지는 순간
네트워크 통신을 하게 됨.

간과하고 넘어가면 불필요한 네트워크 통신을 하게 된다.

async,await 란

Promise를 간결하고 좀 더 동기적으로 보여주게 하는 도구이다.

async와 await을 동기식으로 코드를 작성하는 것처럼
간편하게 코드를 짤 수 있게 도와준다.

함수는 언제나 Promise를 반환합니다.
함수 안에서 await를 사용할 수 있습니다.

async,await 어떻게 사용되는지?

async

  1. async는 항상 함수 앞에 붙는다.
  2. 함수앞에 async를 붙이면 해당 함수는 항상 Promise를 반환한다.
async function promise() {
  return "dohee!";
}

const P = promise();
P.then(console.log);
console.log(P);

//Promise{<pending>} 상태값
//dohee!

await

  • await은 async가 붙은 함수에만 쓸 수 있다.
  • await 키워드를 만나면 Promise가 처리될 때까지 기다린다.

코드 사용하기

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

async function dog() {
  await delay(1000);
  return "🐶";
}

async function cat() {
  await delay(1000);
  return "🐱";
}

//promise 적용버전
function pickPets() {
	return dog().then((dog) => {
	return cat().then((cat) => `${dog}+${cat}`);
	});
}

//async 적용버전
async function pickPets() {
	const dogpick = await dog();
	const catpick = await cat();
	return `${dogpick}+${catpick}`;
}

//병렬처리 적용버전
async function pickPets() {
  const dogPromise = dog();
  const catPromise = cat();
  const dogpick = await dogPromise;
  const catpick = await catPromise;
  return `${dogpick}+${catpick}`;
}

pickPets().then(console.log);
profile
무럭무럭 자라나는 도도 개발성장일기

0개의 댓글