자바 스크립트

08.Algorithm 2020. 6. 1. 15:39
728x90
반응형
  • 목차
  • 들어가기
  • 머릿말
  • 개요
  • 자바스크립트 엔진
  • 런타임
  • 호출 스택(Call Stack)
  • 동시성(Concurrency) & 이벤트 루프(Event Loop)
  • 참고

 

 

개요

아마 모든 분들이 V8 엔진에 대해서 들어봤을 겁니다. 대부분 자바스크립트가 싱글 쓰레드 기반이고 콜백 큐를 사용한다는 걸 알거에요.

이 글에서는 방금 말씀드린 개념들에 대해서 더 자세히 알아보고, 어떻게 자바스크립트가 동작하는지 파헤쳐 볼거에요. 글을 다 읽고 나면 자바스크립트 내장 API를 효율적으로 사용하는 non-blocking 앱을 구현할 수 있을겁니다.

 

자바스크립트 엔진

자바스크립트 엔진의 대표적인 예는 Google V8 엔진입니다. V8 은 Chrome과 Node.js에서 사용합니다. 아래는 엔진의 구조도를 간단히 나타낸 그림입니다.

 

 

엔진의 주요 두 구성요소는

  • Memory Heap : 메모리 할당이 일어나는 곳
  • Call Stack : 코드 실행에 따라 호출 스택이 쌓이는 곳

런타임

거의 모든 자바스크립트 개발자들이 setTimeout 과 같은 브라우저 내장 API를 사용합니다. 하지만, 이 API를 자바스크립트 엔진에서 제공하지는 않습니다.

그럼 얘네들은 대체 어디서 오는 걸까요? 사실 현실은 좀 더 복잡합니다.

 

 

 

위 그림처럼, 자바스크립트 엔진 이외에도 자바스크립트에 관여하는 다른 요소들이 많습니다. DOM, Ajax, setTimeout 과같이 브라우저에서 제공하는 API 들을 Web API라고 합니다. 그리고 아래쪽에 이벤트 루프와 콜백 큐도 있네요.

호출 스택(Call Stack)

자바스크립트는 기본적으로 싱글 쓰레드 기반 언어입니다. 호출 스택이 하나라는 소리죠. 따라서 한 번에 한 작업만 처리할 수 있습니다.

호출 스택은 기본적으로 우리가 프로그램 상에서 어디에 있는지를 기록하는 자료구조입니다. 만약 함수를 실행하면(실행 커서가 함수 안에 있으면), 해당 함수는 호출 스택의 가장 상단에 위치하는 거죠. 함수의 실행이 끝날 때(리턴 값을 돌려줄 때), 해당 함수를 호출 스택에서 제거합니다. 그게 스택의 역할입니다.

아래 예제 코드를 살펴볼까요.

function multiply(x, y) {

return x * y;}function printSquare(x) {

var s = multiply(x, x);

console.log(s);}printSquare(5);

JsCopy

처음 엔진이 이 코드를 실행하는 시점에는 호출 스택이 비어있습니다. 하지만 코드가 실행되면서 호출 스택은 아래와 같이 변합니다.

 

호출 스택의 각 단계를 스택 프레임(Stack Frame)이라고 합니다.

그리고 보통 예외가 발생했을 때 콘솔 로그 상에서 나타나는 스택 트레이스(Stack Trace)가 오류가 발생하기까지의 스택 트레이스들로 구성됩니다. 간단히 말해서 에러가 났을 때의 호출 스택의 단계를 의미하는 거죠.

아래 코드도 살펴봅시다.

function foo() {

throw new Error('SessionStack will help you resolve crashes :)');}function bar() {

foo();}function start() {

bar();}start();

JsCopy

위 코드가 foo.js 에 있다고 하고 크롬에서 실행하면

 

 

호출 스택이 최대 크기가 되면 “스택 날려 버리기” 가 일어납니다. 이는 반복문 코드를 광범위하게 테스트하지 않고 실행했을 때 자주 발생합니다. 아래 코드를 보시면

function foo() {

foo();}foo();

JsCopy

엔진에서 이 코드를 실행할 때, foo()에 의해서 foo 함수가 호출됩니다. 그런데 여기서 foo 함수가 반복적으로 자신을 다시 호출하는 재귀 호출을 수행합니다. 그러면 매번 실행할 때마다 호출 스택에 foo() 가 쌓이게 됩니다. 아래와 같이 말이죠.

 

 

그러다가 특정 시점에 함수 호출 횟수가 호출 스택(Call Stack)의 최대 허용치를 넘게 되면 브라우저가 아래와 같은 에러를 발생시킵니다.

 

싱글 스레드 기반 코딩은 멀티 스레드 환경에서 제기되는 복잡한 문제나 시나리오를 고민하지 않아도 되기 때문에 상당히 쉽습니다. 예를 들면, 데드락 같은 게 있겠죠.

