모던 리액트 Deep Dive - 이벤트 루프와 비동기 통신의 이해

2025. 9. 23. 20:13·Study/모던 리액트 Deep Dive

⚡리액트 개발을 위해 꼭 알아야할 자바스크립트 - 1.5 이벤트 루프와 비동기 통신의 이해

1.5.1 싱글 스레드 자바스크립트

🌚자바 스크립트

  • 한번에 하나의 작업만 동기 방식으로 처리할 수 있음(싱글 스레드)
  • 하나의 코드가 실행하는데 오래걸리면 뒤의 코드가 실행되지 않는 것 > "Run-to-completion"
  • 자바스크립트는 비동기 처리가 가능한 것을 이해하려면 이벤트 루프를 알아야 함
    • 동기 : 직렬방식
    • 비동기 : 병렬방식 
자바스크립트는 싱글스레드지만, 브라우저(혹은 Node.js)가 제공하는 이벤트 루프(Event Loop)와 백그라운드 API(Web API, Thread Pool) 덕분에 비동기 처리가 가능하다.

1.5.2 이벤트 루프란?

  • 자바 스크립트 런타임 외부에서 자바스크립트의 비동기 실행을 돕기 위해 만들어진 장치

💡호출스택과 이벤트 루프

  • 호출스택(call stack) : 자바스크립트에서 수행해야 할 코드나 함수를 순차적으로 담아두는 스택

🌚 foo를 호출하고, 내부에서 bar, baz를 순차적으로 호출하는 구조

function bar() {
  console.log('bar')
}

function baz() {
  console.log('baz')
}

function foo() {
  console.log('foo')
  setTimeout(bar(), 0)
  baz()
}

foo()
  1. foo() 가 호출 스택에 먼저 들어간다
  2. foo() 내부에 console.log가 존재하므로 호출 스택에 들어간다
  3. 2의 실행이 완료된 이후에 다음 코드로 넘어간다
  4. bar()가 호출 스택에 들어간다
  5. bar() 내부에 console.log가 존재하므로 호출스택에 들어간다
  6. 5의 실행이 완료된 이후에 다음 코드로 들어간다
  7. 더 이상 bar()에 남은 것이 없으므로 호출 스택에서 제거된다
  8. baz()가 호출 스택에 들어간다
  9. baz() 내부에 console.log가 존재하므로 호출 스택에 들어간다
  10. 9의 실행이 완료된 이후에 다음 코드로 넘어간다
  11. 더 이상 baz()에 남은 것이 없으므로 호출 스택에서 제거된다
  12. 더 이상 foo()에 남은 것이 없으므로 호출 스택에서 제거된다
  13. 이제 호출 스택이 완전히 비워준다
이벤트 루프(Event Loop) 의 역할은 호출 스택(Call Stack) 이 비어 있는지 확인하는 것이다.
호출 스택이 비어 있으면 태스크 큐(Task Queue) 에서 대기 중인 콜백(작업)을 꺼내와 실행한다.
"코드 실행"과 "호출 스택 확인"은 모두 하나의 싱글 스레드 위에서 순차적으로 일어난다.

 

🌚비동기 작업은 어떻게 실행될까?

function bar() {
  console.log('bar');
}
function baz() {
  console.log('baz');
}
function foo() {
  console.log('foo');
  setTimeout(bar, 0);
  baz();
}
 
foo();
  1. foo() 가 호출 스택에 먼저 들어간다
  2. foo() 내부에 console.log가 존재하므로 호출 스택에 들어간다
  3. 2의 실행이 완료된 이후에 다음 코드로 넘어간다
  4. setTimeout(bar(), 0)가 호출 스택에 들어간다
  5. 4번에 대해 타이머 이벤트가 실행되며 태스크 큐로 들어가고, 그 대신 바로 스택에서 제거된다
  6. baz()가 호출 스택에 들어간다
  7. baz() 내부에 console.log가 존재하므로 호출 스택에 들어간다
  8. 7의 실행이 완료된 이후에 다음 코드로 넘어간다
  9. 더 이상 baz()에 남은 것이 없으므로 호출 스택에서 제거된다
  10. 더 이상 foo()에 남은 것이 없으므로 호출 스택에서 제거된다
  11. 이제 호출 스택이 완전히 비워졌다
  12. 이벤트 루프가 호출 스택이 비워져 있다는 것을 확인했다. 그리고 태스트 큐를 확인하니 4번에 들어갔던 내용이 있어 bar()를 호출 스택에 들여보낸다
  13. bar() 내부에 console.log가 존재하므로 호출 스택에 들어간다
  14. 13의 실행이 끝나고, 다음 코드로 넘어간다
  15. 더 이상 bar()에 남은 것이 없으므로 호출 스택에서 제거된다
