동기, 비동기, Javascript의 비동기적 동작

양주영·2021년 10월 1일
0

javascript

목록 보기
27/42

동기(Synchrounous)와 비동기(Asynchronous)

1. 동기

동기 방식은 한 번에 하나의 작업만 진행하는 것이다.
서버에서 요청을 보냈을 때 응답이 돌아와야 다음 동작을 수행할 수 있다.
즉, A 작업이 모두 진행될 때까지 B작업은 대기해야 한다.

2. 비동기

비동기 방식은 반대로 요청을 보냈을 때 응답 상태와 상관없이 다음 동작을 수행할 수 있다. 즉 A 작업이 시작하면 동시에 B 작업이 실행된다. A 작업은 결과값이 나오는대로 출력된다.

▶️ 💡 비동기 처리란 특정 코드의 연산이 끝날 때까지 코드의 실행을 멈추지 않고 다음 코드를 먼저 실행하는 자바스크립트의 특성을 의미한다.

앞의 글에서 자바스크립트는 싱글 쓰레드로 동작한다고 설명했다.
이것은 한 번에 한 번의 작업만 실행할 수 있다는 특성을 의미한다.
하지만, 그럴 경우 만약 많은 양의 데이터 베이스를 요청해야 한다면 어떻게 할까?
동기적으로 처리한다면 하나의 작업에 대한 요청을 하고 응답을 기다리는 동안 다른 작업은 대기해야 할 것이다.
시간이 굉장히 오래 걸린다.
자바스크립트는 이 이슈에 대해 해결책(비동기적으로 동작 가능)을 제시했다.
그렇다면 어떻게 비동기 작업이 이루어지게 되는 걸까?

이를 이해하기 위해서는 자바스크립트의 실행 환경에 대해 생각해봐야 한다.

모든 프로그램이 그렇듯 프로그래밍 언어가 단순한 문자의 나열이 아닌, 나름의 규칙을 가진 코드로서 동작하려면 그에 맞는 실행 환경이 필요하다. 이를 런타임이라고 부른다.
브라우저는 그 자체로 자바스크립트를 실행할 수 있는 런타임이라고 할 수 있다.

브라우저, 즉 런타임이 멀티 쓰레드를 제공하기 때문에 자바스크립트는 이 위에서 비동기적인 동작들을 수행할 수 있게 된다.



비동기 흐름을 처리하는 방식들

1. 콜백 함수 사용 (콜백 지옥..☄️)

처리되어야 하는 이벤트들을 순차적으로 콜백 함수로 넣어주는 방식이다.
요즘도 많이 사용된다고 하지만 고전적인 방식이며 지옥이라 불리울만큼 치명적인 단점들을 가지고 있다.

1. 가독성이 매우 떨어진다.

2. 에러 처리를 한다면 모든 콜백에서 각각 에러 헨들링을 해줘야 한다.

꼬리에 꼬리를 무는 비동기 처리가 늘어나면 호출이 계속 중첩되고, 코드가 깊어지고, 관리는 어려워진다. 이런 깊은 중첩을 콜백 헬이나 멸망의 피라미드라고 부른다.

function async1('a', function (err, async2){
	if(err){
		errHandler(err);
	}else{
		...
		async2('b', function (err, async3){
			...
		}){
			...
		}
	}
});

콜백 헬이 발생하는 이유?

  • 비동기 처리 시에는 실행 완료를 기다리지 않고 바로 다음 작업을 실행한다.

  • 즉, 순서대로 코드를 쭉 적는다고 우리가 원하는 순서로 작업이 이뤄지지 않는다.

  • 비동기 처리 함수 내에서 처리 결과를 반환하는 걸로는 원하는 동작을 하지 않으니, 콜백 함수를 사용해 동작을 하게 하려고 콜백 함수를 쓴다.

  • 이 콜백 함수 내에서 또 다른 비동기 작업이 필요할 경우 위와 같은 중첩이 생기면서 콜백 헬이 탄생한다.

이러한 불편함을 해소하기 위해서 ES6에서 비동기 흐름을 컨트롤하는 방법으로 Promise 객체가 등장한다.


2. Promise 객체

Promise 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냅니다.
출처 MDN

