JavaScript · 1장 소개
자바스크립트는 어디서 어떻게 돌아갈까
자바스크립트는 웹 페이지를 움직이게 하려고 태어나, 지금은 서버와 앱과 개발 도구까지 돌리는 언어가 됐어요. 이 글에서는 코드 한 줄이 엔진 안에서 어떻게 실행되는지, 브라우저 안에서 무엇을 할 수 있고 무엇이 막혀 있는지 차례로 살펴봐요.
01. 설치 없이 바로 실행되는 언어
자바스크립트는 브라우저만 있으면 바로 실행돼요. 따로 무언가를 설치하거나 실행 파일을 만드는 과정이 없어요. 아래 블록도 지금 이 글을 보고 있는 브라우저 안에서 돌아가요. ▶ 실행을 눌러 보고, 문자열이나 숫자를 바꿔서 다시 실행해 보세요.
const language = 'JavaScript';
const year = 2026;
console.log(language + '로 ' + year + '년에 첫 줄을 실행했어요');
console.log(typeof language, typeof year); // string number
이 언어는 1995년 넷스케이프(Netscape) 브라우저에 넣으려고 만들어졌어요. 이름에 Java가 들어가지만 Java와는 다른 언어예요. 당시 인기 있던 Java의 이름을 빌려 붙였을 뿐이에요. 지금은 Ecma International이라는 표준 단체가 ECMAScript라는 이름으로 언어 규칙을 정하고, 해마다 새 판을 내요. 명세를 읽는 법은 명세와 레퍼런스에서 다뤄요.
02. 엔진: 코드를 실행하는 프로그램
자바스크립트 코드를 받아서 실제로 실행하는 프로그램을 엔진이라고 불러요. 브라우저마다 엔진이 하나씩 들어 있고, 브라우저 밖에서 자바스크립트를 돌리는 프로그램들도 이 엔진을 가져다 써요.
| 엔진 | 만든 곳 | 쓰는 곳 |
|---|---|---|
| V8 | Chrome, Edge, Opera, Node.js, Deno | |
| SpiderMonkey | Mozilla | Firefox |
| JavaScriptCore | Apple | Safari, Bun |
엔진이 하는 일은 크게 세 단계예요. 먼저 코드를 읽어서(파싱) 문법에 맞는지 확인하고 다루기 쉬운 구조로 바꿔요. 그다음 그 구조를 곧바로 한 줄씩 실행해요. 그리고 실행하는 동안 어떤 함수가 자주 불리는지 지켜보다가, 많이 쓰이는 함수는 CPU가 바로 이해하는 기계어로 다시 번역해서 훨씬 빠르게 돌려요.
자주 쓰는 코드만 골라서 다시 번역해요
처음부터 모든 코드를 기계어로 번역하면 페이지가 열릴 때까지 오래 걸려요. 반대로 끝까지 한 줄씩 해석만 하면 반복이 많은 코드가 느려요. 그래서 엔진은 일단 빨리 시작하고, 자주 쓰이는 부분만 나중에 공들여 번역하는 방식을 써요. 이렇게 실행 도중에 번역하는 것을 JIT(Just-In-Time, 그때그때) 컴파일이라고 해요.
최적화된 기계어는 "이 함수에는 늘 숫자가 들어온다" 같은 가정 위에서 만들어져요. 그런데 갑자기 문자열이 들어오면 가정이 깨지니까, 엔진은 최적화된 코드를 버리고 느린 길로 되돌아가요(탈최적화). 같은 함수에 같은 종류의 값을 넣는 습관이 성능에 도움이 되는 이유예요. 다만 이건 엔진이 알아서 하는 일이라, 처음 배울 때는 "엔진이 이렇게 일하는구나" 정도로만 알아 두면 충분해요.
03. 브라우저 안에서 할 수 있는 일
브라우저 속 자바스크립트는 페이지와 사용자 사이에서 일해요. 할 수 있는 일을 몇 가지 꼽아 보면 이래요.
- 페이지의 글자 · 모양 · 구조를 바꾸고, 새 요소를 만들거나 지워요.
- 클릭 · 키 입력 · 스크롤 같은 사용자 행동에 반응해요.
- 페이지를 새로 고치지 않고 서버와 데이터를 주고받아요.
- 브라우저 안에 작은 데이터를 저장해 두고 다음 방문 때 꺼내 써요.
- 사용자가 허락하면 카메라 · 마이크 · 위치 같은 기기 기능을 써요.
예를 들어 페이지 제목의 글자를 바꾸는 코드는 한 줄이면 돼요. 이런 화면 관련 기능은 2부에서 자세히 다뤄요.
// 페이지의 첫 번째 h1 글자를 바꿔요 (브라우저 콘솔에서 해 보세요)
document.querySelector('h1').textContent = '제목이 바뀌었어요';
이 코드는 이 글의 실행 블록에서는 동작하지 않아요. 실행 블록은 페이지를 건드리지 않도록 페이지와 분리된 공간에서 코드를 돌리기 때문이에요. 브라우저의 콘솔에서 직접 실행하는 법은 개발자 콘솔에서 알려 드려요.
04. 브라우저가 막아 두는 일 (샌드박스)
웹 페이지는 누구나 만들 수 있고, 링크 하나만 눌러도 열려요. 그래서 브라우저는 페이지의 자바스크립트를 샌드박스(sandbox, 모래 놀이터)라는 울타리 안에 가둬요. 울타리 안에서는 마음껏 움직여도 되지만, 사용자의 컴퓨터나 다른 사이트에는 함부로 손댈 수 없어요.
컴퓨터의 파일
페이지의 자바스크립트는 하드 디스크의 파일을 마음대로 읽거나 프로그램을 실행할 수 없어요. 읽을 수 있는 건 사용자가 직접 골라서 건네준 파일뿐이에요. 파일 선택 창에서 고르거나, 파일을 페이지 위로 끌어다 놓은 경우가 그래요.
다른 출처의 페이지
브라우저는 출처(origin)가 다른 페이지끼리 서로의 내용을 읽지 못하게 해요. 이 규칙을 동일 출처 정책이라고 불러요. 출처는 프로토콜 + 도메인 + 포트 세 가지로 정해지고, 셋 중 하나라도 다르면 다른 출처예요.
| 주소 | https://shop.example.com과 비교 |
|---|---|
https://shop.example.com/cart | 같은 출처 (경로만 달라요) |
http://shop.example.com | 다른 출처 (프로토콜이 달라요) |
https://shop.example.com:8443 | 다른 출처 (포트가 달라요) |
https://blog.example.com | 다른 출처 (도메인이 달라요) |
이 규칙 덕분에, 쇼핑몰 탭과 메일 탭을 같이 열어 두어도 쇼핑몰의 코드가 메일 내용을 엿볼 수 없어요.
다른 서버와 통신하기
페이지는 자기를 보내 준 서버와는 자유롭게 데이터를 주고받아요. 다른 출처의 서버에도 요청을 보낼 수는 있지만, 응답을 읽으려면 그 서버가 "이 출처는 읽어도 된다"는 허락 표시를 응답에 붙여 줘야 해요. 이 약속을 CORS(교차 출처 리소스 공유)라고 해요. 허락은 페이지가 아니라 상대 서버가 정해요.
https://shop.example.com에서 열린 페이지의 자바스크립트가 아래 일을 하려고 해요. 각각 되는지, 막히는지 골라 보세요.
- (가) 사용자가 파일 선택 창에서 고른
receipt.pdf의 크기를 읽기 - (나) 사용자의 바탕화면에 있는
memo.txt를 몰래 읽기 - (다)
https://shop.example.com/api/items에서 상품 목록 받아 오기 - (라) 같은 브라우저 다른 탭에 열린
https://bank.example.org의 잔액 글자 읽기 - (마)
https://api.example.net에 요청을 보내고 응답 읽기
해답 보기
(가) 돼요 — 사용자가 직접 건넨 파일이에요. (나) 막혀요 — 사용자가 고르지 않은 파일은 읽을 수 없어요. (다) 돼요 — 같은 출처예요. (라) 막혀요 — 다른 출처 페이지의 내용은 읽을 수 없어요.
(마)는 상대 서버에 달려 있어요. 요청은 보낼 수 있지만, api.example.net이 응답에 shop.example.com을 허락하는 CORS 표시를 붙여 줘야 응답을 읽을 수 있어요.
05. 브라우저 밖의 자바스크립트
엔진은 브라우저에서 떼어 내 다른 프로그램에 넣을 수도 있어요. 그래서 지금은 자바스크립트가 브라우저 밖에서도 많이 쓰여요. 브라우저 밖에서는 샌드박스 제한이 없어서, 서버 프로그램이 파일을 읽고 쓰는 것도 자연스러운 일이에요.
| 어디서 | 무엇으로 |
|---|---|
| 서버 · 명령줄 도구 | Node.js, Deno, Bun |
| 데스크톱 앱 | Electron (예: VS Code가 이걸로 만들어졌어요) |
| 모바일 앱 | React Native |
자바스크립트로 바뀌는 언어들
자바스크립트가 어디서나 돌아가다 보니, 다른 언어로 쓰고 자바스크립트로 바꿔서 실행하는 방법도 널리 쓰여요. 가장 많이 쓰이는 건 TypeScript예요. 자바스크립트 문법에 "이 값은 숫자예요" 같은 타입 표기를 더한 언어로, 코드를 실행하기 전에 실수를 잡아 줘요. 이 밖에 Dart, Kotlin, Elm 같은 언어도 자바스크립트로 바꿔서 브라우저에서 돌릴 수 있어요.
// TypeScript — 매개변수 뒤의 : number가 타입 표기예요
function area(width: number, height: number): number {
return width * height;
}
타입 표기를 지우면 그대로 자바스크립트가 돼요. Node.js는 23.6 · 22.18 버전부터 이렇게 타입 표기만 지우고 .ts 파일을 바로 실행할 수 있어요(타입 검사는 따로 해야 해요). 타입이 없으면 어떤 일이 생기는지 아래에서 실행해 보세요.
function area(width, height) {
return width * height;
}
console.log(area(3, 4)); // 12
console.log(area('가로', 4)); // NaN — 숫자가 아닌 값이 들어왔어요
자바스크립트는 area('가로', 4)를 오류 없이 실행하고 NaN(숫자가 아님)을 돌려줘요. TypeScript였다면 실행하기 전에 "숫자 자리에 문자열을 넣었어요"라고 알려 줬을 거예요. TypeScript는 자바스크립트를 충분히 익힌 뒤에 배우는 게 좋아요. 결국 실행되는 건 자바스크립트이니까요.
참고로 WebAssembly라는 것도 있어요. C · Rust 같은 언어로 만든 프로그램을 브라우저에서 빠르게 돌리기 위한 별도의 형식이고, 자바스크립트를 대신하기보다는 자바스크립트와 함께 쓰여요.
정리
- 자바스크립트는 설치 없이 브라우저에서 바로 실행되고, 표준 이름은 ECMAScript예요.
- 엔진(V8 · SpiderMonkey · JavaScriptCore)이 코드를 읽고 실행하며, 자주 쓰는 코드는 기계어로 다시 번역해 빠르게 돌려요.
- 브라우저 속 자바스크립트는 샌드박스 안에서 돌아서, 사용자가 고르지 않은 파일과 다른 출처 페이지의 내용에는 손댈 수 없어요.
- 다른 출처 서버의 응답은 그 서버가 CORS로 허락해야 읽을 수 있어요.
- Node.js 같은 환경 덕분에 서버 · 앱에서도 쓰이고, TypeScript처럼 자바스크립트로 바뀌는 언어도 있어요.