본문으로 바로가기
반응형

 

1. 자바스크립트

 

처음에는 1990년대, 넷스케이프 커뮤니케이션즈사에서 웹 스크립트 언어로 모카(Mocha)라는 이름으로 개발되어 이후 LiveScript로 불렸다가 추후 이름이 JavaScript로 변경되었다.

자바라는 명칭이 들어가서 자바(Java)와 관련이 있지 않느냐는 혼란이 있을 수 있는데 실제 관련은 없다. 당시 자바 인기가 높았고 마케팅적인 이득을 위해 이름을 이렇게 지었다고 한다.
(문법이 비슷해보이는 이유는 모두 C언어가 기반이기 때문이다.)

 

자바스크립트는 '웹 페이지에 동적 기능을 부여하는' 언어이다. HTML 기반 웹 페이지 안에 작성하여 웹 페이지 호출 시 자동으로 실행된다.(HTML, CSS 는 정적인 기능을 담당)

즉, Client 측면에서 동작하는 언어로 웹 페이지의 UI 상에서 발생하는 Event에 대해 어떻게 동작하는지를 디자인할 때 사용하는 언어라고 볼 수 있다.

 

현재에는, 웹 브라우저 상에서만이 아닌 서버에서도 쓰이게 되었고 각종 Application에도 동작할 수 있는 언어로 발전하였다. 

 

 

2. ECMAScript

 

자바스크립트가 성공적으로 자리 잡으며 마이크로소프트에서는 경쟁을 위해 1996년 IE 3.0을 출시하면서 JScript를 발표하는데, 이에 난립하는 상황을 방지하기 위해 표준화가 필요해졌다.

