다음과 같은 코드를 작성했을 때, first, second, third 순서로 출력되는 결과를 볼 수 있을 것이다.
먼저 console.log("first")가 호출되면 Call Stack에 console.log("first")가 쌓이게 된다.
그 후, first를 반환하면 Call Stack에서 console.log("first")는 사라진다.
이때, 동기식으로 작동되기 때문에 first를 반환하지 않으면 다음 작업을 수행할 수 없다.
first를 반환하고 call stack에서 해당 함수가 사라지면 다음 console.log("second")가 call stack에 쌓이고 second를 반환하여 console.log("second")가 사라진다.
마지막으로 console.log("third")가 call stack에 쌓이고 third를 반환하여 console.log("third")는 call Stack에서 사라지고 종료될 것이다.
function first(){
second();
console.log("first");
}
function second(){
third();
console.log("second");
}
function third(){
console.log("third");
}
first();
자바스크립트에서 다음 코드를 실행한다면 first() -> second() -> third() 함수 순서로 호출될 것이다.
그러면 Call Stack에 쌓이는 순서 역시 first() -> second() -> third() 순서로 쌓이게 될 것이다.
하지만 이때 first() 전에 main() 함수가 Call Stack에 쌓여 있을 것이다.
main() 함수는 처음 실행할 때 전역 컨텍스트를 말한다.
전역 컨텍스트란 함수가 호출 되었을 때 생성되는 환경을 말한다.
main() 함수는 함수의 실행이 완료되면 Call Stack에서 지워진다.
즉 Call Stack에 쌓이는 순서를 보면 main() -> first() -> second() -> third()로 쌓이게 된다.
하지만 실행되는 순서는 third() -> second() -> first() -> main() 이다.
main() 함수까지 실행을 완료하면 Call Stack은 비워지고 third, second, first 순서로 출력되는 결과를 볼 수 있을 것이다.
비동기(Asynchronous)
비동기는 어떤 요청을 보내면 하나의 요청이 끝날 때까지 기다리는 것이 아닌, 응답에 관계없이 바로 다음 동작이 실행되는 방식이다.
< 비동기 사용하는 이유 >
만약 작업을 동기적으로 수행한다고 가정해보자.
그러면 어떠한 요청이 끝날 때까지 기다리는 동안 중지 상태가 되기 때문에 다른 작업을 수행할 수 없다.
하나의 요청의 수행 시간이 매우 길다면, 다음 동작을 수행하는데 영향을 미칠 것이다.
하지만 비동기적으로 작업을 수행한다면, 하나의 요청 때문에 웹 어플리케이션이 멈추지 않기 때문에 동시에 여러가지 요청을 처리할 수 있고, 요청을 기다리는 과정에서 다른 함수도 호출이 가능하다.
< 비동기 동작 원리 >
자바스크립트가 비동기적으로 작업을 처리할 수 있는 것은 자바스크립트의 런타임(실행 환경)과 관련 있다.
런타임은 특정 언어로 만든 프로그램들을 실행할 수 있는 환경을 말하고, Node.js나 크롬 등의 브라우저들은 자바스크립트가 구동되는 환경이므로 자바스크립트 런타임이라 한다.
브라우저에서는 자바스크립트 엔진으로만 동작하지 않는다.
자바스크립트 엔진 밖에서 자바스크립트에 관여하는 요소들이 있다.
바로 Web API, Callback Queue(Task Queue), Event Loop이다.
▶ Web API
: 브라우저에서 제공되는 API
: 자바스크립트 엔진에서 정의되지 않았던 setTimeout, HTTP 요청 메소드(ajax), DOM 이벤트 등의 메소드를 지원
[JavaScript] 동기와 비동기 이해하기
동기와 비동기 차이
동기(Synchronous)
우선 자바스크립트는 동기식 언어라고 할 수 있다.
이때 동기란 한 작업이 실행되는 동안 다른 작업은 멈춘 상태를 유지하고 자신의 차례를 기다리는 것을 말한다.
한 번에 하나의 작업만 처리하기 때문에 동기는 단일 스레드(싱글 스레드)라고도 부른다.
< 동작 원리 > - 자바스크립트 V8 엔진
자바스크립트의 동기의 동작 원리를 이해하기 위해서, 자바스크립트 엔진의 주요 구성 요소를 보면 이해가 쉽다.
우선 자바스크립트 엔진 Memory Heap과 Call Stack으로 구성되어 있다.
▶ Memory Heap
: 변수와 객체의 메모리 할당을 담당하는 곳
▶ Call Stack
: 함수가 호출 되면 쌓이는 곳
자바스크립트의 함수가 호출되면 Call Stack에 호출 순서대로 함수가 쌓인다.
그 후, Stack은 맨 마지막에 호출된 함수를 가장 먼저 반환한다.
예를 들어, 콘솔에 first, second, third를 출력하는 코드를 작성하는 예시를 보자.
다음과 같은 코드를 작성했을 때, first, second, third 순서로 출력되는 결과를 볼 수 있을 것이다.
먼저 console.log("first")가 호출되면 Call Stack에 console.log("first")가 쌓이게 된다.
그 후, first를 반환하면 Call Stack에서 console.log("first")는 사라진다.
이때, 동기식으로 작동되기 때문에 first를 반환하지 않으면 다음 작업을 수행할 수 없다.
first를 반환하고 call stack에서 해당 함수가 사라지면 다음 console.log("second")가 call stack에 쌓이고 second를 반환하여 console.log("second")가 사라진다.
마지막으로 console.log("third")가 call stack에 쌓이고 third를 반환하여 console.log("third")는 call Stack에서 사라지고 종료될 것이다.
자바스크립트에서 다음 코드를 실행한다면 first() -> second() -> third() 함수 순서로 호출될 것이다.
그러면 Call Stack에 쌓이는 순서 역시 first() -> second() -> third() 순서로 쌓이게 될 것이다.
하지만 이때 first() 전에 main() 함수가 Call Stack에 쌓여 있을 것이다.
main() 함수는 처음 실행할 때 전역 컨텍스트를 말한다.
전역 컨텍스트란 함수가 호출 되었을 때 생성되는 환경을 말한다.
main() 함수는 함수의 실행이 완료되면 Call Stack에서 지워진다.
즉 Call Stack에 쌓이는 순서를 보면 main() -> first() -> second() -> third()로 쌓이게 된다.
하지만 실행되는 순서는 third() -> second() -> first() -> main() 이다.
main() 함수까지 실행을 완료하면 Call Stack은 비워지고 third, second, first 순서로 출력되는 결과를 볼 수 있을 것이다.
비동기(Asynchronous)
비동기는 어떤 요청을 보내면 하나의 요청이 끝날 때까지 기다리는 것이 아닌, 응답에 관계없이 바로 다음 동작이 실행되는 방식이다.
< 비동기 사용하는 이유 >
만약 작업을 동기적으로 수행한다고 가정해보자.
그러면 어떠한 요청이 끝날 때까지 기다리는 동안 중지 상태가 되기 때문에 다른 작업을 수행할 수 없다.
하나의 요청의 수행 시간이 매우 길다면, 다음 동작을 수행하는데 영향을 미칠 것이다.
하지만 비동기적으로 작업을 수행한다면, 하나의 요청 때문에 웹 어플리케이션이 멈추지 않기 때문에 동시에 여러가지 요청을 처리할 수 있고, 요청을 기다리는 과정에서 다른 함수도 호출이 가능하다.
< 비동기 동작 원리 >
자바스크립트가 비동기적으로 작업을 처리할 수 있는 것은 자바스크립트의 런타임(실행 환경)과 관련 있다.
런타임은 특정 언어로 만든 프로그램들을 실행할 수 있는 환경을 말하고, Node.js나 크롬 등의 브라우저들은 자바스크립트가 구동되는 환경이므로 자바스크립트 런타임이라 한다.
브라우저에서는 자바스크립트 엔진으로만 동작하지 않는다.
자바스크립트 엔진 밖에서 자바스크립트에 관여하는 요소들이 있다.
바로 Web API, Callback Queue(Task Queue), Event Loop이다.
▶ Web API
: 브라우저에서 제공되는 API
: 자바스크립트 엔진에서 정의되지 않았던 setTimeout, HTTP 요청 메소드(ajax), DOM 이벤트 등의 메소드를 지원
▶ Callback Queue(Task Queue)
: 이벤트 발생 후 호출되어야 할 콜백 함수들이 기다리는 공간
: 이벤트 루프가 정한 순서대로 줄을 서 있어 콜백 큐라 불린다
자바스크립트에서 비동기로 호출되는 함수들은 Call Stack에 쌓이지 않고 Callback Queue로 보내진다.
위의 코드 실행 결과 "A", "C", "B" 순서로 콘솔에 출력되는 것을 볼 수 있을 것이다.
setTimeout 함수가 인수로 받은 콜백 함수를 일정 시간이 지난 후 실행하도록 예약하는 처리만 하고, 그 다음 바로 다음 코드가 실행되기 때문이다.
▶ Event Loop
: 이벤트 발생 시 호출할 콜백 함수들을 관리하고, 호출된 콜백 함수의 실행 순서를 결정
1. 전역 컨텍스트 main() 함수가 Call Stack에 쌓이고 console.log("시작")이 Call Stack에 쌓인 후, "시작"이 콘솔에 출력된다.
2. console.log("시작")이 리턴되며 Call Stack에서 제거된다.
3. setTimeout() 함수가 실행되어 Call Stack에 setTimeout() 함수가 쌓인다.
4. setTimeout() 함수는 자바스크립트 엔진이 처리하는 것이 아닌 WebAPI가 처리하기 때문에, Callback 함수를 전달하고 setTimeout 작업을 요청한다.
5. Call Stack에서 setTimeout 작업이 제거된다.
6. console.log("끝")이 호출되고 Call Stack에 쌓이며 "끝"이 콘솔에 출력된다.
7. console.log("끝")이 리턴되며 Call Stack에서 제거된다.
8. main() 함수가 리턴되고 Call Stack에서 제거된다.
9. Web API가 setTimeout 작업을 실행한다. 3초가 지난 후 Callback Queue(Task Queue)에 Callback 함수를 보낸다.
10. Event Loop는 Call Stack이 비어있으면 Callback Queue에서 함수를 하나 씩 꺼내 Call Stack에 넣고 실행한다.
11. console.log("3초후 실행")이 호출되어 Call Stack에 쌓이고 콘솔에 "3초후 실행"이 출력된다.
12. console.log("3초후 실행")이 리턴되고 Call Stack에서 제거된다. Callback 함수도 제거된다. Event Loop는 Callback Queue에 콜백 함수가 들어올 때까지 계속 대기한다.
[JS] Javascript 동작 원리와 비동기처리
자바스크립트는 싱글스레드이다. 어떻게 자바스크립트는 싱글스레드이면서 비동기인 것일까? 자바스크립트가 어떻게 동작하는지 내부 원리에 대해 알아보자.
ingg.dev
비동기적 자바스크립트 참고
이렇듯, 비동기로 구현하여 각 기능이 시간 낭비 없이 동시에 실행될 수 있지만, 실행 결과의 순서를 보장하지 않는다.
따라서 비동기 작업의 순서가 보장되어야 할 때, 콜백 함수, Promise, asyn/await를 사용하여 해결할 수 있다.
다음 게시물에서 비동기 처리의 콜백 함수, promise, asyn/await에 대해 자세히 알아보겠다.
'Front-End > JavaScript' 카테고리의 다른 글