개발이군고구마

[JS] 자바스크립트 동작 원리 2 (비동기와 이벤트루프) 본문

FRONT

[JS] 자바스크립트 동작 원리 2 (비동기와 이벤트루프)

김구황 2024. 6. 30. 16:57
728x90

0. WHY?

- Apple 로그인 API를 사용할 경우, 인증성공 실패 외에 어떤 반응 없이 뒤로가기나 취소 버튼을 누르고 돌아갔을 때의 콜백함수를 처리하고 싶었음. 

AppleID.auth.init({
    clientId : '[CLIENT_ID]',
    scope : '[SCOPES]',
    redirectURI: '[REDIRECT_URI]',
    state : '[STATE]'
});

 
- async과 await를 사용해서 함수가 실행된 이후 API를 통해 받아오는 요청에 따라서 그에 맞는 script 조작

async(
    await (
        AppleID.auth.init({
        });
    )

    document.addEventListener('AppleIDSignInOnFailure', (error) => {
        console.log(error);
         //handle error.
    });
    >> 성공, 실패에 따른 이벤트 리스너로 버튼 조작함 
)

 
- 어떤 순서로 aysnc과 await 가 작동되는지 궁금하였음
 
 

1. 이벤트 루프 

- 브라우저의 동작 타이밍을 제어하는 관리자
- Task Queue 에 대기 중인 작업이 있는지 반복적으로 확인하는 일종의 무한 루프 
 
[비동기란]
- task에 대한 서버에서 응답을 받기 전에 다른 테스크가 실행되는 방법 
 
[역할]
- 싱글 스레드인 자바스크립트를 

  • 멀티스레드로 돌려 작업을 "동시에" 처리
  • 어떤 작업을 "우선" 으로 동작시킬 것인지 컨트롤 

- 작업을 옮기는 역할
 
 
[동작방법]
"Event Driven" 프로그래밍 
- Callstack / Web API / Callback Queue (Microstack Queue, Task Queue) 등의 요소들을 모니터링 하면서,

  • 비동기적으로 실행되는 작업들을 관리하고,
  • 이를 순서대로 처리하여 프로그램 실행을 제어 

 
[브라우저 내부 구성도]
- Web API : 브라우저에서 제공하는 API 모음. 멀티 스레드로 구현되어 있음 
- 자바스크립트 엔진은 소스의 분석 및 실행을 담당
- 이외 모든 업무 (스케줄링, 콜백함수 등록) 는 브라우저가 담당
- 브라우저 환경은 web api와 queue를 제공 

참고 1 사이트
  • DOM, console 동기 
  • XMLHttpRequest(ajax), TimeAPI 비동기 

 
- Callback Queue
콜백함수들이 저장되는 Queue 
종류에 따라 이벤트 리스너가 call stack 에 넘기는 순서가 달라짐 

  • Microtask Queue : promise then, async await  (처리 우선순위가 높음) 
  • Task Queue : setTimeout, fetch, addEventListener

 

2. async await 

- async 는 await를 사용하기 위한 함수 키워드일 뿐, 프로미스 객체를 반환하는 일반적인 함수 
- then 대신 await (즉, Promise 객체에 쓰일 수 있는 핸들러)

async function myFunc(){
    console.log('In function!');
    const res = await One(); >> 이 아래부터 queue 에 넣어짐 
    console.log(res);
}

1) async 함수가 callstack 에 적재되어 실행되면
2) await 키워드로 인해 async 함수의 내부 실행은 잠시 중단되고 
3) callstack 에 빠져나와 나머지 부분들이 Microtask Queue에 적재됨 
4) 스택에 있는 모든 스크립트 코드가 완료되어 callstack 이 비워지게 되면 
5) queue 에 있는 콜백함수(=남아있는 async 함수) 를 callstack으로 올김 
 
 
 

3. Promise

Promise.resolve('Promise!').then(**res => console.log(res))**;
>> then 핸들러의 콜백함수

1) Promise가 callstack 에 적재되어 실행되면
2) then 핸들러의 콜백함수가 Microtask Queue 에 적재
3) 스택에 있는 모든 스크립트 코드가 완료되어 callstack 이 비워지게 되면 
4) queue 에 있는 콜백함수를 callstack으로 올김 
 
 

4. setTimeout

function bar() {
  setTimeout(() => {
  	console.log("Second")
  }, 500); >> 콜백함수 
}

1) setTimeout에 걸린 콜백 함수를 WebAPI 에 전달 
2) 브라우저가 스케쥴링을 시작 -> 대기 시간이 만료되면 콜백함수를 task queue 에 옮김
3) 스택에 있는 모든 스크립트 코드가 완료되어 callstack 이 비워지게 되면 
4) 이벤트 루프가 queue 에 있는 콜백함수를 callstack으로 올김 
 
 


*참고 
https://inpa.tistory.com/entry/%F0%9F%94%84-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84-%EA%B5%AC%EC%A1%B0-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC (그림)
 
https://ljtaek2.tistory.com/129?category=897337 (코드)