JavaScript 개발자를 위한 스프링, NestJS 에 대해서
제목 : Node.js 의 혼란 속에서 NestJS 가 제시한 질서란
부제목 : 다양한 언어와 프레임워크를 둘러본 시각으로서의 NestJS
이 글을 작성하는 이유
다양한 프로그래밍 언어, C, C++, Java, JavaScript, TypeScript, .. 를 작성하여 프로그램을 제작해 보며,
기존 언어들을 넘기 위해 개발 생산성과 프로그램 성능을 둘 다 잡은 신생 프로그래밍 언어
- Rust
- Go
- Zig
를 살펴보며, 현대식 프로그래밍 언어가 어떤 점을 표방하고 만들었는지 분석하며 보았다.
Rust 는 어떤 느낌이었냐면
Rust 는 Memory Address Borrow 라는 통칭 "메모리 빌림" 에 초점을 두고 있었다.
기존 C, C++ 에서 발생하는 메모리 누수를 원천적으로 차단하기 위해 만들어진 대표적인 언어의 기능이기도 했지만,
Memory Leak 를 막는 기능이 도리어 개발 생산성을 해치는 결과로 이어지기도 한다.
메모리에 관련된 에러 스택은 여타 다른 프로그래밍 언어와 다르기 때문에, 신생 개발자들이 굉장히 힘들어한다.
입문은 굉장히 힘들지만, Rust 에 전문화 된 집단 (유저 그룹) 을 살펴보면,
"모든 것을 Rust 로 재창조하자" 라는 기조가 깔려있다고 볼 수 있다.
Microsoft 에서 TypeScript 컴파일러를 golang
으로 바꾼다고 발표했을 때,
Reddit 에서 "Change Everything to Rust" 라는 댓글이 달렸었는데,
여기에 무수한 반대 댓글이 달렸었던 걸로 기억한다.
Rust 커뮤니티는 "정복자" 의 느낌으로 프로그래밍을 진행하며,
이러한 태도로 인해 다른 언어 커뮤니티에서 견제하고 있다는 것을 알게 되었다.
Zig 는 어떤 느낌이냐면
Rust
가 C++
을 대체하려는 신생 언어의 움직임을 띈다면,
Zig 는 C 언어를 대체할 수 있으면 대체하되, C 와 공존하는 모습을 보인다.
Zig 예찬론자는 아니지만, zig
명령어로 .c
파일을 손쉽게 컴파일 할 수 있는 모습으로 알게 되었다.
기존의 C
언어와 "쉽게" 더불어 사용할 수 있는 모습 또한 보인다. (Rust 도 가능하다)
Rust 는 "메모리를 가지는 주체가 명확" 해야 한다는 컨셉이 있다면,
Zig 는 C
의 방식을 차용하되, 새로운 Tool 객체를 통해 메모리를 생성하고,
코드 작성과 컴파일러를 통해 메모리 누수를 막는 방식으로 개발된다.
Go (golang) 은 어떤 느낌이냐면
Google 에서 만들어진 golang 은, C
의 간편한 버전이라고 볼 수 있다.
그러나, C
, Rust
, Zig
가 메모리를 수동으로 제어하지만,
Go
는 C 의 방식을 차용하되, GC (Garbage Collection) 을 추가했다.
덕분에 개발자는 생성한 동적 주소나 메모리에 대한 관리를 걱정할 필요 없이, 작성하면 된다.
Java 보다는 속도가 빠르나, 메모리를 수동으로 제어하는 언어에 비하면 느리다.
그래도 이 언어는 개발 생산성과 프로그램 최적화를 둘 다 균형있게 잡았기 때문에,
최근 굉장히 트렌디하게 뜨고 있는 언어이다.
너무나도 유명한 TypeScript
가 7.0 버전 이후로부터는 Go
로 트랜스파일링 된다는 이야기가 들렸을 때,
Golang 이 비교적 다른 언어보다는 오래 살아남겠구나 라는 생각이 들었었다.
그래서 NestJS 를 바라보았을 때, 어떤 생각이 드는가?
위에서 "이 글을 작성하는 이유" 에 대해서 길게 작성을 했는데,
앞으로 말할 NestJS 에 대한 시각을 설명하기 위해서 다른 언어에 대한 관찰을 적을 수 밖에 없었다.
"NestJS 에 대해서 본격적으로 이야기 하기 전에,"
이 이야기에 필수적인 JavaScript 와 TypeScript 에 대해서 이야기 하지 않을 수가 없다.
솔직히 나의 의견을 말해보자면
생 초보 개발자로 입문하기 위해 JavaScript
만한 언어가 없다고 생각한다.
물론, JavaScript 가 여타 다른 언어에 비해 얼마나 프로그램의 속도가 느린지 알고 있다.
나는 이것을 극복할 수단으로 wasm
을 적극 도입해야 한다고 생각하는 사람이다.
(wasm
이란, 다른 언어에서 작성되어 어셈블리로 파생된 파일을 의미한다.)
(주로 V8 or NodeJS + JS 로 실행했을 때 계산 부하가 걸리는 부분을 wasm
으로 해결 할 수 있다.)
그리고 JavaScript 는 가장 거대한 유저 커뮤니티를 이루고 있다.
이 말은, 전문가와 초보를 가리지 않고, 사람들이 JavaScript 로 프로젝트를 가장 많이 생성하고 있다는 이야기이다.
(저는 나의 첫 개발 시절은 대학생 시절을, 만약에 이걸 읽고 있는 독자가 계시다면, 첫 개발 당시를 회고해 주시면 됩니다.)
처음 개발을 할 때, C 나, C++ 혹은 Java 로 시작하게 된다.
지금 돌이켜보면,
현재 한국의 개발자 채용 시장이 C 기반이거나, Spring 프레임워크로 인한 Java 사용자가 필요했기 때문일 것이다.
그러나 지금은 상황이 많이 다르다.
국가 차원에서 "코딩" 이라는 단어를 앞세워 화이트칼라의 진입점의 대표격으로 만들기도 했지만,
그보다도 업무 프로세스에 존재하는 Legacy(옛 것) 한 아날로그 방식을 현대화 시키기에 최적화 되었다고 생각한다.
C 기반과 Java 기반은 "시각적으로" 빠르게 프로젝트를 완성하기 어렵다.
규칙에 대한 엄격한 문법이 장벽이 되며, 어려운 외부 프로그램 사용은 전문성을 요구한다.
그러나 JavaScript 를 생각 해 보자.
우리가 작은 프로젝트를 완성하기 위해 "가장 편리한" 언어를 꼽자면 어떤 언어일까?
나는 당연히 JavaScript 를 꼽을 것이다.
컴퓨터 엔지니어도 처음에는 대형 프로젝트로 시작 할 수 없을 것이다.
당연히 작은 프로젝트로 컴퓨터에 대한 감각을 키워가게 되는데,
다양한 언어로 전문화 된 사람이 들어오는 다리가 존재한다면,
현재는 JavaScript
가 그 교두보가 되어 다른 유저 커뮤니티에 뿌려주는 형태가 되었다.
(계산과 AI 는 python
이 교두보가 되었다.)
NestJS 는 먼저 "결론적으로" 말해보자면,
TypeScript 로 작성되는 체계적인 Back-End 프레임워크이다.
이에 대한 의견을 뒷받침하기 위해 나의 시각을 펼쳐본다.
JavaScript 의 막대한 영향력
위에서 언급한 내용은 결국 "요즈음 개발자들은 간단한 웹 페이지 서비스를 만들며 컴퓨터를 배운다" 라고 요약할 수 있다.
아무리 핸드폰 앱이 많고, AI 질문이 대세라지만, 검색 엔진이 더 우위다. (아직은)
검색 엔진으로 Chrome, Edge, Oracle, 등등이 존재한다.
이 엔진은 JavaScript 기반으로 동작한다.
"아주 정확하게 말하자면"
HTML + CSS + JavaScript 로 동작한다.
사람들이 가장 많이 사용하는 "검색 엔진" 에서 사용하는 "동적 언어" 는, JavaScript
이다.
다른 언어로도 물론 웹 제작이 가능하긴 하다. (예를 들면 Rust
or go
or C
, ..)
그러나, 결국엔 JavaScript
로 Glue Code 를 제작하여 "부착" 시켜줘야 한다.
그러니까, 검색 엔진은 JavaScript
와 바이너리 패키지를 인식한다.
JavaScript 를 항상 지금처럼 현대적으로 사용할 수 있었던 것은 아니다.
ES6 버전 (2016 년) 에 발표된 기능들, 기본적인 async
, await
, Promise
등등과 같은
비동기, 동기 스위칭 기능이 발표되며 JavaScript 는 더한 영향력을 얻게 되었다.
하드웨어, JavaScript 에 날개를 달아주다
Low, Middle 수준의 프로그래밍 언어가 각광받았던 이유 중 큰 이유는,
제한된 하드웨어 안에서 원활히 실행할 수 있었기 때문이다.
프로그램을 실행하기 전에 이미 Binary or Assembly 수준으로 파싱된 후 실행되는 프로세스는
파일의 크기를 줄여 줄 뿐만 아니라, 컴파일러 단계에서 일부 코드를 캐싱하여 최적화까지 해 주었다.
프로그래밍 역사는 자주 바뀌기 때문에 어떻게 보면 짧은 시간이지만,
현재 NVM (Node Virtual Machine) 을 실행하기 위해 250MB 정도를 사용하는 것을 보면,
왜 옛날 기기에 데이터를 계산하는 용도로 JavaScript 를 사용하지 않았는지를 알 수 있다.
10 년 정도 이전이라면 최고 등급의 하드웨어라면 무리없이 돌릴 수도 있었겠지만,
일반적인 기기를 생각해 본다면, 이는 하드웨어 낭비라고 충분히 생각 될 수 있다고 판단된다.
그러나, 현재 손 안의 핸드폰 조차도 기본 8GB 메모리를 탑재하는 현재 세상은
그러한 단점은 없는 수준으로 변했다고도 볼 수 있다.
계산 속도의 비약적인 향상과 휘발성 저장소 (RAM) 크기의 성장은 JavaScript 기반의 문제를
충분히 상쇄시켰다.
Interpreter (인터프리터) 언어의 문제로,
이미 작성된 자연어와 비슷한 코드를 미리 Binary, 혹은 Assembly 로 파싱하지 않고,
JavaScript 엔진이 실시간으로 Parsing 하여 번역한다는 문제가 존재했다.
그러나, JIT(Just In Time) 컴파일러를 추가하며 코드의 실행 속도를 높였다.
이 전에는 번역된 코드를 따로 캐싱하지 않고 실행했다는데,
이미 번역된 코드를 캐싱하지 않고 다시 번역해서 사용한다면, 지금조차도 감당이 될까 의문이 든다.
성장한 하드웨어는 주로 웹이라는 도메인에서 활동했던 JavaScript 가
복잡한 데이터 처리와 네트워크 처리에도 사용할 수 있게 해 주었다.
이미 bcrypt
, fetch
와 같은 내장 모듈들은 저수준의 언어로 패키징되어 사용될 수 있지만,
개발자가 이를 이용하여 원하는 Logic 을 처리할 수 있는 수준까지 하드웨어가 발전 한 것이다.
JavaScript 의 확산
웹 도메인을 처리하며 JavaScript 의 전문가 수준까지 도달한 개발자들은 이미 많았을 것이다.
그러나, 주 언어가 JS 였으나, 상대적으로 잘 모르는 Low ~ Middle 수준의 언어를 이용하여
데이터 처리를 구성했을 것이다.
그러나, 이제는 그럴 필요가 없다.
웹 전문가도 Express 라는 라이브러리를 통해 자신이 원하는 대로 Back 로직을 구성할 수 있다.
컴파일 과정에서 디버깅에 약한 JavaScript 의 약점을 보완하기 위해 만들어진 TypeScript 도,
동시에 발전하며 타입 기반의 언어로 탈바꿈시켰다. (컴파일은 아닌 "트랜스파일링")
너무나 거대한 Node Package Manager
통칭 NPM
이라고 부르는 패키지 매니저이다.
우리가 어떠한 언어를 사용하더라도, "의존성"(Dependency) 에 대해서 고려할 수 밖에 없다.
(이는 모든 언어에 대해서 핵심적인 부분이며, 프로젝트를 진행한다면 대부분은 의존성을 사용하게 된다.)
너무나 다양한 외부 의존성 패키지가 NPM 에는 2 백만개가 넘는다.
그만큼 유저들이 쉽게 Registry 에 배포 할 수 있으며, 접근이 가능하다.
이 패키지들은 전 세계의 모든 프로그래밍 언어를 비교해도 넘기 어려운 외부 의존성을 제공한다.
프로젝트 생성 시 npm init
명령어를 통해 간단히 package.json
에 외부 의존성 메타데이터를
작성할 수 있는 파일도 만들 수 있다.
Dependency Installation 과정은 로컬 및 여타 기기에 설치된 npm
전역 모듈을 통해 간단히
명령 및 의존성 관리를 수행 할 수 있다.
NestJS 의 탄생
너무나 빠르게 성장해버린 JavaScript 커뮤니티였을까, Back-End 로직의 컨벤션에 대한
정확한 수립이 어려웠다고 한다.
JS 의 백엔드 대표격 라이브러리 express
를 사용하면 느낄 수 있는게,
정말 내 맘대로 작성해도 상관없다는 느낌을 받았다.
아마 이전에 만들어 본 Back-End 프로그램이 Spring
이었기 때문일 것이다.
물론 express
에서 딱히 성능 문제가 제기되는 경우는 거의 없다.
아마 그 정도의 네트워크 및 계산 부하가 걸린다면,
다른 언어와 연결된 프레임워크 모듈을 새로 생성하여 부착하거나,
Container 관리 프로그램으로 분산시키는 것이 맞을 것이다.
그러나, express
의 자율성은 오히려 팀이나 조직의 프로젝트 프로그램 생성에 장애물이 되었다고 한다.
물론 자체적인 Convention 을 지정하면 상관은 없겠지만,
나의 의견으로, 새로운 인원이 내부 로직을 파악하기 위해 걸리는 시간이 많이 소요 될 것이다.
따라서, NestJS 를 만든 분은 TypeScript + Decorator 기반의 백엔드 프레임워크를 제작했다고 한다.
웹 진영에서는 React
, Vue
, Angular
와 같이 잘 정돈되어 수립된 웹 프레임워크가 존재하지만,
서버 사이드의 JavaScript 는 제대로 수립된 프레임워크가 별로 없었다고 한다.
이러한 배경에 근거하여, Angular
에 큰 영감을 받아 아키텍쳐를 구상했다고 한다.
나는 오히려 Java - Annotaion
과 매우 비슷한 JS - Decorator
때문에,
Spring
에서도 큰 영감을 받았을 것으로 추측한다.
NestJS 를 사용해야 하는 이유는 무엇일까?
나는 2 개의 프로젝트를 NestJS 로 구축하며 NestJS 의 사용법을 알며, 컨벤션 또한 숙지했다.
덕분에 온라인으로 편하게 팀원과 프로젝트를 구축할 수 있었는데,
이는 NestJS 가 Express 에서 강제하지 않은 컨벤션을 NestJS 는 Spring 처럼 정해주었기 때문이다.
이러한 프레임워크의 단점으로는, 편한 팀워크를 위해 해당 프로그램을 "배워야" 한다는 단점이 존재하기 마련이다.
그러나, 이건 단점으로 보기 힘들다고 판단했는데, 프로그램을 배웠기 때문에 오히려 편리해졌기 때문이다.
그런데도 불구하고, 나는 NestJS 를 아주 적극적으로 추천하지는 않는다.
아주 크게 보면 프로그램 세상에서 "정답" 인 방법론은 존재하지 않는다고 생각한다.
프로그램이 명세에 맞으며, 유지보수성을 보았을 때 올바로이 작성되었다면, 그게 정답이 아닐까 생각한다.
좁은 시야에서 보자면, 굳이 JavaScript 기반의 NestJS 를 써야 하나요? 라고 물어봐야 한다고 생각한다.
내가 이러한 의견을 필력하는 데에는 이유가 있다.
NestJS 는 백엔드 프로그램으로서, 보이지 않는 복잡한 데이터를 처리하는 프레임워크이다.
NestJS 는 코드 생산성과 성능 면에서 모두 압도 할 만큼의 프로그램이라고는 말할 수 없다.
Java 를 알고, 백엔드 로직에만 집중하고자 한다면, Spring 을 적극 추천한다.
C 나 C++ 를 잘 다루는데, 보안 관련된 프로그램이나 블록체인이 관련되어 있다면, Rust
의 프레임워크를 추천할 것이다.
그러나, 만약에 JavaScript 기반의 웹 개발자이며, 백엔드 프로그램을 배워서 팀워크를 구축하고 싶다면,
나는 단번에 NestJS
를 사용해야 한다고 말할 것이다.
AI 시대로 인해 전체적인 구상도를 만드는 상황이 매우 편리해졌다지만,
결국 코드에서의 디테일과 컨벤션은 사람이 직접 건드려야 한다.
또한, 2 개의 서로 다른 컨셉의 프로그래밍 언어를 사용하여 풀스택을 완성하는 것은 상대적으로 쉽지 않은 일이다.
나는 몇년 전만 해도 큰 도메인(Front, Back) 에 따라 선호되는 언어로 프로그램을 작성해야 한다고 믿고 있었다.
다양한 방법론들과 컨벤션을 각기 다른 언어와 프레임워크에서 살펴보며 느낀 것은,
생산성이라는 생각이 든다.
Java 를 잘하면, Spring 기반의 백엔드 프레임워크에 의존성을 추가하여, 웹 페이지를 제작할 수 있다.
심지어는 Rust 를 잘하면, Rust 커뮤니티에서 제작한 컴포넌트 시스템을 통해
wasm
파일로 브라우저에 접착시켜 웹 페이지를 만드는 것이 가능하다.
Rust 또한, 백 엔드 프레임워크가 존재한다.
각자의 관심사와 원하는 로직 처리의 분야는 개개인이 다를 것이다.
그러나, 현재 소프트웨어의 시대는 당연하고, 언어들이 담당하고 있던 서로의 도메인을 먹어치우는 과정이 포함되어
특정 언어를 잘한다면, 해당 언어로 제작하면 되는 것이다.
따라서, NestJS 를 추천하는 상황이라면, 브라우저 웹을 제작하는 것을 넘어,
Back-End 에서 처리되던 로직을 웹 개발자나 JavaScript and TypeScript 개발자가 처리해야 된다면
NestJS 를 강력 추천한다.
참조 사이트
Reddit (TypeScript 트랜스파일러가 Go 로 바뀌었을 때 반응)
https://www.reddit.com/r/golang/comments/1j8shzb/microsoft_rewriting_typescript_in_go/
NodeJS 공식 문서 (V8 JavaScript 엔진)
https://nodejs.org/ko/learn/getting-started/the-v8-javascript-engine
NPM 공식 문서
https://docs.npmjs.com/about-npm
NestJS 공식 문서