안녕하세요.
여러분들은 어떤 개발 환경 위에서 웹 개발을 하시나요?
오늘은 deno라는 비교적(?) 신기술에 대해 소개를 시켜 드리려고 합니다.
deno?
deno logo
deno는 Deno는 V8 JavaScript 엔진 및 Rust 프로그래밍 언어를 기반으로하는 JavaScript 및 TypeScript 용 런타임입니다.
더 간단하게 설명하면 node.js와 비슷한 무언가(?) 라고 설명할 수 있을 거 같습니다.
개발한 사람도 node.js를 개발했던 Ryan Dahl
이라는 사람입니다.
왜 잘만 쓰이는 node.js를 버리고 새 기술을 익혀야 하느냐 한다면 node.js에 설계상 문제점이 있었기 때문입니다.
node.js의 설계상 문제점
Ryan Dahl
은 2018년 Node.js에 관해 후회하는 10가지라는 주제로 강연을 하면서 node.js의 문제점을 밝혔습니다.
- Promise 문제
node.js에서는 아래와 같이 callback형식을 기본으로 비동기 호출을 하게 됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
step1(function (value1) {
step2(function (value2) {
step3(function (value3) {
step4(function (value4) {
step5(function (value5) {
step6(function (value6) {
// Do something with value6
});
});
});
});
});
});
딱 보기에도 정말 머리가 어지러워 지는 모습입니다.
더군다나 순차처리가 계속되어야 할 경우 더욱 더 높은 산을 쌓을 수 밖에 없는 구조입니다.
사실 callback 함수 기반의 처리는 node.js가 처음 개발 되었을 당시에는 몰라도 현재는 너무 오래된 구식 방법입니다.
아직도 쓸 수는 있지만 ES6 이후 promise와 async/await 이 만들어 진 뒤로는 훨씬 괜찮은 방법이 생겼죠.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// promise
step1()
.then(() => {
return step2
})
.then(() => {
return step3
})
.then(() => {
return step4
})
// async
async function foo() {
let value1 = await step1();
let value2 = await step2();
let value3 = await step3();
let value4 = await step4();
}
하지만 node.js는 callback API를 위해 비동기 처리 자체의 노후화와 async 도입을 늦추는 결과를 가져오게 됩니다.
- 보안을 고려하지 않음
사실 이건 큰 문제가 되지 않는다고 생각합니다. 다른 환경에서도 동일한 문제가 있기 때문이죠.
하지만 Ryan Dahl
은 node.js에게 너무 많은 권한을 준 것에 대해 후회한다고 했습니다.
- 빌드 시스템
node.js는 GYP라는 오래된 Chromium 기반 빌드 시스템을 가지고 있습니다.
GYP를 처음 들어보신 분들이라고 패키지 설치할 때 아래 에러 로그는 한번쯤 봤을겁니다.
1
2
3
4
5
6
7
8
9
10
11
gyp ERR! find Python
gyp ERR! find Python Python is not set from command line or npm configuration
gyp ERR! find Python Python is not set from environment variable PYTHON
gyp ERR! find Python checking if "python" can be used
gyp ERR! find Python - "python" is not in PATH or produced an error
gyp ERR! find Python checking if "python2" can be used
gyp ERR! find Python - "python2" is not in PATH or produced an error
gyp ERR! find Python checking if "python3" can be used
gyp ERR! find Python - "python3" is not in PATH or produced an error
gyp ERR! find Python checking if the py launcher can be used to find Python 2
...
이 빌드 시스템은 매우 오래됐고 느리며, 심지어 Chromium에서도 더이상 쓰지 않습니다.
- 패키지 시스템
여러분들은 node.js를 사용하면서 npm을 사용해 본 적이 있으실 겁니다.
이 npm에도 문제가 많은데 간단히 말하자면 아래 세 가지 문제가 있었습니다.
- 모든 모듈이 npm 생태계에서만 배포될 수 있음. (너무 npm에 의존적임)
- 패키지의 구조 자체가 라이센스, README.md 파일 등 까지 포함되는 구조이기에 과도하게 무거움.
- 모듈 시스템의 알고리즘이 지나치게 복잡함.
- node.js에서 모듈을 불러올 때 편리함을 위해 너무 많은것을 희생함
node.js에서 모듈을 불러올 때 .js를 빼거나 심지어는 디렉터리까지만 입력해도 되는 부분은 코드를 작성하는 입장에서는 무척이나 편리한 기능이었습니다.
다만 그런 어찌보면 필수 기능이 아닌 것들을 구현하기 위해 node.js는 너무 무겁고 복잡해져버렸습니다.
deno에서는 이런 속도와 편리함을 맞바꾼 기능들을 과감히 버렸습니다.
더욱 가볍고 빠른 실행을 위해서였죠.
deno의 특징
deno는 아래와 같은 특징이 있습니다.
- CommonJS에 대한 지원 중단. ES6 문법만 지원
node.js 개발자들은 require
와 module.exports
라는 구문을 본 적이 있을겁니다.
이는 CommonJS라는 모듈화 표준이었죠.
그러나 ES6 이후로는 Javascript에서도 모듈화 표준이 생겼습니다. import
와 export
가 바로 그것이죠.
이런 표준의 파편화를 없애기 위해 CommonJS를 과감히 버렸다고 할 수 있습니다.
- URL(원격)이나 Path(로컬)로 모듈 로딩. package.json 사용 안함
앞서 npm에 종속적인 생태계 문제를 해결하기 위해 deno에서는 URL로 import가 가능해졌습니다.
아래와 같이 말이죠.
1
2
import { serve } from "https://deno.land/std@0.161.0/http/server.ts";
serve(req => new Response("Hello World\n"));
또한 위의 import가 매번 외부 모듈을 가져오지도 않습니다. 최초 1회 로드된 모듈은 캐시되어 local에서 직접 import 됩니다.
- 모든 비동기 함수는 promise를 반환함
네. 더이상 callback 지옥에서 허덕일 필요가 없어졌습니다!
- 파일, 네트워크, 환경(변수) 접근에 대해 명시적으로 권한설정 필요
파일이나 네트워크 연결이 필요할 경우 아래와 같이 명시적으로 권한을 주어야 합니다.
1
2
3
4
$ deno run --allow-read --allow-net main.ts
# 아래와 같이 모든 권한을 허락 할 수도 있습니다.
$ deno run -A main.ts
- 내장 타입스크립트 지원
deno는 typescript를 기본적으로 지원합니다. 따로 컴파일 할 필요도 없이 말이죠!
- 단일 실행파일로 배포 가능
지금까지 node.js는 디렉토리 단위로 배포되었습니다. 모듈도 예외는 아니었죠.
deno에서는 단일 실행 파일의 형태로 컴파일할 수 있습니다.
이 좋은걸 왜 아직 많이 쓰지 않는가
위 내용만 보았을 때는 node.js보다 월등히 좋은 차세대 런타임이라고 생각할법 합니다.
하지만 아직까지 node.js를 대체하지 못하는 결정적인 단점들이 존재합니다.
- npm과 호환되지 않음
deno가 출시된지 1년이 넘은 지금까지도 생태계의 발전이 지지부진한 이유 중 하나라고 할 수 있습니다.
기존 npm에 비해 deno의 생태계는 아직까지 너무 작습니다.
다만 이 문제는 시간이 해결해 줄 문제라고 생각합니다.
- deno의 성능
Deno benchmark 사이트를 보면 아직 deno의 처리 가능한 요청 수가 현저하게 적습니다. (물론 큰 문제는 되지 않습니다.)
하지만 deno 팀은 이를 점진적으로 개선해 나갈것이라고 했습니다. 반면 레이턴시의 경우 node.js보다 매우 빠른 것도 장점으로 볼 수 있습니다.
- TSC 병목 현상
Deno는 내부적으로 MicroSoft사에서 제작한 TypeScript compiler를 타입 체킹에 사용하고 있습니다. 이는 Chromium V8 엔진에 비해 현저하게 느립니다.
물론 이 부분은 점차 개선해 나가고 있습니다. 최근엔 v8-snapshot을 이용하여 조금이나마 개선 되었습니다.
- 아직 미구현된 기능들
Deno는 아직 Production에서 사용하기에 많이 불안정합니다.
특히 파일 입출력, http, FFI 등 미구현되거나 unstable상태인 기능들이 무척 많습니다.
TODO
이번 시간에는 Deno에 대해 알아보는 시간을 가졌습니다.
사실 구현한 모습까지 보여드리고 싶었으나, 너무 길어질 것 같아 다음 시간에 나머지 이야기를 해보도록 하겠습니다.