자바스크립트 들어가기

FAST FOX·2025년 7월 10일

About. JavaScript

목록 보기
1/10
post-thumbnail

1. 개요

자바스크립트를 사용해서 개발을 시작한지 꽤 오랜 시간이 지났지만 결과적으로는 자바스크립트의 동작원리도 모르고 각종 메소드들이 가지고 있는 알고리즘도 모른체 그냥 기능을 외워서 기계처럼 찍어내고 있었다.
덮어놓고 지나가면 더 이상의 발전도 없고 문제점만 깊어질거라고 생각해서 멘토님과 상의 후에 자바스크립트 이론책을 하나 잡고 학습을 하기로 했다.
이 시리즈는 내가 공부한 내용들과 기존에 의미없이 사용했던 코드에서 새롭게 알게된 내용들을 정리하는 내용들이 담길 것이다.
공부한 내용들은 You dont know JS yet이라는 책으로 공부한 내용들이다.

2. 자바스크립트의 배경 지식

2-1. 이름의 유래

개발을 접하게 되면 들어보는 이름 중 자바스크립트와 비슷한 자바라는 언어도 듣게된다. 나도 처음에는 이 둘이 뭔가 관계성이 있을거라 생각했고 나중에도 관계가 없다고 듣기만 했지 구체적으로는 알지 못했다.
짧게 정리해보자면 자바스크립트와 자바는 별개의 언어는 맞지만 C 혹은 C++과 유사한 문법을 기대하는 개발자를 위해 만들어졌기 때문에 문법적으로 비슷한 구석이 있다. 기존에 무거운 언어였던 자바 개발자들을 타겟팅해서 자바스크립트가 만들어졌고 마케팅 목적으로 당시 가벼운 프로그램이라는 뜻으로 유행했던 스크립트자바에 붙여서 자바스크립트라는 이름이 탄생하게 된 것이다.

이후에도 인수합병과 같은 법률적 문제가 있었고 일각에서는 JS라는 약어를 사용하기도 하며 공식화된 명칭으로는 ECMAScript 혹은 ES 뒤에 개정년도를 붙여 ESxxxx이라고도 부릅니다. 현재 블로그를 작성하는 2025년에는 6월에 개정안이 발표되어 ES2025라고 부를 수도 있을 거 같다.

2-2. JS와 웹

JS의 실행 영역은 브라우저, 서버, 로봇 등 굉장히 다양해지고 있다. 하지만 그 중 가장 큰 비중을 차지하는건 역시 이라고 할 수 있고 웹이 JS에 미치는 영향이 얼마나 큰지 알아보면 TC39라는 JS 기술 관리 위원회에서 작성한 명세서를 웹에 맞춰서 철회하는 경우들이 발생한다.
명세서가 작성되기 위해서는 최소 몇개월에서 몇년이 걸리기도 하며 한 번 발표된 개정안을 수정하는 일은 역사적으로도 굉장히 드물기 때문에 이는 웹이 JS에 미치는 영향이 얼마나 큰지 알 수 있다.

또한 브라우저 기반 JS엔진이 명세서를 준수할 가능성이 없는 경우에는 명세서 부록 B (Additional ECMAScript Features for Web Browsers)에 명세서와 실제 웹에서 돌아가는 JS의 차이를 상세하게 기록해두고 다른 환경은 명세서를 반드시 준수하도록 한다.

이렇게 JS는 웹에 많은 비중의 기준이 맞춰져 있지만 미래를 위해서 특정 JS엔진에 종속되지 않으면서 명세서(부록 B 제외)를 준수하는 구현체를 사용하도록 하는게 좋다.

2-3. JS와 웹 전용 문법

웹 사용 비중이 높은 만큼 JS 명세서에는 적혀있지 않지만 웹에서는 마치 JS처럼 인식되는 문법이 많이 있다. 대표적으로 alert()함수와,console.*메서가 있다. 브라우저 엔진, Node.js 등과 같이 JS가 실행되는 환경이 전역 스코프에 API를 추가해 자체적으로 사용할 수 있는 기능을 제공하는 것이다.
이런 문법들은 JS의 함수와 객체 메서드 규칙을 따르기 때문에 JS처럼 보이지만 엄격히 말해서 표면상 JS 문법 규칙을 준수해야 하기 때문에 JS가 아니라 웹 전용 문법이라고 보는게 맞다.

연장선으로 개발을 하면 필수적으로 사용하게되는 개발자 도구가 있다. 이 개발자 도구 역시 위와 같이 개발자 경험을 우선시 하기 때문에 JS의 프로그램 처리 방식을 엄격하게 준수하지 않는다는 것을 항상 인지하고 그 결과가 JS 문법을 정확히 지키더라도 너무 신뢰해서는 안될 것이다.

