지난 포스트
[NestJS 기반 게시판 REST API 만들기] 1. 프로젝트 환경 구축
(Tistory가 에디터에서 마크다운을 지원한다고 하여 마크다운으로 작성했었는데,, 많이 깨지는 부분이 있어 이번 게시글부터 일반 에디터로 작성하겠습니다 ㅠ) 이번 글에서는 DB를 다루는데 TypeORM 공식 문서를 보고 오시면 좀 더 빠르게 이해하 실 수 있습니다.
1. Nest CLI 살펴보기
이번에는 게시판을 이용하는 유저 정보를 저장하기 위해 데이터베이스 테이블을 만들고 TypeORM을 사용하여 NestJS와 연동하는 방법을 설명드리겠습니다.
NestJS CLI는 명령어를 통해 모듈, 서비스, 컨트롤러 등을 자동으로 환경을 맞추고 파일을 생성해줍니다.
nest cli는 다음과 같은 명령어를 가지고 있습니다.
$ nest --help
Commands:
new|n [options] [name] Generate Nest application
generate|g [options] <schematic> [name] [path] Generate a Nest element
Available schematics:
┌───────────────┬───────────┐
│ name │ alias │
│ application │ app │
│ angular-app │ ng-app │
│ class │ cl │
│ configuration │ config │
│ controller │ co │
│ decorator │ d │
│ filter │ f │
│ gateway │ ga │
│ guard │ gu │
│ interceptor │ in │
│ interface │ interface │
│ middleware │ mi │
│ module │ mo │
│ pipe │ pi │
│ provider │ pr │
│ resolver │ r │
│ service │ s │
│ library │ lib │
└───────────────┴───────────┘
info|i Display Nest CLI details
update|u [options] Update Nest dependencies
add <library> Add a library
2. 유저 모듈 생성(Module, Service, Controller)
먼저 유저 관련 기능을 담당하는 유저 모듈을 다음 명령어를 통해 만들겠습니다.
$ nest generate module user
// 또는 아래 명령어를 사용하셔도 됩니다.
$ nest g mo user
유저 관련 요청을 관리하는 user controller와 요청된 내용을 처리하는 user service를 다음 명령어로 생성하겠습니다.
// user.controller.ts 생성
$ nest generate controller user
// user.service.ts 생성
$ nest generate service user
이후 다음과 같이 user.service.ts, user.controller.ts 파일이 생성된 것을 볼 수 있으며, user.module.ts 에 user.controller 와 user.service 가 자동으로 연결된 것을 볼 수 있습니다.
[ user.controller.ts]
import { Controller } from '@nestjs/common';
import { UserService } from './user.service';
@Controller('user')
export class UserController {
constructor(private readonly userService: UserService){}
}
NestJS는 Import된 모듈의 Service객체나 해당 모듈에서 Provider로 등록된 Service객체를 생성자로 넘겨주면, 서버 실행 시 NestJS Container에서 자동으로 인스턴스로 주입해줍니다. DI(Dependency Injection)이라는 개념으로 Spring을 해보신 분은 쉽게 이해하실 수 있습니다. 추후에 더 자세히 설명하겠습니다 ( 코멘트 달아주시면 답변 가능합니다! ).
[ user.service.ts ]
import { Injectable } from '@nestjs/common';
@Injectable()
export class UserService {
constructor(){}
}
[ user.module.ts ]
// user.module.ts
import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';
@Module({
imports: [],
controllers: [UserController],
providers: [UserService],
})
export class UserModule {}
3. User Table 및 User Entity Class 생성
데이터베이스에 유저 테이블을 생성하고, 해당 테이블을 클래스로 변환한 user.entity.ts 파일을 만들겠습니다.
[ user.sql ]
CREATE TABLE `user` (
`user_id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`uuid` VARCHAR(40) NOT NULL COLLATE 'utf8mb4_unicode_520_ci',
`name` VARCHAR(20) NOT NULL COLLATE 'utf8mb4_unicode_520_ci',
`email` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_520_ci',
`password` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_520_ci',
`last_login_date` DATETIME NULL DEFAULT NULL,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`user_id`)
);
위와 같이 SQL을 작성하시고 MariaDB 또는 MySQL 을 설치하고 실행을 하면 다음과 같이 테이블이 생성됩니다!
[user.entity.ts]
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from "typeorm";
@Entity({name:"user", schema:"board"})
export class User {
@PrimaryGeneratedColumn({
name: "user_id"
})
id: number;
@Column({length: 40})
uuid: string;
@Column({length: 20})
name: string;
@Column({length: 100})
email: string;
@Column({length: 100})
password: string;
@Column("datetime",{
name:"last_login_date"
})
lastLoginDate: Date;
@CreateDateColumn({
name:"created_at"
})
createdDate:Date;
@UpdateDateColumn({
name:"updated_at"
})
updatedDate:Date;
}
※ Decorator (@붙은 키워드) 에 대한 내용은 TypeORM 공식 문서를 보시면 좀 더 자세히 알 수 있습니다.
4. User Entity를 조작하는 User Repository 클래스 생성
3번 항목에서는 데이터베이스에 있는 User 테이블의 내용을 맵핑하여 관리할 수 있는 클래스인 유저 엔티티 클래스를 생성하였습니다. User 테이블에 데이터를 insert, update, delete 등의 SQL를 TypORM에서는 메서드를 통해 지원하며 다양한 형태로 구현할 수 있습니다(Entity Manager, Base Entity 상속, Repository 패턴).
※ TypeORM에서의 Repository 정의
Repository is just like EntityManager but its operations are limited to a concrete entity.
이번 프로젝트에서는 Repository 패턴을 사용한 방법을 이용하여 데이터베이스와 관련된 로직을 처리하겠습니다.아래와 같이 User Repository를 생성합니다.
[user.repository.ts]
import { Repository, EntityRepository } from "typeorm";
import { User } from "src/entities/user.entity";
@EntityRepository(User)
export class UserRepository extends Repository<User> {
}
Repository 클래스를 상속받아 구현하며, Repository에서 사용할 엔티티 타입을 지정하기 위해, User 엔티티 클래스를 Repository 타입으로 넘겨줍니다.
데이터베이스에 유저 테이블을 생성하였고, 유저 테이블을 객체로 맵핑하는 유저 엔티티 클래스와 유저 테이블에 관련된 SQL을 메서드 기반으로 수행 가능한 유저 리포지토리 클래스 또한 구현하였습니다. 이제 NestJS에서 DB를 연동하고 정상적으로 구동되는지 확인하겠습니다.
5. NestJS와 TypeORM 연동
TypeORM이 데이터베이스와 성공적으로 Connection을 맺을 수 있도록 다음과 같이 설정 파일을 만들어줍니다.
※ TypeORM에서 설정 파일은 다양한 방법으로 제공됩니다. 다음 링크를 참고하세요! TypeORM Configuration
저는 프로젝트 루트에 ormconfig.json 파일을 생성하여 TypeORM이 환경설정 정보를 읽어올 수 있도록 하겠습니다.
[ormconfig.json]
{
"type": "mysql", // 데이베이스 타입,(여러 데이터베이스를 지원합니다.)
"host": "localhost", // 데이터베이스 호스트 주소
"port": 3306, // 데이터베이스 포트 정보
"username": "db", // 로그인 유저 이름
"password": "1234", // 로그인 유저 비밀번호
"database": "board", // 사용할 데이터베이스 이름
"entities": ["src/entities/*.entity{.ts,.js}"], // 엔티티 파일들이 위치한 경로
"logging": true, // 로깅 여부
"synchronize": true // 동기화 여부
}
위와 같이 DB 관련 설정 정보를 프로젝트 루트 경로에 ormconfig.json 파일로 저장하면, TypeORM에서 DB Connection인스턴스를 생성할 때 자동으로 환경설정 값을 읽어와 적용합니다.
NestJS에서는 모듈 시스템을 사용하며, 모든 모듈은 하나의 Application 모듈에 Import 되어 관리되고, 실행됩니다. 이러한 루트 격의 Application 모듈은 NestFactory에서 인스턴스가 생성되고, 해당 인스턴스로 서버가 실행됩니다.
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app/app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.setGlobalPrefix('/api');
await app.listen(3000);
}
bootstrap();
따라서 우리는 DB Connection을 생성하는 시점을 가장 처음으로 로드되는 모듈인 Application 모듈에 적용하면 됩니다. 따라서 다음과 같이 루트 모듈에 TypeORM Conneciton 생성 관련 함수를 Import 해줍니다.
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import {TypeOrmModule} from '@nestjs/typeorm';
import { UserModule } from '../user/user.module';
@Module({
imports: [TypeOrmModule.forRoot(), UserModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
NestJS에서는 TypeORM을 이용하여 데이터베이스를 연동하는 내용은 NestJS 공식문서에 더 자세히 나와있습니다.
이제 서버를 실행시켜보면 다음과 같이 TypeORM 로그가 찍히면서 DB가 성공적으로 연동된 것을 알 수 있습니다.
yarn start:dev
콘솔에 출력되는 쿼리 내용을 보면 TypeORM이 User Entity Class의 정보를 확인하기 위해 데이터베이스에서 User Table 스키마를 가져오는 모습을 볼 수 있습니다.
트랜잭션이 성공적으로 끝나면 엔티티 클래스와 데이터베이스의 테이블 간의 동기화가 성공적으로 이루어진 것입니다.
다음 포스트에서는 회원가입과 로그인, 개인정보 암호화 및 파라미터 검증 방법을 설명해드리겠습니다^^
'Programming > Nodejs' 카테고리의 다른 글
[NodeJS] APK 파싱 (2) | 2019.06.03 |
---|---|
[NestJS] AWS S3 Image Upload (0) | 2019.06.03 |
NodeJS AES 256 암복호화 코드 (3) | 2019.06.03 |
[NestJS 기반 게시판 REST API 만들기] 3. 회원가입 및 로그인, 파라미터 검증 및 예외 처리 (6) | 2019.05.08 |
[NestJS 기반 게시판 REST API 만들기] 1. 프로젝트 환경 구축 (12) | 2019.04.17 |