JavaScript의 동작 원리

Youn·2021년 6월 5일
1

WEB

목록 보기
4/4
post-thumbnail

JS - 싱글스레드로 동작하는 언어

[동기 = 싱글스레드]

  • 한번에 하나의 작업을 수행

[비동기 = 멀티스레드]

  • 하나의 작업을 수행하며 그동안 다른 작업을 수행
  • 스레드가 여러개 진행되고 있음

자바스크립트는 싱글스레드이고 하나의 콜스택을 가지고 있음

❓❓

console.log("1");
setTimeout(console.log, 5000, "2");
console.log("3");
  • 싱글스레드이기 때문에 1 -> 2 -> 3 순서로 출력돼야 함
  • 실제 결과값은 1 -> 3 -> 2 순서임
  • 이와 같은 현상이 가능한 이유는??

자바스크립트 엔진

  • Javascript 코드를 읽고 해석해서 실행하는 것을 담당하는 일종의 인터프리터(컴파일과는 대조되는 개념)
  • 가장 유명한 엔진은 구글의 V8엔진 (크롬과 노드js 에서 사용)

메모리힙(Memory Heap)

  • 메모리 할당이 일어나는 곳
  • 객체, 배열, 함수와 같이 크기가 동적으로 변할 수 있는 참조타임 값 저장

콜스택(Call Stack)

  • 코드 실행에 따라 스택 프레임이 쌓이는 곳

  • 현재 동작하고 있는 함수, 함수 내 동작하는 함수, 다음에 호출되어야 하는 함수 등을 제어

  • LIFO, 후입 선출

  • 자바스크립트는 단일 콜스택을 가지고 있으므로 싱글스레드라 불림

  • Run-to-completion - 다른 함수가 실행되고 있을 때는 종료 직전까지 다른 작업이 중간에 끼어들 수 없음

  • 스택프레임 - 콜스택의 각각을 부르는 용어

  • 스택트레이스 - 예외가 발생했을 때 콜스택의 상태

  • 스택날림 - 콜 스택의 치대크기에 다다랐을 때

  • 동작 예시

function multiply(x, y) {
    return x * y;
}
function printSquare(x) {
    var s = multiply(x, x);
    console.log(s);
}
printSquare(5);


자바스크립트 런타임(동작환경)

  • 자바스크립트 엔진을 '구동하는 환경', 즉 브라우저나 Node.js에서는 여러 개의 스레드가 사용됨
  • 자바스크립트가 비동기적으로 동작할 수 있는 이유는 자바스크립트는 자바스크립트 엔진으로만 돌아가는 것이 아니기 때문
  • 자바스크립트 엔진 밖에서 자바스크립트 실행에 관여하는 요소 존재
    • Web API
    • Task Queue (Callback Queue)
    • Event Loop

WebAPI

  • 자바스크립트 엔진 밖에서 동작하는, 웹 브라우저에 내장된 API
  • 자바스크립트 엔진에서 정의되지 않았던 setTimeout이나 HTTP 요청 메서드(AJAX), DOM 이벤트 등의 메서드를 지원하는 별도의 쓰레드
    • AJAXsetTimeOut 등의 비동기 작업 실행
  • 위에서 정의한 Javascript Engine의 스택에서 실행된 비동기 함수는 작업에 대한 정보와 콜백 함수 를 Web API에게 전달

Task Queue(Callback Queue)

  • Event 실행 관리를 위해 사용되는 Queue (FIFO 구조)
  • Web API를 통해 쌓인 비동기적으로 실행되는 callback 함수를 보관하는 공간
    • 비동기 콜백(asynchrounous callback) - Web APIs, ES6의 Promise
  • 자바스크립트 비동기 작업의 종류는 Task 이외에도 Microtask Queue, Animation Frames 등 다른 Queue도 존재함
    • Microtask Queue
      • ECMA에선 PromiseJobs라는 내부 큐(internal queue)를 명시. V8 엔진에선 이를 '마이크로태스크 큐(microtask queue)'라고 부르기 때문에 이 용어가 좀 더 선호함
      • process.nextTick, Promise, Object.observe, MutationObserver 등이 존재함
    • Animation Frames
      • requestAnimationFrame과 같은 함수가 존재
  • setTimeout 함수는 일정시간 이후 즉시 실행되는 함수가 아닌, Call Stack과 Task Queue의 상황이 고려해야하는 최소 일정 시간의 delay를 보장하는 함수라고 표현할 수 있음

Event Loop

  • 계속 반복해서 Call Stack과 Queue 사이의 작업들을 확인하고, Call Stack이 비어있는 경우 Queue에서 꺼내어 Call Stack에 적재하는 과정수행
    • 위의 작업을 틱(tick)이라고 함
    • tick 을 반복
  • 이때, 위에서 Queue는 크게 3개로 나누어진다고 정의하였는데 Microtask Queue → Animation frames → Task Queue 순으로 우선순위를 두어 작업을 가져감!
    • setTimeoutPromise가 각각 Queue에 존재할경우 Microtask Queue인 Promise가 더 빨리 실행
  • Node.js는 비동기 IO를 지원하기 위해 libuv 라이브러리를 사용하며, 이 libuv가 이벤트 루프를 제공
  • 이벤트 루프를 통해 비동기 작업이 수행되며 동시성이 구현될 수 있음!

동작 예시

시뮬레이션 보기

console.log("Hi!"); // 1번

const timeout = () => console.log("5 Seconds Later"); // 2번

setTimeout(timeout, 5000); // 3번

console.log("Hello!"); // 4번


참고
https://velog.io/@jwlee134/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%9D%98-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC
https://www.notion.so/dooking/9c35f66df98e4ca1ba29afaf69ef7726
https://velog.io/@graphicnovel/JS-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC
https://hudi.kr/%EB%B9%84%EB%8F%99%EA%B8%B0%EC%A0%81-javascript-%EC%8B%B1%EA%B8%80%EC%8A%A4%EB%A0%88%EB%93%9C-%EA%B8%B0%EB%B0%98-js%EC%9D%98-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC-%EB%B0%A9%EB%B2%95/

profile
youn

0개의 댓글