2-4. 패러다임

우선 패러다임이라는 말의 의미를 나는 잘 몰랐다. 보통 새롭고 놀라운 것을 소개할 때 '혁신적인 패러다임'이라고 소개하는걸 봐서 느낌적으로는 알지만 정확한 의미를 모르는 것이었다.
프로그래밍 분야에서 패러다임은 코드를 어떻게 구조화할지에 대한 접근방식사고방식을 의미한다.
패러다임 자체가 굉장히 다양하고 또 그 안에서 변형이 무수히 많이 존재하는데 대표적인 프로그래밍 패러다임으로는 절차적, 객체 지향, 함수형이 있다.

1. 절차적 패러다임

  • 개념 : 코드가 상태 변화와 순차적 흐름에 중점을 두고 톱다운 그리고 선형적으로 구성된다.
  • 대표 언어 : C
  • 대표 라이브러리/프레임워크 : glibc, NCurses, SDL

2. 객체 지향 패러다임

  • 개념 : 데이터를 객체(클래스)로 묶고 객체 간의 상호작용으로 프로그램을 구성한다.
  • 대표 언어 : 자바, C++
  • 대표 라이브러리/프레임워크 : Spring, Django

3. 함수형 패러다임

  • 개념 : 부수 효과가 없는 순수 함수로 코드를 구조화한다. 또한 함수 자체가 값으로 취급된다.
  • 대표 언어 : 자바스크립트, 파이썬, 하스켈
  • 대표 라이브러리/프레임워크 : Ramda, Lodash-fp

내가 사용하는 언어인 자바스크립트는 함수형 패러다임에 속하고 다양한 패러다임을 사용해 코드를 구조화할 수 있는 다중 패러다임 언어이다.

2-5. 하위 호환성과 상위 호환성

우선 각 단어의 의미부터 알아보자.

  • 하위 호환성 : 단 한 번이라도 JS문법이라고 인정되면 명세서가 변경되더라도 그 유효성이 깨지지 않는다. 1995년에 작성한 코드를 현시점에서 동작시켜도 문제없이 작동된다.
  • 상위 호환성 : 새로운 명세서에 추가된 문법으로 코드를 작성했을 때 구형 JS엔진에서 문제가 발생하지 않는다. 최신 문법에 따라 작성한 코드를 구현 브라우저에서 실행하면 망가지지 않는다.

JS가 어떤 특징을 가지는지 결론부터 말하자면 하위 호환성을 가지고 있다. 그렇기 때문에 브라우저 버전이 업데이트 되어도 우리가 작성한 코드는 깨지지 않는다는 믿음을 가지고 작성할 수 있는 것이다.

반대로 상위호환성을 가진 HTML과 CSS로 최신 기능을 구현하고 구형 브라우저에서 실행한다면 브라우저가 인식 불가능한 HTML과 CSS는 건너뛰고 인식 가능한 HTML과 CSS는 명세서에 따라 처리하기 때문에 망가지지는 않는 것이다.

자바스크립트가 하휘호한성을 띌 수 밖에 없는 이유가 있다. HTML이나 CSS는 상호간 최소한의 영향을 미치면서 건너뛰는게 상대적으로 간편하지만 프로그래밍 언어를 처리하는 엔진이 이해할 수 없는 구문이나 표현식을 선택적으로 건너 뛰었을 때는 프로그램에 문제가 생기고 혼란이 발생하기 때문이다.

2-5-1. 호환성 문제 극복

1. 트랜스파일을 사용한 방법

위에서 말했던 것과 같이 JS는 상위 호환성을 보장하지 않기 때문에 최신 문법을 사용한 코드를 옛날 엔진에서 실행했을 때 프로그램이 멈추는 상황을 마주할 수 있다.
이러한 문제를 해결하기 위해서 트랜스파일을 이용한다. 트랜스파일의 정의는 한 형태에서 다른 형태로 소스 코드를 변환해주는 것을 의미하며 결과물 역시 소스 코드로 나오게 된다.

예시 코드를 보면

if (true) {
	let x = 3;
   	console.log(x);
} else {
	let x = 4;
  	console.log(x);
}

위와 같은 조건문을 트랜스파일한면 아래와 같은 소스 코드가 출력된다.

var x$0, x$1; //변수 x$0와 x$1 선언
if (true) {
	x$0 = 3; // x$0에 정수 3을 할당.
  	console.log(x$0);
} else {
	x$1 = 4; // x$0에 정수 4을 할당.
  	console.log(x$1);
}

