NestJS는 nodejs (javascript) 진영에서 매우 유명한 백엔드 프레임워크이다.
공식 문서에서 nestjs는 typescript를 완전히 지원하며 OOP(Object Oriented Programming), FP(Functional Programming), FRP(Functional Reactive Programming)를 결합했다고 소개하고 있다. 또, NestJS를 통해 nodejs 진영에서 애플리케이션 아키텍처를 제공해줄 수 있게 해주기 위한 철학을 가지고 있다고 하며, Angular에서 영감을 많이 받았다고 한다. 실제로 module과 같은 개념이 있는 것을 보면 Angular에서 영감을 받았다는 점이 팍팍 느껴진다.
즉, JVM 생태계 언어에서 Spring 프레임워크가 있다면 nodejs 진영에서는 NestJS 프레임워크가 있다는 점!
실제로 (아직 나도 맛만 봤지만) 둘은 상당히 비슷하다고 느껴진다.
그렇기 때문에 nodejs, spring 경험이 있다면 배우는 데 도움이 되리라 생각한다.
학습 동기
사실 js 카테고리에 글을 다시 쓰리라곤 생각하지 못했는데... 생각보다 빠르게 글을 쓰게 됐다.
학습 동기는 아래와 같다.
- 넥스터즈 동아리에서 기술 스택 관련 얘기를 할 때 nestjs가 언급됐다.
- spring과 비슷하다고 해서 관심이 생겼다.
- 7월에 입사하는 팀에서 react, vue도 간단하게 다루어야 된다고 했기 때문에 js계열을 조금이라도 공부해두면 좋을 듯하다. (html, css 다시 하기 싫어서 미루고 nestjs 하는 것도 있는듯 ㅋㅋ)
- Java 8 이후나 Kotlin에서 함수형 프로그래밍 (ex. lambda)도 조금씩 사용되기 때문에 익혀서 나쁠 건 없다.
- nodejs는 JVM 계열 언어와 다르게 싱글 스레드, Event-Driven (event loop), Non-Blocking 기반으로 돌아간다. 그렇기 때문에 특성 상 Spring과 비슷하다 해도 꽤나 다른 점들이 존재한다. 게다가 nestjs는 최근에 나왔다. 그렇기 때문에 Spring에 비해 좀 불편한 점들이 있다고 한다. 이러한 둘의 차이점을 비교해보고 싶어졌다.
nestjs에 대해 찾아보다가 문득 아래와 같은 글을 발견했다. nestjs, spring을 모두 경험해본 개발자분이 작성한 글이었는데 흥미로워서 가져와봤다. 이 분께서는 nestjs가 spring에 공식문서의 부실함, nestjs 자체의 불편함 등으로 인해 불편하다고 하셨다.
https://blog.naver.com/biud436/222419394997
https://blog.naver.com/biud436/222611201210
이 글을 읽고 든 생각은... nestjs가 그래도 spring이랑 비슷할텐데 어떤 점이 불편할까? 였다.
그래서 나도 한 번 직접 경험해보고 싶어졌다.
아래에 설치법 및 구축 방법을 간단하게 적어보도록 하겠다.
NestJS 설치
나는 아래 환경에서 설치를 진행했다.
- node: 16.14.2
- npm: 8.5.0
버전 확인 방법은 터미널에서 npm -v, node -v를 입력해주면 된다.
$ npm i -g @nestjs/cli
$ nest new project-name
이제 위 명령어를 입력해주면 된다.
아래 스크린샷을 참고하여 따라해보도록 하자.
다만, 나의 경우는 nestjs를 설치할 때 권한 에러가 발생해서 sudo 명령어를 추가해주어 아래와 같이 진행해주었다.
package manager는 yarn, npm 중에 npm을 사용하기로 했다.
나중에 패키지 매니저도 아래에 우아한테크코스 4기 프론트 비녀가 발표한 테코톡을 보면서 공부해봐야겠다.
아무튼 위와 같이 nestjs를 설치해주고 프로젝트를 열면 아래와 같이 애플리케이션 구축이 돼있을거다.
저 boards 라는 것은 내가 듣고 있는 강의에서 생성하라고 해서 별도로 만든거다.
중요한건 `package.json`, `.eslintrc.js`, `.prettierrc`, `node_modules`, `app.module.ts`가 생성됐는지의 여부다.
eslint랑 prettier는 컨벤션을 맞춰주는 역할을 한다. indent를 어떻게 할 것인지, 작은따옴표와 큰따옴표 중 무엇을 쓸 것인지, 세미콜론을 사용할 것인지 등등. vscode에서 shift + option + f를 누르면 자동정렬이 되니까 한 번 확인해보자.
애플리케이션 실행 방법은 package.json을 참고하면 된다.
package.json에 나와있듯이 npm run start 또는 npm run start:dev를 입력하고 localhost:3000로 들어가면 Hello World! 가 출력될 것이다.
종료하는 방법은 control + c이다.
NestJS에서 Module, Controller, Service 생성하기
먼저 모듈을 생성해보자.
모듈은 컨트롤러, 서비스의 생명주기를 제공 및 관리하는 대상을 의미한다.
참고로 컨트롤러는 클라이언트와 소통하여 api 송수신을 하는 역할을 하고, 서비스는 비즈니스 로직을 담당하는 역할을 한다고 이해하면 될 듯하다.
아래 명령어를 터미널에 입력해주자.
nest g module {모듈명}
g는 generate의 약자이다.
위와 같이 명령어를 입력해주기만 하면 module이 생성된다.
개인적으로 정말 신기했던 부분이다. 스프링에선 본인이 직접 생성했어야 됐는데, nestjs에선 터미널에서 명령어를 입력해주면 자동으로 module, controller, service를 생성해준다. 하지만 엄청난 장점으로 느껴지진 않았고 그냥 신기한 정도긴 했다.
여기서 @Module 데코레이터는 nestjs에서 해당 클래스가 module임을 인식하게 해준다. @가 붙어있는 부분은 데코레이터라 생각하면 된다. 장고의 데코레이터, 스프링의 어노테이션이랑 같은 역할을 한다고 생각하면 된다.
Controller, Service도 생성해보자.
nest g controller {모듈명}
nest g service {모듈명}
// 테스트 코드 (spec.ts) 없이 진행하려면
nest g controller {모듈명} --no-spec
nest g service {모듈명} --no-spec
Service는 --no-spec 옵션을 포함하여 명령어를 입력해주어서 spec.ts가 생성되지 않은 것을 확인할 수 있다!
개인적으로는 테스트 코드는 필수로 있어야 한다고 생각하는 입장이지만... 아직 nestjs를 처음부터 배우는 단계이기 때문에 테스트는 조금 이후에 포스팅할 예정이므로 --no-spec 옵션을 자주 사용하리라 생각된다.
컨트롤러, 서비스는 @Controller, @Injectable 데코레이터로 생성 및 module에 주입된 것을 확인할 수 있다.
@Controller('apple')
export class AppleController {
constructor(private appleService: AppleService) {}
}
컨트롤러에 서비스를 위와 같이 주입해줄 수 있다. (레이어드 아키텍처는 이미 알고 있다고 가정한다.)
Service와 같이 @Injectable 데코레이터로 종속성으로 주입되는 대상을 Providers라 한다. 주입 과정은 NestJS 런타임에 위임된다.
위 코드를 보면서 마치 kotlin 문법이랑 비슷하다고 생각이 들었으며, Spring의 DI와 유사하다고 느꼈다.
참고로 private 키워드는 javascript에는 없고 typescript에 있다고 한다. private 키워드가 없다면 조금 더 코드가 길어진다.
공식문서에서 나와있듯이 nestjs는 module을 주입받는 과정으로 싱글톤 인스턴스를 생성해준다. module, providers는 싱글톤으로 생성해주기 때문에 스프링 프레임워크와 마찬가지로 매 요청마다 인스턴스가 생성될 걱정을 하지 않아도 된다.
For people coming from different programming language backgrounds, it might be unexpected to learn that in Nest, almost everything is shared across incoming requests. We have a connection pool to the database, singleton services with global state, etc. Remember that Node.js doesn't follow the request/response Multi-Threaded Stateless Model in which every request is processed by a separate thread. Hence, using singleton instances is fully safe for our applications.
출처: https://docs.nestjs.com/fundamentals/injection-scopes
출처: https://docs.nestjs.com/controllers
자동으로 생성된 AppleController.spec.ts 코드를 가져와봤다.
우측 사진을 보면 jest를 기본으로 사용하는 것을 확인할 수 있다.
스프링에서 자주 사용되는 테스트 코드 문법인 JUnit5와 유사하다는 생각이 들었다.
개인적으로는 javascript는 너무 자유도가 높아서 좋아하진 않는다.
그럼에도 불구하고 nestjs는 아직까진 꽤 재밌고 흥미있게 느껴졌다.(조금 깔짝댄 정도이기 때문에 당연한 거 아니냐? 라고 하면 할 말이 없긴 하지만...)
그나마 nestjs는 typescript를 지원해주어 타입 검증도 되고 spring과 유사한 점이 많아 익숙한 덕분에 그런 게 아닐까 싶다.
조금 더 공부해봐야 알겠지만 Spring과 어떤 점에서 차이가 나는지, nodejs 진영의 single-thread, non-blocking으로 인한 차이점들을 몸소 겪어볼 수 있으면 좋겠다.
다만, nestjs 공부는 현재 나에게 우선순위가 높진 않아서 포스팅 속도가 느리거나 중간에 끊길 수도 있다.
'JS > Nest.js' 카테고리의 다른 글
[NestJS] pipe를 이용한 validation 처리 (0) | 2023.01.18 |
---|---|
[NestJS] 간단한 게시판 CRUD 구현하기 (2) | 2023.01.13 |