본문 바로가기
Backend/NestJS

[NestJs] 끄적끄적

by 찬찬2 2023. 3. 29.

■ NestJS 설치하고 새로운 프로젝트 생성하면 이것저것 생김.

eslintrc.js : 개발자의 코드 스타일 정의

prettierrc : 코드 포맷 형식 정의

 

npm run start:dev 실행. 실행순서

main.ts 순서 상 제일 먼저 로드되는 스크립트. 여기에 NestFactory.create()에 의해 루트모듈 정의, 포트설정

 

진입 순서?

module → controller → service

 

■ 모듈의 구성

① module, ② entity, ③ service, ④ repository, ④ pipe 

 

■ 모듈 파일 생성 명령어

base: nest g module boards / nest g controller boards / nest g service boards 

option: --no-spec

 

■ 중요1: 의존성 주입(Dependency Injection - service를 controller 클래스 constructor함수의 인자로 넣는 것)

 

■ 중요 2: Providers를 통해 service들을 묶어 service가 필요로하는 곳의 모듈에 등록하고 싱글으로 사용할 수 있다.

 

Model 만들기 → Entity 만들기

 

DTO(Data Transfer Object)

계층간 데이터 교환을 위한 객체.

DB에서 데이터를 얻어 Service나 Controller 등으로 보낼 때 사용하는 객체를 말한다.

DTO는 데이터가 네트워크를 통해 전송되는 방법을 정의하는 객체이다.

 

class 또는 interface로 작성 가능. 보통 class를 많이 사용한다고 하는데 그 이유가 잘 이해가 안됨.

class 는 interface와 다르게 "런타임"에서 작동하기 때문에 파이프 같은 기능을 이용할 때 더 유용하다??

 

■ @Body, @Param

사용자측에서 HTTP 요청, controller에 있는 함수에서 인자로 받을때 사용할 수 있는 데코레이터

 

■ Pipe를 선언할 수 있는 3 곳

사용법: Handler-level / Parameter-level / Global

- built-in pipe

 

■ 유효성 검사 라이브러리 (링크)

class-validator, class-transformer

@UsePipes( ValidationPipe ) + (IsNotEmpty, IsString, MinLength, MaxLength, Matches...)

(controller 단계)Handler-level에서 "ValidationPipe" 객체를 @UsePipes 데코레이터 안에 넣어주고, ↓ 아래와 같이 DTO 타입 객체에 class-validator에서 제공하는 데코레이터(IsNotEmpty, IsString, MinLength, MaxLength, Matches...)를 프로퍼티에 연결 시켜주면 된다.

 

① controller 객체 안에서 Handler-level의 위치에 UserPipes 데코레이터의 인자로 built-in pipe "ValidationPipe" 객체를 넣어준다.

② DTO 객체 안에서 class-validator에서 지원하는 데코레이터를 객체의 유효성이 필요한 프로퍼티와 연결한다.

 

즉, class-validator을 사용하기 위해서는 유효성 검사가 필요한 프로퍼티(필드)에 IsNotEmpty, IsString과 같은 데코레이터를 선언하고, 해당 DTO를 사용하려는 곳(controller)에서는 반드시 "UsePipes( ValidationPipe )" 데코레이터를 선언해줘야 한다.

 

예외처리 에러 처리

throw new NotFoundException 등 상황에 맞는 것들이 있음.

 

■ 유효성 검사 파이프

 

■ TypeORM(Object Relational Mapping)

TypeORM 은 node.js 에서 실행되고 TypeScript 로 작성된 객체 관계형 매퍼 라이브러리이다.

MySQL, PostgresSQL, MariaDB, SQLite, MS SQL Server, Oracle, SAP 등 여러 데이터베이스를 지원한다.

 

ORM: 객체(object)와 관계형 데이터베이스(table)의 데이터를 자동으로 변형 및 연결하는 작업. ORM 을 이용한 개발은 데이터베이스의 변형에 유연하게 사용할 수 있다.

 

인스톨한 라이브러리: pg(postgress), typeorm, @nestjs/typeorm

 

■ DB 생성

Postgres를 다운 받고 아래 내용을 참고해서 host, port, username, password, database 데이터를 넣어준다.

 

typeorm.config.ts 데이터베이스 연결

 

↑ PostgresSQL과 연결해주는 config 객체를 생성하고, 아래 처럼 루트 모듈 메타데이터에 넣어준다.

 

TypeORM config 객체를 루트 모듈에서 import하고, forRoot 매서드로 싱글톤으로 사용한다.

 

Entity - 데이터베이스 테이블 만들어줌

① 일반적인 데이터베이스 테이블 생성

 

② TypeORM으로 데이터베이스 테이블

 

 