넷스케이프는 표준화를 위해 자바스크립트 기술 규격을 ECMA에 제출하게 되어 1997년 ECMA-262 라는 규격이 생기게 된다.
(※ ECMA는 European Computer Manufacturer's Association이라는 국제 표준화 비영리 기구)

ECMA-262는 하나의 기술 규격이며, 범용 목적의 스크립트 언어에 대한 명세를 담았다. 즉, 이런식으로 언어를 개발하세요 라고 가이드를 명세한 것!

 

ECMAScript는 ECMA-262 표준 규격에 의해 정의된 범용 스크립트 언어이다. ECMAScript는 스크립트 언어가 준수해야 할 규칙/세부 사항/지침을 제공한다. 

즉, ECMA-262는 명세서고 ECMAScript는 스크립트 언어의 기본 베이스 문법이라고 볼 수 있다.

 

자바스크립트는 이 ECMAScript의 사양을 준수하는 범용 스크립팅 언어이다. 자바스크립트는 ECMAScript를 기반으로 개발하였으며 이외에도 여러가지 Script언어들이 ECMAScript의 기준을 따라 개발되었다.
(예 : MS의 JScript, Adobe의 액션스크립트 등)

 

ECMAScript는 규격에 따라 여러 판이 만들어졌는데, 2015년 제 6판이 나오면서 많은 변화가 있었다.

제 6판을 ECMAScript6 혹은 ECMAScript2015라고 부르는데, 이를 줄여서 ES6 또는 ES2015라고도 부르며, 이는 ECMA-262 표준 규격의 제 6판이라고 이해할 수 있다.

2015년의 ES6 / ES2015 부터 뒤에 년도가 붙었는데, 이는 매년 개정하기로 ECMA 측에서 결정한 바에 따른 것이며, 현재는 매년 해당 해의 숫자를 딴 ECMAScript가 발표되고 있다.

 

현재 기준 최신 브라우저들은 ES6 이상의 사양을 모두 준수하여 개발되고 있다.

MS의 IE등 오래된 브라우저와 같은 경우는 해당 사양을 지키지 않고 있으나 현재는 지원이 중단되었으며, Babel(바벨) 이라는 Plugin을 통해 코드를 변경(ES6 → ES5 코드로 변경)하여 호환성을 유지하는 방법도 있다.

 

 

3. 자바스크립트의 특징

 

① 객체(Object) 기반의 스크립트 언어이나 함수형 프로그래밍도 가능
② 주로 웹 브라우저에서 사용하나 Node.js와 같은 Framework를 통해 서버 측 프로그래밍에서도 사용 가능
③ 동적, 타입 명시가 필요 없는 인터프리터 언어

컴파일러(Compiler) 언어 vs 인터프리터(Interpreter)  (+ 스크립트 언어)

컴파일러 언어 인터프리터 언어
Runtime 이전에 전체를 목적 코드로 변환
(Assembly어로 변환, 바뀐 코드를 목적 코드(Object Code)라고 부름, 목적 코드를 Binary 코드로 변환하여 실행됨)
Runetime 이후에 행 단위로 해석하며 프로그램 구동
변환 속도 느림 번역 속도 빠름
실행 속도 빠름
(변환 이후 하나의 Package로 Binary화 가능)
실행 속도 느림
수정 시마다 재 컴파일 필요(개발 시간 소요) 컴파일 과정이 없이 바로 번역, Runtime 간 수정 가능
문법적 오류 있을 시 실행 불가 문법적 오류 있어도 실행 가능
OS, Build 환경에 종속적 번역을 위한 VM이 있고 해당 VM이 OS 환경 지원하여 플랫폼 종속적이지 않음
C, C++ R, Python, Ruby, Javascript..
하나의 독립적 프로그램 구성 시 사용 이미 존재하는 프로그램 제어 시 보조적으로 사용
대규모 프로그램에 적합 소규모 프로그램에 적합

자바스크립트는 이름에서도 볼 수 있듯, 스크립트 언어이다.
스크립트 언어는 코드 동작 중에 기계어로 번역되는 방식으로 인터프리터 언어 중 하나이다.(컴파일러 스크립트 언어도 있다고 함)
따라서 컴파일링이 불 필요하며, 수정이 빈번한 WEB 개발 등에 매우 유리하다.

 

인터프리터(스크립트) 언어 vs 컴파일 언어 차이 그림으로 알아보기

 

 

4. 자바스크립트 구성요소

 

자바스크립트는 1개의 Core와 2개의 Model로 구성되어 있다. 웹 브라우저의 구성 요소는 모든 것이 객체화되어 있는데 자바스크립트로 이 객체를 제어할 수 있으며 이들은 계층적 관계로 구조화 되어 있다.

객체는 BOM(Browser Object Model)과 DOM(Document Object Model)로 분류할 수 있으며, 나머지는 Core이다.
BOM / DOM은 Window 객체의 속성이다.

 

Window 객체란?

브라우저 전체를 담당하는 객체를 의미하여 모든 객체의 조상이 된다. 따라서 생략하고 바로 함수 호출이 가능하다. 사용자가 자바스크립트로 만든 변수(지역변수 제외) / 함수 또한 모두 Window 객체에 등록된다.

구성 그림은 다음과 같다.

 

Window 함수 예
ⓐ window.close() : 창을 닫는다.
ⓑ window.open() : 새 창을 연다.
ⓒ window.setTimeout(함수, 밀리초) : 몇 초뒤에 함수를 실행시킬 때 사용
ⓓ window.setInterval(함수, 밀리초) : 지정한 초만큼 함수를 반복 실행 시 사용

 

① Core 문법
  - 기본 문법, 데이터 타입, 조건문 등의 Syntax를 갖고 있으며 이 Core는 ECMAScript를 기반으로 한다.

② Core 라이브러리
  - 여러 가지 내장 함수를 의미하며, Math, Date 등 기본적으로 사용 가능한 라이브러리를 의미한다. ECMAScript를 기반으로 한다.

③ DOM
  - Document Object Model. Window 객체의 속성
  - HTML / XML 문서의 프로그래밍 Interface로 문서의 구조화된 표현을 제공하며 프로그래밍 언어가 구조에 접근할 수 있는 방법을 제공하여 문서 구조/스타일/내용을 변경할 수 있도록 돕는다.
  - 즉, 웹 페이지의 문서(태그)를 제어할 수 있는 역할을 하는 것.
  - 예 : Element 제어 / Style(CSS) 제어 / Attribute 제어 / Event 제어 등..

④ BOM
  - Browser Object Model. Window 객체의 속성
  - 브라우저와 관련한 객체를 의미하며, 자바스크립트가 브라우저와 소통하기 위해 만들어진 모델이다.
  - 웹 브라우저 창을 관리할 목적으로 제공되는 객체 모음을 대상으로 하는 모델
  - 아래 내용과 같은 객체들이 있다.

Document HTML 문서 정보를 갖는 객체
navigator 브라우저 / OS에 대한 정보를 갖는 객체
screen 화면에 대한 정보를 갖는 객체(너비/높이/픽셀/컬러 등..)
location 주소에 대한 정보를 갖는 객체(protocol, host, hostname, pathname..)
history 기존 방문 페이지에 대한 정보를 갖는 객체
(뒤로 가기, 앞으로 가기 등 제어 가능)

 

 

5. 자바스크립트 동작 원리

 

① 자바스크립트 엔진

자바스크립트는 상단에서 설명하였듯이, 인터프리터 언어라서 해당 코드를 번역하여 실행할 수 있도록 만드는 엔진이 필요하다.

아래와 같은 엔진들이 있다.

1) V8 : 구글에서 만든 오픈소스 엔진, C++로 개발(구글 Chrome, Android 브라우저에 탑재)
2) Rhino : 모질라 Foundation만든 오픈소스 엔진, 자바로 개발
3) SpiderMonkey : 최초 자바스크립트 엔진. Firefox에서 사용
4) JavaScriptCore : Apple사에서 사파리에 탑재하기 위해 개발
5) 그 외..(KJS, Chakra, Nashorn, JerryScript 등)