차이점은 ES6부터 사용된 letvar로 대체했으며 var의 경우 변수 선언의 유효 범위가 블록 수준을 넘기 때문에 두 개의 변수를 따로 선언하게 되었다.

어떻게 보면 비효율적인 과정일 수도 있는 트랜스파일을 진행하면서도 최신 문법을 사용하는 이유는 당연하게도 양질의 깜끔하고 의도한 바를 정확히 전달할 수 있는 코드를 작성하기 위함이다.

2. 폴리필을 사용한 방법

트랜스파일이 최신 문법을 과거 문법으로 변경해서 문제를 해결하는 방법이라면 폴리필은 사용하고자 하는 메서드 정의를 추가해 원래 있었던 것처럼 해주는 방법이다.
바벨과 같은 트랜스파일러는 작성된 코드에서 폴리필이 필요한 코드는 찾아내서 자동으로 폴리필을 추가하지만 그렇지 않은 경우에 개발자가 직접 작성해야한다.
폴리필을 사용하기 위해서는 가급적 공신력이 있는 ES-shim과 같은 폴리필을 사용하는 것이 좋지만 이해를 돕기 위해서 finally()를 가지고 예시를 들어보자.

let pr = getSomeRecords(); //Promise를 반환하는 함수 선언

startSpinner(); // startSpinner 함수 실행

pr
.then(renderRecords) //동작이 성공했다면 결과 값 출력
.catch(showError) //실패했다면 에러 출력
.finally(hideSpinner) //성공,실패 여부와 상관없이 spinner 종료

만약 finally()를 지원하지 않는 브라우저 엔진을 사용한다면 finally()를 대체하는 구조를 추가해주면 된다.

if (!Promise.prototype.finally) { // Promise에 finally가 존재하지 않는다면
  	Promise.prototype.finally = function f(fn){ // 새롭게 finally를 선언, fn()은 상시 실행 함수인 hideSpinner
      return this.then( // 성공과 실패 두 경우를 나누기 위해서 각각 t()와 c()를 사용
        function t(v){ // 성공의 경우, 위에 renderRecors와 동일
          return Promise.resolve( fn() )
          	.then(function t(){
            	return v;
          	});
        },
        function c(e){ // 실패의 경우, 위에 showError와 동일
          return Promise.resole( fn() )
          	.then(funtion t(){
            	throw e;
          	})
        }
      );
    };
}

이렇게 폴리필을 작성해주면 finally 메서드 구현 여부에 따라서 if문을 뛰어넘거나 실행되어서 폴리필이 작동한다.

2-6. 인터프리터와 컴파일러, 자바스크립트는 어떤 언어?

자바스크립트는 어떤 언어인지 알아보기 전에 인터프리터와 컴파일러의 차이에 대해서 간단하게 알아보자.

  • 인터프리터 : 프로그래밍 언어의 소스 코드를 한 줄씩 읽어 바로 실행하는 프로그램 또는 환경
  • 컴파일러 : 프로그래밍 언어로 작성된 소스 코드를 컴퓨터가 이해하고 실행할 수 있는 기계어로 변환하는 프로그램 또는 환경

위의 정의와 같이 인터프리터 언어는 작성한 언어를 한 줄씩 읽어 내려가면서 실행되는 방식이고 컴파일러 언어는 파싱이라는 전처리가 존재하고 컴파일 단계까지 끝나면 실행하는 방식이다.

그럼 이제 자바스크립트가 어떤 언어에 가까운지 알아보자.
기존에 자바스크립트는 인터프리터 언어에 가깝다고 했지만 현대의 자바스크립트 엔진들은 실행 속도를 높이고 안정성을 높이기 위해서 JIT(Just In Time) 컴파일러 기술을 도입했다.
JIT 컴파일러 기술이란 파싱을 통해서 AST(추상 구문 트리)를 생성하고 컴파일을 통해서 컴퓨터가 이해할 수 있는 바이트 코드로 변환해준다. 여기서 기존의 컴파일 언어와의 차이점이 있는데 기존 컴파일 언어는 생성된 바이트 코드를 포터블 파일 형태로 생성하지만 JIT 컴파일러는 바이트 코드가 포터블 파일 없이 생성됨과 동시에 JSVM(JS virtual machine)에 전달되어 실행 및 최적화 된다는 차이가 있다.

결과적으로 관점에 따라서 자바스크립트를 인터프리터 언어로 보기도, 컴파일 언어로 보기도 하지만 코드 실행 전에 정정 오류를 미리 발견할 수 있다는 점에서 컴파일 언어에 가깝다고 생각할 수 있다.
참조 : V8엔진에서 자바스크립트 실행 방법

profile
준비하는 개발자

0개의 댓글