에니메이션 프레임

60FPS = 1초에 60개의 프레임.

하나의 프레임은 1000ms / 60 = 16.67ms

약 16.67ms 마다 하나의 프레임이 처리된다.

requestAnimationFrame(() => {
  // 16.67ms마다 실행 (60fps 기준)
});

requestAnimationFrame 콜백은 등록되면 다음 프레임 주기의 시작 시점에 실행된다.

setTimeout(() => {
  console.log("1");
}, 50);

requestAnimationFrame(() => {
  console.log("3");
});

Promise.resolve().then(() => {
  console.log("4");
});

console.log("5");

for (let i = 0; i < 10000000; i++) {
  JSON.parse('{ "test": "test" }');
}
  • 50ms 이후 1번 로그가 Macro Queue 에 적재된다.
  • 3번 로그는 다음 프레임 시작 부분에 실행된다.
  • 4번 로그는 Micro Queue 에 적재된다.
  • 동기 코드 5번 로그가 콜 스택에 적재되고 바로 실행된다.
  • JSON.parse() 루프가 바로 실행되며 메인 스레드가 블로킹된다.
  • 콜 스택이 비워진 시점에 이벤트 루프에 의해 4번 로그가 실행된다.
  • 1번 로그는 50ms 가 훨씬 지난 시점이므로 즉시 실행할 수 있다.
  • 만약 블로킹이 프레임 경계라면 3번 로그가 다음 프레임 시작 부분에서 출력되고 1번 로그가 출력된다.
  • 반대로 프레임 경계가 아니라면 1번 로그가 먼저 출력되고 3번 로그는 마지막에 출력될 수 있다.

프레임 상황에 따라 다르게 출력된다.

  • 5 → 4 → 3 → 1
  • 5 → 4 → 1 → 3