자바스크립트는 기본적으로 싱글 스레드이기 때문에 한 번에 하나의 동작만 할 수 있다. 동기 언어. 따라서 코드가 순차적으로 실행된다. 하지만 이렇게 되면 문제가 있다. 네트워크 요청 등의 작업은 시간이 오래 걸리는데, 이런 코드를 동기식으로만 처리한다면 뒤의 작업들은 모두 대기 상태가 된다. 블로킹이 발생하는 것이다.
이걸 해결하기 위한 것이 비동기!
자바스크립트는 웹 개발을 위해 설계되었기 때문에 비동기 처리가 매우 중요하다. 또한 UI에서 상호작용을 즉각적으로 처리하기 위해서는 백그라운드에서 오래 걸리는 작업들이 비동기로 처리되어야 할 필요가 있다.
- ex. 버튼 클릭할 때 HTTP 요청을 보내는 동안 UI는 멈추지 않고 반응해야.
자바스크립트에서 비동기 작업을 처리하는 방법
- 콜백함수
- 비동기 작업이 완료되었을 때 실행될 함수를 콜백함수(다른 함수의 인자로 넘길 수 있는 함수)로 넘긴다.
- 간단한 비동기 작업을 처리할 때는 괜찮지만, 두 개 이상의 비동기 작업이 순차적으로 처리되어야 할 때는 콜백 함수 내부에 또 콜백함수를 넘겨야 해서(콜백 지옥 발생) 가독성과 유지보수성에 어려움이 있다.
- Promise
- 비동기 작업의 완료 또는 실패를 나타내는 객체로 Pending(완료되지 않은 상태), Fulfilled(완료된 상태), Rejected(실패한 상태)의 상태를 가진다.
- then, catch 체이닝으로 비동기 작업을 순차적으로 처리할 수 있다.
- async/await
- 비동기 코드를 동기식 코드처럼 작성해서 가독성 면에서 장점이 있다.
- 비동기 함수 앞에 async를 붙이고 함수 내부에서 promise 앞에 await를 붙여서 동기식으로 코드를 작성할 수 있다.
자바스크립트 엔진과 이벤트 루프
그렇다면 자바스크립트 엔진은 어떻게 비동기 작업을 처리할까?
- 콜 스택
- 현재 실행 중인 함수들이 쌓인다. 함수 호출 시 스택에 추가되고, 실행이 완료되면 스택에서 pop 된다. LIFO.
- 태스크 큐
- 비동기 작업이 완료된 후 실행될 콜백함수들이 대기하는 곳. 타이머 함수나 이벤트 핸들러들이 대기.
- 마이크로 태스크 큐
- 프로미스의 then, catch, finally 메서드가 들어가는 곳. 태스크 큐보다 우선순위가 높다!
- 현재 실행 중인 함수들은 콜 스택에 쌓인다. 그리고 자바스크립트 엔진은 콜 스택의 가장 상단에 쌓인 함수부터 실행한다. (LIFO)
- 비동기 함수가 실행되면 자바스크립트 엔진은 이를 브라우저 API에 넘기고 콜백 함수를 등록한다.
- 비동기 작업이 완료되면 콜백 함수가 태스크 큐에 추가된다.
- 이벤트 루프는 콜 스택과 태스크 큐를 오가며 콜 스택이 비어있는지를 확인한다. 그리고 비어있으면 태스큐 큐에서 콜백 함수를 가져와 콜스택에 추가하고 실행한다.
마치며
면접 때 자바스크립트와 비동기에 대해서 제대로 답변하지 못한 것 같아서 다시 정리해봤다. 동기식으로 처리하면 좋은데 왜 비동기를 사용해서, 자바스크립트를 사용할까? 에 대한 충분한 고민을 더 해봐야겠다.
'Frontend > JavaScript' 카테고리의 다른 글
| JS의 sort()는 기본적으로 문자열 정렬이다. (1) | 2024.06.04 |
|---|---|
| Array.at() 뒤에서부터 인덱스 접근 (0) | 2024.03.14 |
| 검색어 입력하는 동안 API 호출 지연하기 - 디바운스(Debounce) (0) | 2024.01.22 |
| [JavaScript] e.preventDefault() 로 form 의 기본 동작 막기 (0) | 2024.01.22 |
| Proxy 프록시 (0) | 2023.12.29 |