[NestJS] js, express, nestjs 비교

star_moon_cloud_k·2024년 3월 27일

NestJs

목록 보기
1/5
post-thumbnail

잡설

시작하기 앞서, 나는 자바 스프링으로 2년간 공부를 했고, 대학에 늦게 졸업하게 되며, 취업하려고 뭐 열심히 했던것 같긴한데.. 역시 취업은 쉽지 않았다.

어쩌다보니 잡기술들이 많았던게 도움이 되었는지, 교수님의 추천으로 스타트업에 취업하게 되었고, 회사의 코드를 보고 나는 좌절했다.

열심히 스프링했더니, 회사 코드는 모두 nestjs에 nextjs로 구현되어있다. js는 그냥 어플이랑 react 페이지 조금 핥아본 정도였는데, typescript의 세계는 나에게 너무 버거워보였다.

그래도 다행인게 회사에 강의 사달라고 하니, 그 자리에서 결제해주셨다.

출퇴근을 하면서 아래 두 강의를 보면서 언어 공부를 하고,
[코드팩토리][입문] 9시간만에 끝내는 코드팩토리의 Javascript 무료 풀코스
[코드팩토리][초급] 8시간만에 끝내는 코드팩토리의 Typescript 완전정복 풀코스

주말과 저녁에는 NestJs를 공부해야겠다고 마음먹었다.
NestJs 강의는 [코드팩토리][초급] NestJS REST API 백엔드 완전 정복 마스터 클래스 - Part 1 NestJS Core 로 정하고 공부하고 있다.

강의를 잘 하시는 것 같다.

출근한지 이제 10일 쯤 되었나, 얼추 NestJs 코드는 간단하게 짤 수 있겠지만, 강의는 최대한 열심히 보고있다.

주말에 공부했던 내용들을 버리듯이 정리하는 글이다.


1. js로 서버 만들어보기

  • js 자체만으로도 웹 서버를 만들 수 있다.
  • 왜 express가 나오게 되었는지 간단하게 작성해본다.
    1_server.js 파일
const http = require("http")

//localhost -> 127.0.0.1 -> loop back

const host = "localhost"
const port = 3000

//req -> request : 요청
//res -> response: 요구

const server = http.createServer((req, res) => {
  res.writeHead(200, { "Content-Type": "text/html" })

  res.end("<h1>Hello World</h1>")
})

server.listen(port, host, () => {
  console.log("server. running on http://localhost:3000/")
})

require()로 필요한 라이브러리를 import하는 방식이 독특하다

  • 기본적으로 사용 가능한 js 내부로 서버만들기
  • 간단한 서버를 node 명령어로 사용하여 실행 가능
  • node 1_server.js
const http = require("http")
const url = require("url")

//localhost -> 127.0.0.1 -> loop back
const host = "localhost"
const port = 3000

//req -> request : 요청
//res -> response: 요구

const server = http.createServer((req, res) => {
  const path = url.parse(req.url).pathname //실제 보내온 URL 값을 받아서 url 값으로 변환가능

  if (path === "/") {
    res.writeHead(200, { "Content-Type": "text/html" })

    res.end("<h1>Home Page!</h1>")
  } else if (path === "/post") {
    res.writeHead(200, { "Content-Type": "text/html" })

    res.end("<h1>Post Page!</h1>")
  } else if (path === "/user") {
    res.writeHead(200, { "Content-Type": "text/html" })

    res.end("<h1>User Page!</h1>")
  } else {
    res.writeHead(404, { "Content-Type": "text/html" })

    res.end("<h1>404 Page Not Found!</h1>")
  }
})

server.listen(port, host, () => {
  console.log("server. running on http://localhost:3000/")
})

위와 같이 path 를 나누는 방법도 있다.
하지만 http 패키지를 다이렉트로 사용하게 되면, boilerplate도 많고, 복잡한 작업을 직접 해야하는 것들이 많아진다.

js 파일과 node만으로는 서버를 만들 수 없다.
package를 관리할 수 있는 무언가를 만들어야함.

yarn init 명령어를 사용하면 package.json 파일이 만들어진다

  • 패키지의 정보를 담아줄 수 있다.
    ╰─$ yarn init                                               
    yarn init v1.22.22
    question name (1_actual_1_pure_js_server): 
    question version (1.0.0): 
    question description: 
    question entry point (index.js): 
    question repository url: 
    question author: 
    question license (MIT): 
    question private: 
    success Saved package.json
    ✨  Done in 6.20s.
