Introduction

Nest는 효율적이고 확장가능한 server-side application을 building하기 위한 프레임워크이다.
또한 Javascript, TypeScript로 작성하는 하며 OOP(Object Oriented Programming), FP(Functional Programming), FRP(Functional Reactive Programming)적 요소를 결합하였다.

client-side: 클라이언트측(브라우저)에서 수행하는 처리를 뜻함
    - HTML, JavaScript, CSS, Ajax, JQuery ...
server-side: 서버 측에서 수행하는 처리를 뜻함
    - PHP, JSP, ASP, Ruby, Python ...

OOP(Object Oriented Programming):  객체 지향적인  프로그래밍, 즉, C언어같은 절차지향적인 프로그래밍이 아닌 객체의 
    관점에서 프로그래밍을 한다는 것
FP(Functional Programming): 모든 것을 순수 함수로 나누어 문제를 해결하는 기법, 작은 문제를 해결하기 위한 함수를 작성하여
    가독성을 높이고 유지보수를 용이하게 해준다.
RP(Reactive Programming): 데이터의 흐름과 변경사항의 전파에 중점을 둔 선언적 프로그래밍 패러다임
    e.g. 엑셀에서 C1 = A1 + B1 라고 선언적으로 정의한다. 이 때 C1의 값은 A1과 B1의 값에 따라 즉시 반영되어 변경된다.
FRP(Functional Reactive Programming): 비동기적인 데이터 처리를 간단한 함수를 통해 수행하는 프로그래밍    

좀 더 상세하게, Nest는 강력한 HTTP 서버 프레임워크를 제공한다. default로 Express와 그리고 Fastify가 있다.

Express: Node.js 환경에서 웹 애플리케이션과 API를 구축하기 위해 널리 사용되는 웹 프레임워크이다.
Fastify: 마찬가지로 Fastify도 Node.js 기반의 웹 프레임워크로, 웹 애플리케이션과 API 구축에 사용된다. 비교적 새로운 프레임워크이다.

Nest는 Node.js 프레임워크(Express/Fastify)를 통해 높은 수준의 추상화를 제공한다. 또한 Nest의 API들은 바로 개발자에게 보여준다. 개발자들은 Nest에서 사용가능한 수많은 yarn, npm 따위를 통해 많은 모듈들을 선택할수 있는 선택권을 가진다.

Philosophy

최근 몇년사이에, Node.js 덕분에 JavaScript는 front와 backend application에서 "lingua franca"가 되었다. Node.js 덕분에 Angular, React, Vue와 같은 프레임워크가 생겼고 이를 통해 frontend Application들은 생상성, 창의성, 속도, testable, 그리고 확장가능해 졌다. 하지만 다양한 Node와 server-side를 위한 JavaScript 라이브러리, 도구들은 존재하지만 소프트웨어 아키텍처와 관련된 주요 문제들을 해결해 주진 못했다.

Nest는 out-of-the-box(별도의 설치가 필요 없는) application architecture을 제공한다. 이는 개발자들에게 testable하고 확장가능하고 또 loosely=coupled하고 마지막으로 쉽게 maintainable한 application을 제공한다. Angular에 의해 영감을 받은 architecture이다.

Installation

시작을 위해서는 Nest CLI을 발판삼아 project를 시작하거나, 혹은 이미 진행되고 있는 project를 clone하는 수가 있다.

$ npm i -g @nestjs/cli
$ nest new project-name

위의 코드를 작성하면 새로운 project를 위한 directory를 만들고 초기 base structure를 위한 Nest files, modules들이 채워진다.

만일 저 엄격한 TypeScript를 만들고자 한다면 --strictnest new에 추가한다.
strict을 추가한다면 tsconfig.json에 몇 가지 설정이 바뀐다.

// 설정 전
    "strictNullChecks": false,
    "noImplicitAny": false,
    "strictBindCallApply": false,
    "forceConsistentCasingInFileNames": false,
    "noFallthroughCasesInSwitch": false
