일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 프론트
- 탄스택쿼리
- 리액트
- CSS
- 자바스크립트
- 개발
- react
- Tanstack Query
- 개발자
- 개발공부
- 코딩
- 프론트엔드 스쿨
- 인터넷
- 조건문
- props
- 콜백
- 리액트쿼리
- Tanstack
- TS
- 제로베이스
- 부트캠프
- 프론트엔드
- 타입스크립트
- TypeScript
- HTML
- components
- 공식문서
- hooks
- JavaScript
- JS
- Today
- Total
SUE 개발 블로그
자바스크립트 동기 & 비동기 본문
순서대로 실행하는 것(동기)과 그렇지 않은 것(비동기) 들
자바스크립트 엔진이 동작하는 원리를 파악해보자.
우리가 만약 세가지의 작업을 다 해야하는 상황.
각각의 작업은 TASK A, B, C 함수로 만들어 놓고 이 작업을 모두 순서에 상관없이 해야한다면?
프로그래밍된 코드를 계산해서 실행시키는 연산과정을 진행하는 일꾼을 쓰레드라고 한다.
이 과정은 코드 한줄 한줄마다 진행되며 스레드는 코드를 한줄 한줄 실행시켜주는 친구라고 생각하면된다.
taskA를 작업하고 있다면 taskB를 작업하지 않고 A가 끝나야 B작업으로 넘어갈 수 있다.
이렇게 지시한 순서대로 작업하면서 앞에 작업이 끝나기를 기다렸다가 뒤에 작업을 하는 것을 동기적 방식이라고 한다.
그리고 스레드에서 작업 하나가 수행 중일 때 다른 작업을 동시에 수행할 수 없는 것을 블로킹 방식이라고 부른다.
그런데 수행해야하는 여러가지의 작업들이 오래걸리는 무거운 작업들이 포함되어 있다면?
( 위의 이미지는 TaskB가 0.5초 걸렸었다 )
웹사이트가 사용자에게 반응 ( 상호작용 ) 이 늦는다면? 우리가 만든 사이트를 다신 찾아오지 않을 것.
동기적으로만 작업을 모두 처리하게 되면 중간 중간 오래걸리는 작업까지 포함되어 작업 수행시간이 길어지는 등
성능 상에 문제가 발생한다.
Q : 그러면 일꾼 ( 쓰레드 ) 를 늘리면 되지 않나요?
여러 쓰레드를 사용하는 방식을 멀티쓰레드 라고 부르며 위 문제가 해결이 가능하다.
하지만 자바스크립트는 쓰레드를 단 한개만 사용하는 싱글 쓰레드 방식으로 작동하고있다.
하지만 쓰레드가 하나일지라도 작업 여러 개를 동시에 실행시켜 버리면 된다.
Task A, B, C 작업이 끝나던 말던 관심없이 동시에 다 실행시켜버린다.
이렇게 동기적이지 않게 여러 개의 작업을 동시에 수행하게 하는 방식을 비동기 처리방식이라고 부른다.
그리고 이렇게 하나의 작업이 쓰레드를 점유하지 않는.
하나의 작업을 수행할 때 쓰레드가 다른 작업을 하지 못하도록 블로킹을 하지 않는 방식을
논 블로킹 방식이라고 부를 수 있다.
이렇게 동시에 다 실행시키면 작업들이 정상적으로 끝났는지는 어떻게 확인하고 작업들의 결과는 어떻게 확인할까?
위와 같이 비동기적으로 실행된 각각의 함수들에게 작업 끝나면 실행하라는 의미의 콜백함수를 붙여서 전달하면 된다.
이렇게 비동기 처리를 할 때는 자바스크립트에서 함수를 호출 할 때 콜백함수를 붙여서
그 비동기 처리의 결과값이나 작업이잘 끝났는지를 확인할 수 있다.
자바스크립트의 엔진은 어떻게 이런 동기적인 코드와 비동적인 코드를 구분해 실행하는지 알아보자.
자바스크립트들로 작성한 코드들은 웹브라우저나 프로그램에 탑재되어 있는
자바스크립트의 엔진을 이용해 해석되고 실행된다.
자바스크립트 엔진은 Heap 과 Call Stack 두 가지의 구성요소로 구성되어 있다.
Heap은 변수나 상수들의 사용되는 메모리를 저장하는 영역으로 알고있으면 되며, Call Stack은
우리가 작성한 코드의 실행에 따라서 호출 스택이란 것을 쌓는 영역이다. ( 중요 )
코드의 실행 흐름을 살펴보며 자바스크립트 엔진의 구동 방식을 알아보자.
자바스크립트 코드의 실행이 시작되면 Call Stack에 자바스크립 코드 최상위 문맥인 Main Context가 가장먼저 들어온다.
Main Context가 Call Stack에 들어오는 순간이 프로그램이 시작되는 순간이고
Call Stack에서 사라지는 순간이 프로그램이 종료되는 순간인 것이다.
첫번째 코드가 실행이 되고 function one(), two(), three() 는 함수를 생성이기 때문에 생성만 하고 넘어가고,
실제로 실행되는 부분은 console.log(three()); 가 되므로 이때 콘솔로그 안에서
three()라는 함수를 실행하게되므로 Call Stack에 three()에 추가되게 된다.
왜냐면 three() 라는 함수를 실행해야 우리가 결과값을 리턴받아 콘솔에 찍어 사용가능하기 때문이다.
그 다음에는 three() 함수를 실행하여 결과값이 뭔지 받아보려고 했는데
three() 라는 함수 안에서는 two()라는 함수를 실행하고 있다. 그럼 two() 라는 함수를 호출했기 때문에
얘도 실행시킨다. 그럼 Call Stack에 또 two() 를 쌓게된다.
그래서 two() 를 실행시키려 했더니 one() 을 실행시키고 있다.
또 two() 함수에서 one() 함수를 호출하고 있기 때문에 Call Stack엔 one() 함수가 쌓인 것을 확인할 수 있다.
그래서 one() 함수를 실행했더니 1을 리턴하고 바로 종료가 되는 것을 볼 수 있다.
Call Stack 에서는 종료된 함수는 바로 바로 스택에서 빠지게된다. ( 1을 반환하고 종료 → 콜 스택에서 제거 )
two() 함수에서는 리턴받은 1에 1을 더하고 2를 반환하면서 종료된다. ( 콜 스택에서 제거 )
three() 함수에서 리턴받은 2에 1을 더하고 3을 반환하며 종료. ( 콜 스택에서 제거 )
three() 에서 반환되는 값은 3으로 콘솔로그에 3을 출력한다.
콘솔로그까지 끝났으면 프로그램이 종료된 것으로 더 이상 수행할 코드가 없으므로
프로그램을 종료하기 위해 Main Context 도 Call Stack 에서 빠지게 된다. ( 프로그램의 종료 )
자바스크립트 엔진은 위와 같은 방식으로 프로그램을 실행하고 종료한다. ( 동기방식 )
이번엔 비동기 방식 으로 어떻게 작동하는지 알아보도록 하자.
setTimeout() 함수를 포함해서 asyncAdd() 함수는 비동기 작업을 실행하고 있다.
화면을 보면 이전과는 다르게 Web APIs 와 Callback Queue, Event Loop 라는 새로운 요소들이 생겨난 걸 볼 수 있다.
이 자바스크립트 엔진외에 세가지 구성요소들은 자바스크립트 엔진과 웹브라우저간의 상호작용 등을 처리하기 위해 존재.
그 중 가장 대표적인 상호작용이 비동기 처리이다.
프로그램이 시작되고 asyncAdd()함수가 1,3 과 콜백 함수 세개의 파라미터가 전달하면서 호출하면
실제로 실행하기 위해서 콜 스택에 asyncAdd() 함수가 추가되는 것을 알 수 있다.
asyncAdd() 함수를 실행할려고 봤더니 안에서 setTimeout() 이라는 비동기 함수를 호출하는 것을 확인한다.
그리고 setTimeout() 은 cb() 라는 콜백함수도 포함하고 있어서 위의 그림과 같이 콜 스택에 추가된다 볼 수 있다.
빨간색으로 표시한 이유는 다른 함수들과 달리 비동기 함수이기 때문이다.
setTimeout() 함수는 3초를 기다리게 되어있는데
콜 스택에서 그대로 수행하게 두면 정말 3초를 기다렸다가 다음 코드를 실행해야 한다.
그렇기에 자바스크립트 엔진은 비동기로 수행되는 setTImeout() 같은 함수를 위와 같이 Web APIs 로 넘기게 된다.
그러면 넘겨진 setTimeout() 함수는 실행이 멈추는게 아니라 그 곳에서 3초를 기다리게 된다.
이렇게 setTimeout() 함수가 Call Stack에 머무리지 않게되기 때문에 바로 다음 코드를 수행 할 수 있게 되고
asyncAdd() 함수를 끝낼 수 있게 된다. asyncAdd() 함수는 실행이 끝났기 때문에 콜 스택에서 제거가 된다.
asyncAdd() 함수가 제거가 된 다음에 setTimeout() 함수의 3초의 기다림이 끝나면
setTimeout() 함수는 제거가 되고 Web APIs 에 있는 콜백.
cb() 함수가 Callback Queue 로 옮겨지게 된다. ( 이제 수행을 해야하기 때문에 )
이렇게 콜백 큐에 옮겨지게 되면은 Event Loop 에 의해서 콜 스택으로 다시 옮겨질 수 있다.
어떤 콜백 함수가 Web APIs 에 있다가 위와 같이 Callback Queue 에서 Call Stack 으로 들어간다는 의미는
콜백 함수가 실제로 수행이 이루어진다 생각하면 된다.
Event Loop가 Callback Queue 에서 Call Stack 으로 cb() 함수를 넘겨주게 되는데 어떻게 넘겨주게 되냐면
이벤트 루프는 콜 스택에 Main Context 를 제외한 다른 함수가 남아있는지를 계속 확인한다.
만약 아무것도 남아있지 않다면 콜백 함수를 수행할 수 있으니까 위와 같이 넘겨주게 된다.
위와 같이 cb() 함수가 실행이 되어 콘솔로그를 실행하게 하고
결과를 출력하게 된 다음 cb() 함수를 콜 스택에서 제거하게 되고
더 이상 수행할 프로그램이 없으니 Main Context 가 제거가 된다. ( 프로그램의 종료 )
이렇게 자바스크립트 엔진의 비동기 코드 실행 원리를 알아보았다.
'JavaScript' 카테고리의 다른 글
자바스크립트 async & await (0) | 2023.12.19 |
---|---|
자바스크립트 Promise 콜백 지옥 탈출 (2) | 2023.12.18 |
자바스크립트 This 란? (0) | 2023.12.12 |
자바스크립트 spread 연산자 (0) | 2023.12.12 |
자바스크립트 비구조화 할당 (0) | 2023.12.11 |