허나 싱글 스레드에서 코드를 실행하는 건 상당히 제약이 많습니다. 한 개의 호출 스택을 갖고 있는 자바스크립트의 실행이 느려지면 어떻게 될까요?

 

동시성(Concurrency) & 이벤트 루프(Event Loop)

호출 스택에 처리 시간이 어마어마하게 오래 걸리는 함수가 있으면 무슨 일이 발생할까요? 예를 들어, 브라우저에서 자바스크립트로 매우 복잡한 이미지 프로세싱 작업을 한다고 합시다.

이게 대체 어때서? 라고 의문이 생길지도 모르지만, 여기서 문제는 호출 스택에서 해당 함수가 실행되는 동안 브라우저는 아무 작업도 못하고 대기 상태가 된다는 겁니다. 이 말뜻은 브라우저는 페이지를 그리지도 못하고, 어느 코드도 실행을 못한다는 거죠. 말 그대로 그냥 가만히 있는 겁니다. 만약 매끄럽고 자연스러운 화면 UI를 가진 앱을 원한다면 위 경우는 문제가 됩니다.

문제는 이뿐만이 아닙니다. 브라우저가 호출 스택의 정말 많은 작업들을 처리하다 보면 화면이 아마 오랫동안 응답하지 않게 됩니다. 이 경우에 대부분의 브라우저가 아래와 같은 에러를 띄우면서 페이지를 종료할 건지 물어봅니다.

 

절대 이상적인 사용자 경험은 아니죠. 맞나요?

자 그렇다면 어떻게 페이지 렌더링 동작을 방해하지 않고 브라우저의 응답도 끊지 않으면서 연산량이 많은 코드를 실행할 수 있을까요? 정답은 바로 비동기 콜백 입니다. 비동기 콜백 관련 내용은 V8 엔진에서 최적화 코드 짜는 5가지 팁 에서 자세히 다룰 예정입니다.

 

 

 

메모리 생명주기

  • 메모리 할당(allocate): 프로그램이 사용할 수 있도록 운영체제가 메모리를 할당합니다. 저수준 언어(예를 들어 C)에서는 이를 개발자가 명시적으로 처리해줘야 합니다. 그러나 고수준 언어에서는 개발자가 신경쓸 필요 없습니다.
  • 메모리 사용(use): 이제 할당된 메모리를 실제로 프로그램이 사용하는 단계입니다. 개발자가 코드 상에서 할당된 변수를 사용함으로써 읽기 쓰기 작업이 이루어집니다.
  • 메모리 해제(release): 프로그램에서 필요하지 않은 메모리 전체를 되돌려주어 다시 사용가능하게 만드는 단계입니다. 메모리 할당 작업과 마찬가지로 저수준 언어에서는 이를 명시적으로 처리해야 합니다.

 

가비지컬렉션(garbage collection)

 

자바스크립트에서는 무언가(객체, 문자열 등)가 생겨날 때 메모리가 할당되며 이들이 더 이상 사용되지 않을 때는 ‘자동으로’ 메모리가 반환

 

메모리 참조

가비지 컬렉션 알고리즘이 의존하고 있는 주요 개념은 참조(reference)입니다.

 

https://engineering.huiseoul.com/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%9E%91%EB%8F%99%ED%95%98%EB%8A%94%EA%B0%80-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B4%80%EB%A6%AC-4%EA%B0%80%EC%A7%80-%ED%9D%94%ED%95%9C-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%88%84%EC%88%98-%EB%8C%80%EC%B2%98%EB%B2%95-5b0d217d788d

자바스크립트는 어떻게 작동하는가: 메모리 관리 + 4가지 흔한 메모리 누수 대처법

How JavaScript works: memory management + how to handle 4 common memory leaks

engineering.huiseoul.com

 

모두 WebGL을 통해 브라우저에서 GPU 가속을 구현 하고 적합한 그래픽 카드가없는 경우 CPU로 폴백

 

Deeplearn.js :  신경 네트워크를 대상으로하는 기능 세트이지만 범용 기계 학습 프레임워크

Propel:  자동 차별화 기능을 제공하는 과학 컴퓨팅을 위한 라이브러리

Gpu.js: GPU에서 JavaScript 함수를 실행할 수있는 편리한 방법을 제공

Brain.js: 오래된 신경망 라이브러리의 연장선이며 하드웨어 가속을 위해 gpu.js를 사용

 

 

 

 

 

https://towardsdatascience.com/gpu-accelerated-neural-networks-in-javascript-195d6f8e69ef

GPU-accelerated Neural Networks in JavaScript

An Overview

towardsdatascience.com

 

728x90

'08.Algorithm' 카테고리의 다른 글

휴리스틱 함수, 휴리스틱 이론  (0) 2020.06.02
영상 특징점 추출  (0) 2020.06.02
타입 스크립트 (Type Script)  (0) 2020.06.01
백트래킹  (0) 2020.06.01
그래프  (0) 2020.06.01
Posted by Mr. Slumber
,