// 설정 후
    "strictNullChecks": true,
    "noImplicitAny": true,
    "strictBindCallApply": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true
  1. strictNullCheck: 변수가 null 또는 undefined 값을 가질 수 있는지 여부를 엄격하게 검사하도록 한다.
    이 옵션을 활성화하면,모든 변수와 속성이 null이나 undefined 값을 가질 수 있는 지 명시적으로 선언해야 한다.
    그렇지 않으면 컴파일 오류가 발생한다.
  2. noImplicitAny: 변수나 함수의 매개변수가 암시적으로 'any' 타입을 가지지 않도록 강제하는 옵션. 이 옵션을 활성화하면, 타입을 명시하지 않은 변수나 함수 매개변수에 대해 TS가 암시적으로 any 타입을 할당하지 못하도록 한다.
  3. strictBindCallApply: Function.prototype.bind, Function.prototype.call, Function.prototype.apply 메서드 사용 시 타입 검사를 엄격하게 수행하도록 강제한다. 이 옵션을 활성화하면, 메서드를 사용할 때 인수의 타입이 정확히 일치하지 않으면 컴파일 오류가 발생한다. 즉 'bind', 'call', 'apply' 메서드를 사용할 때 정확한 타입 검사가 수행되어 더 안전한 코드를 작성할 수 있다.
// strictBindCallApply 비활성화
function add(a: number, b: number): number {
  return a + b;
}

const boundAdd = add.bind(null, '1'); // 'a'는 암시적으로 'any' 타입을 가짐
console.log(boundAdd(2)); // 정상 동작 (하지만 타입 안전성이 없음)

const result = add.call(null, '1', '2'); // 'a'와 'b'는 암시적으로 'any' 타입을 가짐
console.log(result); // 정상 동작 (하지만 타입 안전성이 없음)

// strictBindCallApply 활성화
function add(a: number, b: number): number {
  return a + b;
}

const boundAdd = add.bind(null, '1'); // 컴파일 오류: 'string' 타입은 'number' 타입에 할당할 수 없습니다.
console.log(boundAdd(2)); // 오류 발생

const result = add.call(null, '1', '2'); // 컴파일 오류: 'string' 타입은 'number' 타입에 할당할 수 없습니다.
console.log(result); // 오류 발생

// 수정된 코드
const boundAddCorrect = add.bind(null, 1); // 정상 동작
console.log(boundAddCorrect(2)); // 정상 동작

const resultCorrect = add.call(null, 1, 2); // 정상 동작
console.log(resultCorrect); // 정상 동작
  1. forceConsistentCasingInFileNames: TS의 컴파일러 옵션 중 하나로, 파일 이름의 대소문자 일관성을 강제하는 옵션이다. 이 옵션을 활성화하면, 파일 시스템이 대소문자를 구분하지 않더라도 파일 이름의 대소문자가 일관되지 않으면 컴파일 오류가 발생한다.
// 파일 이름이 MyComponent.ts인 경우.

// 비활성화
import { MyComponent } from './myComponent'; // 오류 없음 (하지만 대소문자 일관성 없음)

// 활성화
import { MyComponent } from './myComponent'; // 컴파일 오류: 대소문자 불일치

// 수정된 코드
import { MyComponent } from './MyComponent'; // 정상 동작 (대소문자 일관성 유지)
  1. noFallThroughtCasesInSwitch: TS의 컴파일러 옵션 중 하나로, switch 문에서 의도하지 않은 경우 값의 누락(fallthrough)을 방지하도록 강제하는 옵션이다. 이 옵션을 활성화하면 'switch'문에서 'case' 블록이 'break'문을 포함하지 않으면 컴퍼일 오류가 발생한다. 이는 코드의 가독성과 안전성을 높이고, 의도하지 않은 논리 오류를 방지하는데 도움이 된다.
npm i -g @nestjs/cli
에서 '-g'는 'global'을 의미한다. 이는 해당 패키지를 전역(global)로 설치하겠다는 뜻이다.
전역으로 설치된 패키지는 시스템 전체에서 접근할 수 있으며, 모든 프로젝트에서 사용할 수 있다.

Alternatives

다른방법으로, Git을 통해 TypeScript기반의 nest를 설치하고자 한다면

$ git clone https://github.com/nestjs/typescript-starter.git project
$ cd project
$ npm install
$ npm run start

참고로, 만일 git history없이 repo를 clone하고자 한다면, degit을 이용할 수 있다.
또한 TS가 아닌 JS로 시작하고자 한다면, typescript-starter대신 javascrip-starter.git을 쓸 수 있다.

마지막으로 the core와 supporting files을 포함한 project로 시작하고자 한다면 다음과 같다.
이 경우에, project의 boilerplace files를 만들 책임이 있다.

npm install @nestjs/core @nestjs/common rxjs reflect-metadata

+ Recent posts