현대 Javascript 생태계에 있어서 빠지지 않고 등장하는 것이 무엇일까
react 개발이든, nodejs를 이용한 next.js, express.js든 어떠한 코드를 작성을 한다면 결국 js엔진이 읽을 수 있게끔 컴파일 하는 과정이 필요하다.
우리가 컴파일러를 알아야 하는 이유는 무엇일까?
실제 개발하면서 사용한 Bable의 AST 구문 해석 및 순환에 대해 정리해보자 한다.
위와 같은 코드가 있다고 하자.
위 코드는 현재 typescript이지만, 트랜스파일링과 관련된 의존성들을 번들링 하기 전에는 위와 같은 모양이지만 번들링을 한다면 어떤 모양이 될까?
나는 위 코드가 18만줄 js 배포하기글에 나온 이유로 번들링을 한 이후에 사용자에게 보내주어야한다.
즉, 파라미터를 통한 어떠한 조작을 할 수 없다. 그리고 어떤 식으로 변환될지 예상할 수 없다.
처음에 나는 아래와 같은 선택을 했다.
터미널에서 선택한 값을 이용해, 사용자의 터미널에서 번들링된 JS를 파싱해 사용자에따라다른지역입니다
를 찾아서 바꿔주면 되는 것 아닐까?
실제로 구현했을때, 잘 동작했다. 하지만 위와 같은 방식은 문제가 생길 수 있다.
나는 저 함수를 사용자의 터미널 입력을 받아서 region을 넣어주어야한다.
위 코드는 실제로 잘 동작한다.
하지만 아래와 같은 문제가 있다.
region: 사용자에따라다른지역입니다,
//이렇게 바뀐다면?
region:사용자에따라다른지역입니다,
//혹은
region:
사용자에따라다른지역입니다
,
위와 같은 상황에서는 정규식에서 요구하는 조건을 만족할 수 없다.
그래서 아래와 같은 방식을 사용했다.
단순 문자열이 아니라 구문
자체를 파싱한다면 어떨까? region:사용자에따라다른지역입니다
<- 이 코드 자체를 찾아서 치환해준다면 미래에 고려하지 못할 다른 변수들을 차단할 수 있다.
구문 자체를 해석하는 방법은 AST를 이용하면 된다.
AST란 무엇일까?
function sum(a,b){
return a+b
}
위와 같은 코드가 있다고 해보자, javascript는 이를 어떤 식으로 해석할까?
위의 JS코드는 내 코드에서는 babel에 의해 아래와 같은 AST(Abstract Syntax Tree)로 변환된다.
이 AST 구문으로 변환하는 과정은 언제언제 쓰일까? 내 코드의 흐름을 읊어보자
AST
로 파싱AST
를 생성AST는 뗄레야 뗄 수 없는 개발자의 필수적인 기본 소양인 셈이다. AST는 코드 주변 어디에나 있다.
그렇다면 나는 이걸 어디에 이용할 수 있을까? Identifier를 순회하면서 updateInfoFunction라는 Identifier안에 parameter가 key가 region이면서 value가 사용자에따라다른지역입니다
인 Identifier가 있다면, 이를 바꿔주면 되지 않을까?
위 코드에서 transformEnv의 파라미터는 아래 두 가지다.
parse를 통해 javascript 코드를 AST구문으로 바꿔주고, traverse를 통해 바꿔준 AST 구문을 순회하며 원하는 값을 찾아낸다.
원하는 값을 찾아냈다면 Identifier 자체를 바꿔준 후, 원래 js코드로 바꿔준다.
처음엔 단순한 문자열 파싱이었는데 어떻게 하다 보니 babel과 컴파일러가 어떻게 동작하는지
안정성을 위해서는 어떠한 기술들을 사용할 수 있는지에 대해 많은 것을 알게 되었다.
코드 -> AST구문 -> 코드라는 과정이 어떻게 보면 비효율적일 수 있지만, 중요한 것은 유지보수성이지 않을까 생각한다.
만약 내가 문자열 파싱으로 코드를 작성했다면 저 코드는 지금 나만 알고 있지만, 누군가 나중에 저 함수의 파라미터를 임의로 변경했을때(정말 단순한 스페이스바 한 스푼이어도), 어디서 무엇이 일어나는지, 왜 이게 이렇게 바뀌는지 모를 가능성이 높다.
누구나 내 코드를 만지게 되었을 때, 불필요한 사이드 이펙트를 발생시키지 않을 만한 코드를 작성하는 것이 중요하지 않을까?