■ TypeORM으로 데이터베이스 테이블 만들기 (데코레이터)

@Entity  → "CREATE TABLE board" 부분

@PrimaryGeneratedColumn → Primary KEY 열

@Column → 열

 

Repository

Entity 개체와 함꼐 작동하며 Entity 찾기, 삽입, 업데이트, 삭제 등을 처리한다.

(메서드: find, create, delete, findOne 등)

https://typeorm.delightful.studio/classes/_repository_repository_.repository.html

 

Repository는 일반적으로 데이터베이스에서 하는 일들을 수행한다. INSERT, FIND, DELETE...

 

Repository 생성

 

생성된 Repository 를 모듈에 연결

Module 메타 데이터 imports 배열에 등록한다.

 

 

■ Repository pattern - TypeORM을 사용할때 Repository pattern을 사용한다.

Repository patter의 장점과 단점 비교 정리 → https://tasddc.tistory.com/124

 

(그림1) TypeORM 구성

 

(그림2) TypeORM 데이터 전달 흐름

 

(그림3) TypeORM 사용자 시점의 흐름

 

Repository pattern, Repository Injection

service와 동일하게 Repository를 사용하고자 하는 곳에 의존성 주입을 해줘야 사용할 수 있다. (그림1)

 

service에 reposition 를 의존성 주입을 해준다.

 

Repository API & async / aswait (TypeORM - repository-api)

Repository API()를 사용할 때 반드시 promise pattern을 이용해야 한다.

※ SELECT, DELETE, UPDATE, INSERT, WHERE 절 등도 사용할 수 있음. 링크 참

 

유니크한 값 주기 Entity 파일에 Unique 데코레이터 안에 배열 안에 항목명들을 명시.

@Unique([항목이름])

만약 테이블에 항목이름이 이미 존재할 경우 에러가 출력된다. try/catch 문으로 에러 예외처리를 해준다. (기본 에러 메시지 500 코드가 나오는데, 에러의 유형별로 메시지를 정해주는 것이 좋다.)

 

 암호화 - bcrypt.js

만약 유저1과 유저2가 같은 비밀번호인 경우, 심지어 아이디까지 비슷했을때 유저2는 유저1의 계정에 접속할 수 있을 것이다. 그리고 서버가 뚤려 해커가 위 유저의 비밀번호를 알아낸다면 하나의 비밀번호로 두개의 계정이 도난당할 수 있다.

bcrypts.js는 "salt_순수 비밀번호" 의 형태를 hash로 변환해준다. 그렇기 때문에 유저간 비밀번호가 같아지는 상환은 발생하지 않을 것이다.

유저1 → pawword: 1234 oaisdh_1234 asdafhgjekwnqqw;;ew

유저2 → pawword: 1234 ggasdsw_1234  ;lksdjiwnqnwnee223r

 

■ JWT(JSON Web Token) 인증 절차

구조: Header / Payload / Verify Signature

Header: 토큰에 대한 메타 데이터(해싱 알고리즘 타입)

Payload: 사용자 정보, 말료기간, 주제(요청할 데이터) ...

Verify Signature: 서비스의 서버에 감춰진 Secret Key와 Header & Payload가 한데 묶인 "서명"

 

■ JWT 사용 흐름

1. 유저 로그인 → 토큰 생성 & 토큰 보관(로컬 스토리지, 쿠키)

2. 너가 너인지 비교하는 절차(서버): 사용자가 서버 데이터 요청(header에 token을 담아) → 서버는 토큰을 비교

 

 

■ JWT 토큰 생성하기

모듈 설치: @nestjs/jwt, @nestjs/passport, passport, passport-jwt, @types/passport-jwt

 

① JWT, Passport 모듈 등록 (JwtModule, PassportModule)

② jwtService.sign 메서드로 payload를 담아 access 토큰을 만들어 반환해준다.

 

■ UseGuard & AuthGuard() - 인증 관련 middleware

토큰의 유효성 체크를 위해 생성한 "JwtStrategy" 객체 안에 사용자의 request에 user 정보를 담아 보낼 수 있도록 validate 함수를 만들었다. 그리고 유효성 검사 절차를 사용하기 위해 핸들러 단위에서 UserGuard, AuthGuard를 선언해주면 된다.

 

■ 커스텀 데코레이터

 

parameter 데코레이터이기 때문에 파라미터 안에서 사용해야 한다.

 

■ 관계(Relation) 형성하기 - onToMay, ManyToOne

 

 

■ 환경변수 설정

라이브러리: (윈도우) npm install -g win-node-env & npm install config

config 모듈 생성 : default.yaml / development.yaml / production.yaml

환경변수 내용 입력.

import * as config from 'config' 로 불러와서 사용.

댓글