가장 대표적인 것은 V8 이며, 이는 Node JS 의 Runtime으로도 사용된다. ECMAScript 규격을 준수하여 작성되었고 독립적 실행이 가능하다.

V8은 자바스크립트 JIT 컴파일러 방식을 사용하여 효율적인 기계어로 코드를 번역하며, 최적화를 위해 내부적으로 인라인 캐싱 등의 기법을 적용하였다.

V8 관련 자세한 내용은 더 상세히 설명해주신 분의 블로그 링크를 참고

 

 

② 엔진의 구성

기본적으로 자바스크립트 엔진은 Heap / Call Stack 로 구성되며 동작은 약간 복잡하다. 아래의 그림을 보자.

하나 하나 이해하면서 넘어갈 수 있게 우선 알아본다.

1) 호출 스택(Call Stack)

자바스크립트는 싱글 Thread 기반 언어라서 호출 스택이 1개이다. 즉, 한 번에 1개의 작업만 처리가 가능하다.

호출 스택은 메모리 공간 중 하나로 함수 실행 시, 현재 프로그램 상에서 실행되고 있는 순서대로 스택에 쌓는 구조를 갖는다. 만약 함수를 호출했으면, 해당 함수가 스택에 쌓이고, 완료되면 호출 스택에서 제거되는 방식이다.

즉, 현재 실행 중인 코드를 Tracking 하는 공간

function a() {
   console.log('a');
}

function b() {
   a();
}

b();

 

위와 같은 코드가 있다면 호출 스택은 아래와 같이 쌓인다고 볼 수 있다.

 

즉, 코드를 한 줄씩 읽어 내려가며 수행할 작업을 밑에서부터 쌓고, 필요 시, 메모리 Heap에서 필요한 내용을 찾아 작업을 수행한다.

위의 각 스택 단계를 스택 프레임(Stack Frame)이라고 부르며, 오류 발생 시의 스택 트레이스에서 쌓인 순서에 따라 단계적으로 표기 된다.

만약 위 스택이 모두 차게 된다면, 즉 허용치를 넘으면 브라우저에서는 console 상에 StackOverFlow 에러를 남기고 스택을 모두 비워버린다.

 