위 코드에서 setTimeout(() ⇒ {}, 0) 이 정확히 0초 뒤에 실행된다는 것을 보장하지 못한다.

🌕이벤트 루프

  • 태스크 큐를 한 개 이상 가지고 있음( ※ 태스크 큐: 실행해야 할 태스크의 집합을 의미 )
  • 자료구조의 queue가 아니고 set 형태인데, 그 이유는 선택된 큐 중에서 실행 가능한 가장 오래된 태스크를 가져와야 하기 때문
  • 태스크 큐에서 의미하는 '실행해야 할 태스크'라는 것은 비동기 함수의 콜백 함수나 이벤트 핸들러 등을 의미

🌕이벤트 루프의 역할

  • 호출 스택에 실행 중인 코드가 있는지, 태스크 큐에 대기 중인 함수가 있는지 반복해서 확인하는 것
  • 호출 스택이 비었다면 태스크 큐에 대기 중인 작업이 있는지 확인하고, 이 작업을 실행 가능한 오래 된 것부터 순차적으로 꺼내와서 실행

1.5.3 태스크 큐의 마이크로 태스크 큐

  • 마이크로 태스크 큐는 기존 태스크 큐보다 우선권을 갖는다. (promise)
  • setTimeout과 setInterval은 Promise보다 늦게 실행된다. 
functioni foo() {
	console.log('foo')
}

functioni bar() {
	console.log('bar')
}

functioni baz() {
	console.log('baz')
}

setTimeout(foo, 0)

Promise.resolve().then(bar).then(baz)
예제코드를 실행하면 bar, baz, foo 순으로 실행된다. 확실히 Promise가 우선권이 있다.
각 태스크에 들어가는 대표적인 작업은 아래와 같다.
- 태스크 큐: setTimeout, setInterval, setImmediate
- 마이크로 태스크 큐: process.nextTick, Promises, queueMicroTask, MutationObserver
💊렌더링은 언제 실행될까?  
태스크 큐를 실행하기전 마이크로 태스크 큐를 실행하고, 마이크로 태스크 큐를 실행한 뒤에 렌더링이 일어난다.
각 마이크로 태스크 큐 작업이 끝날 때마다 한 번씩 렌더링할 기회를 얻게 된다.

1.5.4 정리

자바스크립트 코드를 실행하는 것 자체는 싱글 스레드로 이루어져서 비동기를 처리하기 어렵지만 자바스크립트 코드를 실행하는 것 이외에 태스크 큐, 이벤트 루프, 마이크로 태스크 큐, 브라우저/Node.js API 등이 적절한 생태계를 이루고 있기 때문에 싱글 스레드로는 불가능한 비동기 이벤트 처리가 가능해진 것이다!

'Study > 모던 리액트 Deep Dive' 카테고리의 다른 글

모던 리액트 Deep Dive - 타입 스크립트  (1) 2025.09.23
모던 리액트 Deep Dive - 자주 사용되는 자바스크립트 문법  (0) 2025.09.23
모던 리액트 Deep Dive - 클로저  (1) 2025.09.15
모던 리액트 Deep Dive - 클래스  (0) 2025.09.15
모던 리액트 Deep Dive - 함수  (0) 2025.09.15
'Study/모던 리액트 Deep Dive' 카테고리의 다른 글
  • 모던 리액트 Deep Dive - 타입 스크립트
  • 모던 리액트 Deep Dive - 자주 사용되는 자바스크립트 문법
  • 모던 리액트 Deep Dive - 클로저
  • 모던 리액트 Deep Dive - 클래스
happy_dev
happy_dev
복사하고 붙여넣기 잘하고 싶어요
  • happy_dev
    happy의 개발일지
    happy_dev
  • 전체
    오늘
    어제
    • 전체 (43)
      • Java (0)
      • React (1)
      • DB (1)
      • Study (41)
        • 친절한 SQL 튜닝 (9)
        • 모던 리액트 Deep Dive (18)
        • 젠킨스로 배우는 CI,CD 파이프라인 구축 (14)
        • Studyd (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    toad
    젠킨스
    인덱스의기본
    Jenkins
    리액트
    oracle
    DB
    SQL
    조인
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
happy_dev
모던 리액트 Deep Dive - 이벤트 루프와 비동기 통신의 이해
상단으로

티스토리툴바