여러 함수를 호출하는 스크립트에서 해당 위치를 추적한다.
💫예를 들자면 엄청 두꺼운 책을 여러 페이지를 넘기면서 볼 때 용어 사전이나 부록등을 참고 하려고 할 것이다. 읽었던 곳을 표시하기위해 손이나 책갈피 등을 두기도 한다. 콜 스택의 역할이 바로 이거다 !!!!!!
스택이라는 말을 좀 더 생각해보면 이전에 언급했던 배열 push,pop,shift,unshift 등과 같다.
스택은 컴퓨터 과학의 기본 데이터 구조이다.이는 후입선출(LIFO) 데이터 구조로 알려져 있다.
만약에 책 더미가 있고 맨 위에 사과가 있다고 치면 사과가 맨 마지막에 추가 됐지만, 꺼내는 것도 사과를 가장 먼저 꺼낼 수 있다.
스크립트가 함수를 호출하면 해석기는 콜스택에 추가한다. 그리고 실제 그 함수를 수행하기 시작한다. 첫번째 함수가 호출한 다른 함수도 콜 스택에 추가되어 호툴되면 실행된다. 현재 함수가 완료되면 해석기는 콜 스택에서 함수를 제거하고 마지막 코드 목록의 멈춘 곳에서 계속 실행한다.
const multiply = (x, y) => x * y;
const square = x => multiply(x, x);
const isRightTriangle = (a, b, c) => (
square(a) + square(b) === square(c)
)
console.log("BEFORE")
isRightTriangle(3, 4, 5)
console.log("DONEEEE!")
isRightTriangle
은 square
를 세번 호출한다. square
는 multiply
를 호출한다.
이걸 콜스택으로 표현하자면
나는 이렇게 쌓인 책으로 그려내봤다. 맨 위 책부터 꺼낼 수 있고 마지막에 함수가 실행된다.3 다음에 4 , 4다음 5 이런순서로 ! 그럼 마지막에 9 + 16 === 25
의 결과가 나오게 된다.
🤔자바스크립트는 단일 스레드이다 이게 무슨 말일까?
자바스크립트는 어느 시점에서 작동할 수 있는 부분이 하나 있음을 의미한다. 그러면 동시에 두 가지 일을 수행하는 멀티 태스킹을 할 수 없다. 다르게 말하면 자바스크립트는 최대 한번에 한줄의 코드만 실행한다. 다른 줄의 코드 사이를 앞뒤로 전환 할 수도 있다. 이게 너무 빠르게 전환되어서 우리가 모르지만 다시 말하지만 자바스크립트는 최대 한번에 한줄의 코드만 실행한다.
만약에 AJAX로 들어가 자바스크립트로 요청을 하고 정보를 불러온다고 해보자!
프런트 엔드에 코드로 " 영화 API '박쥐'가 들어간 모든 영화를 보내줘 "라고 쓴다면,
제목에 박쥐가 있는 영화를 찾을 것이다. 실제로 응답을 받는 그 시간까지 자바스크립트가 한가지 일만 할 줄 안다면 , 코드에서는 아무일도 안일어나는걸까? 사용자가 그 일이 끝날때까지 기다려야 하는 걸까?
=> 그런식으로 진행되지 않는다. 해결하는 방법이 있다.
예를들어 콜백함수의 setTimeout
을 예를 들 수 있다.
console.log("Sending request to server!")
setTimeout(() => {
console.log("Here is your data from the server...")
}, 3000)
console.log("I AM AT THE END OF THE FILE!")
실제 실행 될 때 하나하나 실행이 된다. 그럼 3초를 기다리는 걸까?
어떻게 작동이 되는걸까? 아니다.자바스크립트가 아니라 브라우저가 실제로 작업을 하고 있다.
자동차의 엔진룸처럼 브라우저 자체가 무엇이든 간에 브라우저가 자바스크립트로 작성되는게 아니라 다른 언어로 작성되기때문에 처리하도록 넘길 수 있다. 실제로 작동하는 방식은 자바스크립트의 콜 스택이 Web API의 함수를 인식하고 브라우저에 전달하는 것이다.
" 이 일을 처리하기위해 3초 후에 알려주세요"라 한다면 브라우저가 작업을 마치자마자 콜 스택을 추가해준다.
setTimeout(() => {
document.body.style.backgroundColor = 'red';
setTimeout(() => {
document.body.style.backgroundColor = 'orange';
setTimeout(() => {
document.body.style.backgroundColor = 'yellow';
setTimeout(() => {
document.body.style.backgroundColor = 'green';
setTimeout(() => {
document.body.style.backgroundColor = 'blue';
}, 1000)
}, 1000)
}, 1000)
}, 1000)
}, 1000)
위 코드처럼 쓰게 되면 콜백지옥에 빠지게 되는데 이걸
아래 코드펜처럼 쓰게되면 더 가독성이 좋고 콜백지옥을 벗어 날 수 있다.
영화를 가져온다고 생각해보자! 여기서도 콜백 함수를 이렇게 적어낼 수 있다.
searchMoviesAPI('amadeus', () => {
saveToMyDB(movies, () => {
//작동한다면 이걸 실행
}, () => {
//작동하지 않는다면 이걸 실행
})
}, () => {
if API is down, or request failed
})
// THE CALLBACK VERSION
const fakeRequestCallback = (url, success, failure) => {
const delay = Math.floor(Math.random() * 4500) + 500;
setTimeout(() => {
if (delay > 4000) {
failure('Connection Timeout :(')
} else {
success(`Here is your fake data from ${url}`)
}
}, delay)
}
// THE PROMISE VERSION
const fakeRequestPromise = (url) => {
return new Promise((resolve, reject) => {
const delay = Math.floor(Math.random() * (4500)) + 500;
setTimeout(() => {
if (delay > 4000) {
reject('Connection Timeout :(')
} else {
resolve(`Here is your fake data from ${url}`)
}
}, delay)
})
}
//콜백지옥
//요청을 보내고 성공과 실패 콜백을 넣어주는 방식이 가장 일반적이다
//이 예시는 대충 만든 가짜
fakeRequestCallback('books.com/page1',
function (response) {
console.log("IT WORKED!!!!")
console.log(response)
fakeRequestCallback('books.com/page2',
function (response) {
console.log("IT WORKED AGAIN!!!!")
console.log(response)
fakeRequestCallback('books.com/page3',
function (response) {
console.log("IT WORKED AGAIN (3rd req)!!!!")
console.log(response)
},
function (err) {
console.log("ERROR (3rd req)!!!", err)
})
},
function (err) {
console.log("ERROR (2nd req)!!!", err)
})
}, function (err) {
console.log("ERROR!!!", err)
})