2) 메모리 힙(Memory Heap)

메모리 힙은 정보를 저장하는 공간이다. 현재 실행 중인 코드의 변수/함수의 정보 등을 저장하여 필요할 때, 호출 스택에서 참조하여 사용할 수 있도록 저장한다.

즉, 동적으로 생성되는 객체를 할당하는 곳으로 넓은 메모리 영역을 지칭한다.

 

호출 스택의 코드가 실행되면, 필요에  따라 메모리 공간이 할당되고, 사용한 뒤 사용이 완료되거나 에러 등이 발생하게 되면 공간 할당을 해제하게 된다.

이 작업은 명시적으로 코드로 구현하지 않고, 암묵적으로 내부에서 동작한다.

 

3) Web API

웹 브라우저에서 제공하는 기능이다. 간단한 Element 작업 부터, 복잡한 그래픽 효과 등의 작업이 가능하며, 각종 비동기 처리 작업(Ajax, setTimeout 등) 등도 있다.

참고로, 자바스크립트는 기본적으로 동기식(Synchronous) 언어이다. 즉, 하나의 작업이 실행되는 동안 다른 작업은 하지 못한다.(호출 스택이 1개!)

 

그런데, Ajax, setTimeout 과 같은 비동기 처리가 필요한 경우가 있는데, 이럴 때는 어떻게 처리할까?

자바스크립트는 스택으로 이러한 비동기 처리가 들어가면, 브라우저로 정보/콜백함수를 넘기게 되고 브라우저는 별도의 Thread에 위임하여 진행한 뒤 그 Thread는 완료 후 전달 받은 콜백 함수를 엔진의 콜백 큐에 넣게 된다.

그리고 콜백 큐에 들어간 콜백 함수는 이벤트 루프에 의해 동작을 할 때까지 대기하게 된다.

 

4) 콜백 큐(Callback Queue 또는 Task Queue)

웹 API를 처리하고 있던 Thread에게서 전달 받은 콜백 함수를 FIFO 구조로 저장하는 큐.

여기 저장된 콜백 함수는 스택이 비는 순간 스택에 순서대로 푸시되어 동작하게 된다. 그래서 스택이 계속해서 비어 있지 않은 상황이 이어지게 되면 콜백 함수가 실행되지 못할 수 있다.

 

5) 이벤트 루프(Event Loop)

브라우저에서 제공되는 기능으로 호출 스택이 비어 있는지 여부 / 콜백 큐에 대기 중인 콜백 함수가 기다리고 있는 지 여부를 계속 확인하는 동작을 수행하는 부분.
(이 큐/스택을 확인하는 작업을 틱(Tick) 이라고 부른다.)

이벤트 루프는 대기 중인 콜백 함수가 있다면 호출 스택이 비었을 때, 큐에서 해당 함수를 빼서 스택에 넣어 작업이 실행될 수 있도록 한다.

 

 

③ 동작 방식

지금까지 자바스크립트는 인터프리터 언어이고, 브라우저에서는 그러한 인터프리터(엔진)이 탑재되어 자바스크립트가 동작할 수 있도록 구성된다는 것을 알았다.

그리고, 그 엔진의 내부는 어떠한 것들도 구성되어 있고, 브라우저에서 제공하는 다른 기능들이 있는 것도 확인했다.

 

그렇다면, 본격적으로 이 내용을 기반으로 어떻게 자바스크립트가 동작하는지 알아보자.

일단 2가지 방식의 동작이 있다. 동기식(Synchronous)과 비동기식(Asynchronous).

 

동기식 동작은 다음과 같다.
(기본적으로 상단의 호출 스택 그림과 동일하다.)

1) 인터프리터가 코드를 번역하여 실행될 Line을 호출 스택에 넣는다.(Push)
2) 쌓인 함수의 순서 반대로 실행된다(메모리 힙에 필요 데이터 저장)
3) 실행 완료된 함수는 호출 스택에서 제거(Pop)

 

비동기식 동작(Ajax, setTimeout, 이벤트 핸들러 등)은 다음과 같다.