**명령어를 실행하게 되면 생성되는 package.json**
```json
{
	"name": "1_actual_1_pure_js_server",
	"version": "1.0.0",
	"main": "index.js",
	"license": "MIT",
}

yarn add <module> 명령어를 사용하게 되면, 모듈이 추가로 설치되며 package.json 파일에 저장되며 관리된다.

2. express, NestJs비교

2_server.js 코드

const express = require("express")
const app = express()

app.get("/", (req, res) => {
  res.send("<h1>Home Page</h1>")
})

app.get("/post", (req, res) => {
  res.send("<h1>Post Page</h1>")
})

app.get("/user", (req, res) => {
  res.send("<h1>User Page</h1>")
})

app.use((req, res) => {
  //use는 path 값을 받지 않는다.
  res.status(404).send("<h1>404 Page Not Found!</h1>")
})

// app.post();

//app.delete();

//app.put();

app.listen(3000, () => {
  console.log("server running http://localhost:3000")
})
  • 이번 코드는 express 모듈을 사용해서 http 기본 패키지를 사용하지 않고, 1_server.js 같은 기능의 코드를 작성했다.
  • 같은 기능이지만, express 를 사용해서 만들어진 코드가 더 간결하고 보기도 편하다.
  • 하지만, node의 기본 모듈이 아니므로, yarn add 명령어를 사용하여 모듈이 설치되어야 실행이 가능하다.
╰─$ yarn add express                                                                                               1 ↵
yarn add v1.22.22
info No lockfile found.
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Saved lockfile.
success Saved 39 new dependencies.
info Direct dependencies
└─ express@4.19.1
info All dependencies
├─ accepts@1.3.8
├─ array-flatten@1.1.1
├─ body-parser@1.20.2
├─ call-bind@1.0.7
├─ content-disposition@0.5.4
├─ content-type@1.0.5
├─ cookie-signature@1.0.6
├─ cookie@0.6.0
├─ define-data-property@1.1.4
├─ ee-first@1.1.1
├─ express@4.19.1
├─ finalhandler@1.2.0
├─ forwarded@0.2.0
├─ get-intrinsic@1.2.4
├─ has-property-descriptors@1.0.2
├─ has-proto@1.0.3
├─ has-symbols@1.0.3
├─ hasown@2.0.2
├─ inherits@2.0.4
├─ ipaddr.js@1.9.1
├─ media-typer@0.3.0
├─ merge-descriptors@1.0.1
├─ methods@1.1.2
├─ mime-db@1.52.0
├─ mime-types@2.1.35
├─ mime@1.6.0
├─ ms@2.0.0
├─ negotiator@0.6.3
├─ object-inspect@1.13.1
├─ path-to-regexp@0.1.7
├─ proxy-addr@2.0.7
├─ raw-body@2.5.2
├─ safer-buffer@2.1.2
├─ serve-static@1.15.0
├─ set-function-length@1.2.2
├─ side-channel@1.0.6
├─ toidentifier@1.0.1
├─ utils-merge@1.0.1
└─ vary@1.1.2
✨  Done in 2.69s.

위와 같이 설치되고 나면, 해당 명령어를 실행한 폴더에 node_modules 라는 폴더가 생성된다.
그리고 package.json 파일을 살펴보게 되면 "dependencies" 라는 항목이 생성되고 그 안에 express 값이 저장되어있다.

{
  "name": "1_actual_1_pure_js_server",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "express": "^4.19.1"
  }
}

express 그리고 nestjs

결국 express도 충분히 좋고, 깔끔하게 코드가 작성이 가능한 것 처럼 보이지만, nestjs를 만든 사람들에게는 부족했던 모양이다.

나보다 더 똑똑하고 더 깔끔떠는 개발자들이 만든 프레임워크일테니 이유가 있겠지 싶다.

NestJs 간단한 시작

nest new <프로젝트 이름> 명령어를 실행하여 프로젝트를 생성하면 폴더가 만들어지고, 다양한 패키지가 설치된 package.json 파일을 볼 수 있다.

.
├── dist
├── node_modules
├── src
└── test

간단하게 폴더의 구조를 보면 루트에는 package.json , eslint tsconfig 등 패키지를 관리하는 파일들과 node_modules 같은 폴더들도 보인다.

  • src 폴더 안에는 프로젝트에서 실질적인 로직이 작성될 것으로 보인다.
  • test 폴더는 개발 후 테스트 할 코드들이 있을것으로 보인다.
src
├── app.controller.spec.ts
├── app.controller.ts
├── app.module.ts
├── app.service.ts
└── main.ts

src 폴더 내부에는 nestjs에서 가장 기본적인 코드 틀을 볼 수 있겠다.

  • app.controller : 아마 http 요청을 처리하는 가장 기본 단위를 작성하는 곳
  • app.module : 이곳은 app 이라고 나눠진 코드에서 의존성 단위를 관리하는 곳이라고 한다.
  • app.service : 요청을 직접적인 로직으로 처리하는 부분
  • main : 실질적으로 nestjs 를 시작하는 시작점이다.

Typescript 코드를 기반으로 작성되어 있다보니, 기본 확장자가 .ts 로 끝이난다.

NestJs 코드

import { Controller, Get } from "@nestjs/common"
import { AppService } from "./app.service"

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHome() {
    return "home page"
  }

  @Get("post")
  getPost() {
    return "post page"
  }

  @Get("user")
  getUser() {
    return "user page"
  }
}

확실히 비교해보면 nestjs가 express가 더 깔끔하고, 함수 반환하는게, spring 같은 느낌이 든다.

  • 실행 방법은 nestjs 가 설치 된package.json 안에서 script 부분을 보면 확인이 가능하다.
  • yarn <실행할 명령어> 로 실행한다.
  • 그냥 시작할 경우 yarn start 로만 명령어를 입력하면 코드에 문제가 없다면 바로 실행된다.
"scripts": {
  "build": "nest build",
  "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
  "start": "nest start",
  "start:dev": "nest start --watch",
  "start:debug": "nest start --debug --watch",
  "start:prod": "node dist/main",
  "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
  "test": "jest",
  "test:watch": "jest --watch",
  "test:cov": "jest --coverage",
  "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
  "test:e2e": "jest --config ./test/jest-e2e.json"
},
  • 서버 실행하는 명령어도 다른 옵션을 추가해서 커스텀 할 수 있다.

모든 내용은 강의 [코드팩토리][초급] NestJS REST API 백엔드 완전 정복 마스터 클래스를 수강하며 정리하는 내용들을 올린 글이다.

profile
자유로운 개발자

0개의 댓글