자바스크립트는 컴파일 과정 없이 브라우저 내부의 자바스크립트 처리기(인터프리터)에 의해 바로 실행됩니다. 개발이 발전함에 따라 컴파일 과정이 가능해졌으며, Node.js를 이용해 서버 환경을 구축할 수 있게 되었습니다.
웹 페이지는 HTML, CSS, JS 세 가지 코드가 결합되어 작성됩니다. 자바스크립트는 다음과 같은 다양한 역할을 수행합니다:
-
사용자의 입력 및 연산: 키, 마우스 등의 입력과 연산은 자바스크립트로만 처리 가능합니다.
-
웹 페이지 내용 및 모양의 동적 제어: HTML 태그의 속성이나 콘텐츠, CSS 속성 값을 변경하여 웹 페이지에 동적인 변화를 일으킬 수 있습니다.
-
브라우저 제어: 브라우저 윈도우의 크기나 모양 변경, 새 윈도우나 탭 열기, 다른 웹 사이트 접속, 브라우저의 히스토리 제어 등 브라우저의 작동을 제어합니다.
-
웹 서버와의 통신: 웹 페이지가 웹 서버와 데이터를 주고받을 때 활용됩니다.
-
웹 애플리케이션 작성: 자바스크립트 언어로 활용할 수 있는 많은 API를 제공하여, 웹 브라우저에서 실행되는 다양한 웹 애플리케이션을 개발할 수 있습니다.
Node.js는 자바스크립트 코드 실행에 필요한 런타임으로, V8 엔진을 사용합니다. 자바스크립트 런타임에 필요한 이벤트 루프 및 운영체제 시스템 API를 사용하는 데는 libuv 라이브러리를 사용합니다.
- 애플리케이션에서 요청이 발생하면, V8엔진은 자바스크립트 코드를 바이트 코드 혹은 기계어로 변경합니다.
- 자바스크립트로 작성된 Node.js의 API는 C++로 작성된 코드로 사용됩니다.
- V8 엔진은 이벤트 루프가 필요하기 때문에 libuv를 사용하고 전달된 요청을 libuv의 이벤트 큐에 추가합니다.
- 이벤트 큐에 쌓인 요청은 이벤트 루프에 전달되고, 운영체제 커널에 비동기 처리를 요청합니다. 운영체제 내부적으로 비동기 처리가 힘든 경우(DB, 네트워크 통신, 파일 처리 등)는 워커 쓰레드에서 처리합니다.
- 운영체제의 커널 혹은 워커 쓰레드가 완료한 작업은 다시 이벤트 루프로 전달됩니다.
- 이벤트 루프에서 콜백으로 전달된 요청에 대해 완료 처리 후 V8로 넘깁니다.
- 완료 처리된 응답은 애플리케이션으로 전달됩니다.
Node.js는 싱글 쓰레드, 즉 콜 스택을 1개 가지고 있습니다. 하지만, 1개의 콜 스택으로는 마지막 작업이 앞에 있는 작업을 모두 기다려야하기 때문에, libuv에 있는 이벤트 루프로 보냅니다.
- V8의 콜 스택에 쌓인 뒤 I/O 처리가 필요한 코드는 이벤트 루프로 보냅니다.
- 이벤트 루프에서 처리될 작업을 태스크 큐에 담습니다.
- 태스크 큐에 있는 작업을 이벤트 루프로 보내서 루프를 실행하고 운영체제 또는 쓰레드 워커에서 I/O 처리를 진행합니다.
- 쓰레드 워커와 운영체제는 받은 요청에 대한 결과를 이벤트 루프로 다시 돌려줍니다.
- 이벤트 루프에서는 결과값에 대한 코드를 콜 스택에 다시 추가합니다.
운영체제의 비동기 I/O 기능을 사용하거나, 쓰레드 풀을 사용해서 모든 작업을 비동기로 처리합니다. 여러 큐를 사용해서 특정 우선순위대로 작업들을 처리해줍니다.
- 이벤트 루프의 시작 및 각 반복의 마지막에 루프가 활성화 상태인지 체크합니다.
- 타이머 단계에서 타이머 큐를 처리하며, 이 때
setTimeout()
,setInterval()
을 처리합니다
- 이벤트 루프의 시작 및 각 반복의 마지막에서 루프가 활성화 상태인지 체크합니다.
- 타이머 단계에서 타이머 큐를 처리하며, 이 때
setTimeout()
,setInterval()
을 처리합니다. 타이머가 실행되는 순서는 프로세스의 퍼포먼스에 따라 달라질 수 있습니다. - 펜딩(pending) I/O 콜백 단계에서는 다음 반복으로 연기된 콜백을 처리합니다.
- 유휴, 준비 단계를 통해 다음 폴 단계의 준비를 내부적으로만 진행합니다.
- 폴 단계에서는 새로운 연결(소켓 맺기, 파일 읽기, DB 커넥션 생성하기 등) 작업을 진행합니다. 각 작업은 쓰레드 풀을 사용합니다.
- 검사 단계에서는 폴 단계의 성공 실패 여부를 판단하고 이를
setImmediate()
로 처리합니다. I/O 사이클에 스케줄링 되었다면,setTimeout()
보다setImmediate()
가 항상 먼저 실행됩니다. - 종료 콜백 단계에서는 콜백의 종료 처리(파일 닫기, 커넥션 종료 등)를 합니다.
- 각 단계 사이마다
nextTickQueue
와microTaskQueue
에 있는 작업이 먼저 실행됩니다.process.nextTick()
함수를 통해nextTickQueue
에 작업을 추가할 수 있고, 이벤트 루프가 진행되기 전에 에러를 핸들하며 필요 없는 자원을 해제 및 재요청 처리까지 가능합니다.microTaskQueue
에는 Promise로 만든 콜백 함수가 추가됩니다.
자바스크립트 코드를 작성할 수 있는 위치는 다양합니다. 각 위치에 따라 자바스크립트 코드의 실행 시점과 방식이 달라질 수 있습니다.
-
HTML 태그의 이벤트 리스너 속성에 작성
HTML 태그에는 마우스 클릭, 키보드 입력 등의 이벤트가 발생할 때 처리하는 코드를 등록하는 이벤트 리스너 속성이 있습니다. 예를 들어, 자바스크립트에서는
this
를 사용하여 현재 요소를 참조할 수 있습니다. -
<script></script>
태그 안에서 작성<script>
태그는<head>
나<body>
내부, 또는 body 태그 바깥 어디에든 위치할 수 있습니다. 이 태그 내부에 자바스크립트 코드를 직접 작성할 수 있습니다. -
.js 자바스크립트 파일에 작성
자바스크립트 코드를
.js
확장자를 가진 별도의 파일로 저장하고,<script src=".js경로"></script>
를 사용하여 HTML 문서에 가져올 수 있습니다. -
URL 부분에 작성
<a>
태그의href
속성에 자바스크립트 코드를 작성할 수 있습니다. 이 경우,href
속성 값 앞에javascript:
라는 키워드를 붙여야 합니다.
식별자(identifier)는 자바스크립트에서 변수, 상수, 함수에 붙이는 이름입니다. 식별자를 만들 때는 다음 규칙을 준수해야 합니다:
- 첫 번째 문자: 알파벳, 언더바(
_
),$
문자만 사용 가능 - 두 번째 문자 이상: 알파벳, 언더바(
_
),0-9
,$
사용 가능 - 대소문자 구분:
data
와dAta
는 다른 식별자입니다. - 키워드(예약어) 사용 불가
문장은 세미콜론(;
)으로 구분합니다. 한 줄에 한 문장만 있는 경우 세미콜론을 생략할 수 있습니다.
i = i + 1
j = j + 1;
k = k + 1; m = m + 1;
n = n + 1 p = p + 1 // (X)
- 한 줄 주석:
//
를 사용하여 코드 뒤에 주석을 추가할 수 있습니다. - 범위 주석:
/* */
를 사용하여 여러 줄에 걸친 주석을 추가할 수 있습니다.
자바스크립트에서 사용할 수 있는 주요 데이터 타입은 다음과 같습니다:
- 숫자 타입(
number
): 예)42
,3.14
- 논리 타입(
bool
): 예)true
,false
- 문자열 타입(
string
): 예)"안녕"
,"하세요"
,"35"
,'a'
,"A"
- 객체 레퍼런스 타입(
object
): 예)Object
,Array
,Math
,Date
undefined
: 타입이 정해지지 않은 것을 의미합니다.null
: 값이 정해지지 않은 것을 의미합니다.
변수를 선언하는 키워드와 그 특성은 다음과 같습니다:
var
키워드: 함수의 영역만을 스코프로 판단합니다.let
키워드: 블록({}
)을 스코프로 판단합니다.
const
키워드: 상수를 선언하며, 한번 할당된 값을 변경할 수 없습니다.
변수의 사용 범위(scope)에 따라 다음과 같이 구분됩니다:
- 전역변수(
global
): 함수 밖에서 선언된 변수로, 어디서든 접근 가능합니다. - 지역변수(
local
): 특정 영역(함수, 블록) 안에서 선언된 변수로, 해당 영역 내에서만 접근 가능합니다.