비동기 연산이 종료된 이후 결과를 알기 위해 사용하는 객체이다.
비동기 처리 시점을 더 명확하게 표현할 수 있어 비동기 작업이 종료된 이후에 어떤 결과를 알기에 더 좋다.
Promise를 쓰면 비동기 메서드를 마치 동기 메서드처럼 값을 반환할 수 있다.
전통적인 콜백 패턴으로 인한 콜백 헬 때문에 ES6에서 도입한 또 다른 비동기 패턴 처리이다.
=> 비동기 처리 시점을 좀 더 명확하게 표현할 수 있다.


💡 Promise가 필요한 이유?
Promise는 주로 서버에서 받아온 데이터를 화면에 표시할 때 사용된다.
일반적으로 웹 애플리케이션을 구현할 때 서버에서 데이터를 요청하고 받아오기 위해 아래와 같은 API를 사용한다.

$.get('url 주소/products/1', function(response) {
  // ...
});

위 API가 실행되면 서버에다가 ‘데이터 하나 보내주세요’ 라는 요청을 보낸다. 그런데 여기서 데이터를 받아오기도 전에 마치 데이터를 다 받아온 것 마냥 화면에 데이터를 표시하려고 하면 오류가 발생하거나 빈 화면이 뜬다. 이와 같은 문제점을 해결하기 위한 방법 중 하나가 프로미스이다.


1️⃣ Promise 생성

  • 프라미스는 Promise 생성자 함수(new 키워드!)를 통해 생성한다.
  • 비동기 작업을 수행할 콜백 함수를 인자로 전달받아서 사용한다.
// 프라미스 객체 생성
// 인자로는 (resolve, reject) => {} 이런 excutor 실행자(혹은 실행 함수라고 불러요.)를 받음.
// 이 실행자는 비동기 작업이 끝나면 바로 두 가지 콜백 중 하나를 실행함.
// resolve: 작업이 성공한 경우 호출할 콜백
// reject: 작업이 실패한 경우 호출할 콜백
const promise = new Promise((resolve, reject) => {
	if(...){
		...
		resolve("성공!");
	}else{
		...
		reject("실패!");
	}
});

2️⃣ Promise 상태값

  • pending: 비동기 처리 수행 전(resolve, reject가 아직 호출되지 않음)
  • fulfilled: 수행 성공(resolve가 호출된 상태)
  • rejected: 수행 실패(reject가 호출된 상태)
  • settled: 성공 or 실패(resolve나 reject가 호출된 상태)

3️⃣ Promise 후속 처리 메서드

  • Promise로 구현된 비동기 함수는 Promise 객체를 반환한다.
  • Promise로 구현된 비동기 함수를 호출하는 측에서는 이 Promise 객체의 후속 처리 메서드를 통해 비동기 처리 결과를 받아서 처리해야 한다.
  • .then(성공 시, 실패 시)
    then의 첫 인자는 성공 시 실행, 두 번째 인자는 실패 시 실행된다. (첫 번째 인자만 넘겨도 된다!)
// 프라미스를 하나 만들어 봅시다!
let promise = new Promise((resolve, reject) => {
	setTimeout(() => resolve("완료!"), 1000);
});

// resolve
promise.then(result => {
	console.log(result); // 완료!가 콘솔에 찍힐거예요.
}, error => {
	console.log(error); // 실행되지 않습니다.
});

4. Promise chaining

Promise는 후속 처리 메서드를 체이닝해서 여러 개의 Promise를 연결할 수 있다.
후소 처리 메서드(then)을 쭉쭉 이어주는 것이다.

new Promise((resolve, reject) => {
	setTimeout(() => resolve("promise 1"), 1000);
}).then((result) => { // 후속 처리 메서드 하나를 쓰고,
	console.log(result); // promise 1
	return "promise 2";
}).then((result) => { // 이렇게 연달아 then을 써서 이어주는 거예요.
	console.log(result);
	return "promise 3";
}).then(...);

3. Promise를 활용한 async/await

자바스크립트의 비동기 처리 패턴 중 가장 최근에 나온 문법이다. 기존의 비동기 처리 방식인 콜백 함수와 프로미스의 단점을 보완하고 개발자가 읽기 좋은 코드를 작성할 수 있게 도와준다.




참고 >
https://usage.tistory.com/60
https://pro-self-studier.tistory.com/89
https://joshua1988.github.io/web-development/javascript/promise-for-beginners/

profile
뚜벅뚜벅

0개의 댓글