예전 블로그 글에 promise 공부를 했을 때, 정리해서 올린 내용이 있었는데, 시간이 지난 지금 이해하고 적은게 아닌것같아 다시 정리해 보려한다. 헤헷😏
Synchronous 자체를 번역하면 동시성 / 동시의 이라는 단어가 나오는데 gpt에게 물어보면 '하나 하나 순차적으로 실행된다는 뜻'이라고한다. 다음은 gpt와 각종 블로그의 정보를 참고 + 조합해서 나온 동기가 무엇인지에 대해 간단히 정리하자면 아래와 같다.🤔
그럼 다음 코드를 살펴보자.
console.log("hello")
for(let i = 0; i < 10000; i++){
//동기적으로 처리하기 위한 코드
}
console.log("Hi")
이렇게 hello -> for문 -> Hi가 찍히기도 하지만
console.log("Hi");
alert("확인 안누르면 다음 콘솔 안찍힐걸?!");
console.log("으악 찍힘");
alert을 사용해 확인할 수도 있다. alert은 브라우저의 기본 내장 API이며, JS로 사용자와 상호작용할 수 있도록 설계된 동기 함수이다. 따라서 Web API와는 다르다.(alert과 더불어 prompt, confirm이 있다.)
비동기는 동기의 반대의 개념이니, 동시에 일어나지 않는다는 뜻이다! 그렇다면 동시에 처리할 수 있다는 뜻도 되고, 긴 작업이 진행되는 다른 무엇을 기다리는 동안 다른 작업을 동시에 실행할 수 있다는 뜻이된다.
비동기 코드의 예시는 아래와 같다.
//I/O 작업이나 네트워크 요청이라고 했으니 fetch로 예시를 들었다.
console.log("얏호");
fetch('서버로부터 요청할 URL')
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error('Error:', err));
console.log("끗!");
위와 같이 네트워크 요청 fetch가 있다면
얏호 -> 끗 -> 네트워크 요청 완료 후 데이터 출력
순으로 나오게 될것이다. fetch 함수는 Promise를 반환한다. 이 Promise는 바로 다음 내용에서 살펴보자.
Promise는 비동기 작업의 결과를 나타내는 객체이다. promise는 객체가 생성될 때 내부의 executor 함수가 즉시 실행된다. 그래서 executor 함수는 promise를 생성하는 순간 동기적으로 실행된다고한다. 나는 여기서 신선한 충격을 받았다. promise -> 비동기라는 생각이 있었는데, 동기적으로 실행 후 .then이나 .catch로 비동기 처리가 이어진다니.. 너무 신기했다. 그런고로 promise에 대해 다시 내용을 정리하려한다.
executor 👉 집행자라는 영어 뜻을 가지며, 여기선 Promise 객체를 생성할 때 전달하는 함수이다. 이 함수는 Promise의 실행자 함수라고 하며, 'resolve', 'reject'라는 두 개의 콜백 함수를 인수(=Argument)로 받는다.
다음 예시 코드를 보면서 다시 살펴보자
const myPromise = new Promise((resolve, reject) => {
//executor함수!
const data = fetch('서버로부터 요청할 URL');
if(data){
resolve(data);
}
else{
reject("Error");
}
})
이 코드를 해석하면 다음과 같다.
1. new Promise가 호출될 때 executor 함수가 즉시 실행됨
2. executor 함수 내부에서 비동기 작업(여기선 fetch 함수가 네트워크 요청하는 것)
3. 작업이 성공하면 resolve에 data가 나올것이고, 이게 아니라면 reject의 error가 호출될 것이다.
Promise의 로직을 보면 new가 붙은걸 볼 수 있는데, 이것은 new 연산자라고 한다. new 연산자는 생성자 함수를 호출할 때 사용되는것으로 생성자 함수를 호출해 새로운 객체를 생성하는 역할을 한다. (따지고보면 new 연산자 !== 생성자 함수이다.)
다음은 new 연산자가 어떻게 동작하는지에 대한 간단한 과정이다.
새로운 객체 생성 -> 프로토타입 연결 -> this 바인딩 -> 생성자 함수 실행 -> 객체 반환 순이다.
다음은 세부 설명이다.
새로운 객체 생성
let obj = {};
프로토타입 연결
//이렇게 언더바 두 개가 있는것을 던더 프로토라고 한다.
obj.__proto__ = ConstructorFunction.prototype;
this 바인딩
생성자 함수 실행
객체 반환