1) 인터프리터가 코드를 번역하여 실행될 Line을 호출 스택에 넣는다.(Push)
2) 비동기식 API 동작이라면 브라우저의 Web API를 통해 브라우저의 다른 Thread로 위임되며 호출 스택에서 빠진다.(Pop)
3) Web API에서 비동기 동작이 실행되고 콜백 함수는 콜백 큐에 들어간다.(Push)
4) 이벤트 루프에 의해 호출 스택이 비어 있는지 확인되고 비어 있다면 호출 스택에 콜백 함수가 넘어간다(Push)
5) 호출 스택에 들어간 함수가 실행되고 끝나면 호출 스택에서 빠진다.(Pop)

위 과정을 쉽게 이해할 수 있도록 참고할 수 있는 페이지가 있다. 참고

 

비동기식 동작을 이해하기 위해 하나의 예시를 들어보자. 다음과 같은 코드가 있다고 가정하자.

console.log("1");

setTimeout(function ha(){
  console.log('haha');
}, 5000);

console.log("2");

 

 

비동기식 동작 예시

 

⑴ console.log("1") 실행

- 다음 그림과 같이 현재 실행 되는 코드가 호출 스택에 들어간다. 비동기식 동작이 아니므로 호출 스택에 바로 Push된다.
(표현상 코드가 스택에 바로 들어가는 것처럼 되어 있는데 당연히 그건 아니다.. 그림의 이해를 위한 것일 뿐)

 

⑵ console.log("1") 실행 완료

- 다음 그림과 같이 실행 완료된 부분은 호출 스택에서 빠지게 된다.

 

⑶ setTimeout 이벤트 실행

- setTimeout 부분 코드 실행을 위해 우선 호출 스택에 들어간다.

 

⑷ setTimeout 위임

- 비동기식 처리를 위해 다른 Thread로 위임되어 다른 Thread에서 동작한다.

 

⑸ console.log("2") 실행

- 호출 스택이 비었고 콜백 큐도 비어있으므로 바로 다음 코드로 동작

 

⑹ console.log("2") 실행 완료

- 실행 완료된 코드는 호출 스택에서 빠진다.

 

⑺ setTimeout 콜백 함수 콜백 큐 진입

- 콜백 함수는 콜백 큐에 진입하여 이벤트 루프에 의해 감지 되기 시작한다.

 

 

⑻ 콜백 함수 호출 스택으로 이동하여 실행

 

 

⑼ 콜백 함수 실행 완료

 

 

실제 콘솔에는 다음과 같이 출력된 것을 볼 수 있다.

 

참고한 글

https://it-eldorado.tistory.com/86

 

[JavaScript] 비동기 작업의 원리 (JavaScript 엔진, Web API, Task Queue, Event Loop)

JavaScript를 공부하는 사람이라면 한 번쯤은 JavaScript가 단일 쓰레드 기반의 프로그래밍 언어라는 말을 들은 적이 있을 것이다. 그렇다면 setTimeout() 함수로 특정 시간을 기다림과 동시에 다른 코드

it-eldorado.tistory.com

 

https://ljtaek2.tistory.com/129?category=897337 

 

자바스크립트 - 동작 원리

자바스크립트는 싱글 스레드 프로그래밍 언어이다. 싱글 스레드 런타임을 가지고 있다는 의미이다. 이것은 결국 한 번에 하나의 싱글 콜 스택(Call Stack)만을 가지고 있다는 말을 뜻한다. 여기서

ljtaek2.tistory.com

 

https://velog.io/@namezin/javascript-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC

 

javascript 동작 원리

Javascript가 어떻게 해석되고 동작되는지 알아보고자 한다.

velog.io

 

https://joshua1988.github.io/web-development/translation/javascript/how-js-works-inside-engine/

 

자바스크립트의 동작원리: 엔진, 런타임, 호출 스택

(번역) 자바스크립트가 엔진에서 어떻게 돌아가나? 런타임과 호출 스택 해부

joshua1988.github.io

 

반응형