๊ธฐ์กด๊น์ง๋ nest.js์ ๊ตฌ์กฐ์ ๋ง์ถฐ ์ํคํ ์ฒ ์ ๊ฒฝ ์์ฐ๊ณ ๊ตฌํ์๋ง ์ ๊ฒฝ ์ผ์๋๋ฐ ์ง๊ธ ํ์ฌ์์ ์๊ตฌํ๋ ์ํคํ ์ฒ๋ mvc ํจํด์ด์๊ณ , TypeORM์ ์์จ์ orm ์์ด ์ด๋ป๊ฒ mysql ์ฐ๊ฒฐํ ์ง๋ถํฐ ๋ง๋งํ๋ค.
1. Nest.js, MySQL ์ฌ์ฉํด์ MVC ํจํด ๊ตฌ์กฐ ์ง๊ธฐ
- nestjs mvc ํจํด ๋ฌธ์๋ฅผ ๋ณด๋ ์ ๋ทฐ๋จ๋ง ์ฐ๊ฒฐํด์ฃผ๊ณ ๋ง๋๊ฑด๋ฐ..(๋ด๊ฐ ๊ถ๊ธํ๊ฑด model์ธ๋)
- ์ผ๋จ ์ฐธ๊ณ ํด์ ๋๋ ํ ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ๊ณ model์ ๋นผ๊ณ service ํ์ผ ๋ถ๋ถ์ model์ด ๋ด๋นํ๋ ๊ธฐ๋ฅ๋ค์ ๋ค ์ถ๊ฐํด์ฃผ์๋ค.
- entity(typeorm ๋ฐฉ์)๋ ์ฌ์ฉํ์ง ์์๋ค.
- ๋ทฐ ํ ํ๋ฆฟ์ ejs๋ฅผ ์ฌ์ฉํ๋ค.
- fastify ์ฌ์ฉํ ๋ถ๋ถ๋ง ์์ด์ ๋ค๋ฅธ ๊ณณ์์๋ ์ฐพ์๋ดค๋๋ฐ ์ ์ผ ๋์ ๋์๋๊ฑด ์ด ์ ํ๋ธ ์์์ด์๋ค.
https://youtu.be/2h5NSwZ6neA?si=ZeQfCHsLiZU2PCfJ
2. MVC ํจํด
Model
- ๋ฐ์ดํฐ ๊ฐ๊ณต ๋ด๋น
View
- ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ง๋ ๋ถ๋ถ
Controller
- Model๊ณผ View๋ฅผ ์ด์ด์ฃผ๋ ์ฐ๊ฒฐ๋ค๋ฆฌ ์ญํ
3. DTO
- ์์ํ๊ฒ ๋ฐ์ดํฐ ์ ๋ฌ๋ง์ ๋ด๋นํ๋ ๊ฐ์ฒด

4. ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ


DTO(๋ฐ์ดํฐ ์ ๋ฌ ๊ฐ์ฒด)
- ๊ฐ๋จํ๊ฒ name, email, password๋ง ์ฃผ๊ณ ๋ฐ์๊ฑฐ๋ค.
export class CreateUserDto {
name: string;
email: string;
password: string;
}
Controller
/user/create | ์ ์ ์์ฑ |
/user/all | ์ ์ ์ ์ฒด ์กฐํ |
/user/find | ํน์ ์ ์ ์กฐํ(์ด๋ฉ์ผ ์ฌ์ฉ) |
import { Controller, Get, Post, Body } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UserService } from './user.service';
@Controller('user')
export class UserController {
constructor(private readonly userService: UserService) {}
// ์ ์ ์์ฑ
@Post('create')
async create(@Body() createUserDto: CreateUserDto) {
return await this.userService.create(createUserDto);
}
// ์ ์ ์ ์ฒด ์กฐํ
@Get('all')
async findAll() {
const users = await this.userService.findAll();
return { users };
}
// ํน์ ์ ์ ์กฐํ(์ด๋ฉ์ผ ์ฌ์ฉ)
@Post('find')
async findOne(@Body() data: object) {
const email = JSON.stringify(Object.values(data)[0]);
const user = await this.userService.findOneByEmail(email);
return { user };
}
}
Model, Service
- typeorm์ ์ฐ์ง ์๊ณ mysql ์ฐ๊ฒฐ ๋ฐ ์ฌ์ฉํด๋ณด๋๊ฒ ์ฌ๋ฌ ๋ชฉ์ ์ค ํ๋์๋ค.
- ๊ฐ์ฅ ๋์์ด ๋๋ ๊ธ์ ๊ณต์๋ฌธ์์๋ค.
https://sidorares.github.io/node-mysql2/docs/documentation/typescript-examples
Using MySQL2 with TypeScript | Quickstart
Installation
sidorares.github.io
import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { ConnectionOptions } from 'mysql2';
// mysql ์ฐ๊ฒฐ
const mysql = require('mysql2/promise');
const access: ConnectionOptions = {
host: '...',
user: '...',
password: '...',
database: '...',
port: 3306,
};
@Injectable()
export class UserService {
// ์ ์ ๋ฑ๋ก
async create(createUserDto: CreateUserDto) {
try {
const { name, email, password } = createUserDto;
const conn = mysql.createPool(access);
const sql =
'INSERT INTO `user`(`name`, `email`, `password`) VALUES (?, ?, ?)';
const values = [`${name}`, `${email}`, `${password}`];
const result = await conn.execute({
sql,
values,
});
return result;
} catch (err) {
console.log(err);
}
}
// ์ ์ ์ ์ฒด ์กฐํ
async findAll() {
try {
const conn = await mysql.createPool(access);
const findAllSql = 'SELECT * FROM user';
const users = await conn.query(findAllSql);
return users;
} catch (error) {
console.log(error);
}
}
// ํน์ ์ ์ ์์ด๋ ์กฐํ
async findOneById(id: number) {
try {
const conn = await mysql.createPool(access);
const findUserSql = 'SELECT * FROM `user` WHERE `id` = ' + id;
const user = await conn.query(findUserSql);
return user;
} catch (error) {
console.log(error);
}
}
// ํน์ ์ ์ ์ด๋ฉ์ผ ์กฐํ
async findOneByEmail(email: string) {
try {
const conn = await mysql.createPool(access);
const findUserSql = 'SELECT * FROM `user` WHERE `email` = ' + email;
const user = await conn.query(findUserSql);
return user[0];
} catch (error) {
console.log(error);
}
}
}
View
- ejs ํ ํ๋ฆฟ ์ฌ์ฉ
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<title>Basic Project</title>
</head>
<body>
<h1>BASIC PROJECT</h1>
<div class="inputWrap">
<div class="nameBox">
<p>name</p>
<input id="nameText" class="nameValue" type="text" />
</div>
<div class="emailBox">
<p>email</p>
<input id="emailText" class="emailValue" type="email" />
</div>
<div class="passwordBox">
<p>password</p>
<input id="passwordText" class="passwordValue" type="password" />
</div>
<button class="registerBtn">SIGN UP</button>
</div>
<br />
<hr />
<br />
<div class="findWrap">
<button class="findAllBtn">FIND ALL USER</button>
<div class="allUserBox"></div>
<div class="userTableWrap"></div>
<div class="emailBox">
<p>email</p>
<input id="findEmailValue" class="emailValue" type="email" />
<button class="findUserBtn">FIND USER</button>
<div class="userBox"></div>
</div>
</div>
<script src="/app.js"></script>
</body>
</html>
- app.controller.ts ํ์ผ์์ nest.js @Render() ๊ธฐ๋ฅ์ผ๋ก ๋ทฐ ํ์ด์ง ๋ ๋ํด์คฌ๋ค.
import { Body, Controller, Get, Post, Render, Req, Res } from '@nestjs/common';
import { AppService } from './app.service';
import { Response, Request } from 'express';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get('')
@Render('index')
getHello(): object {
return {};
}
}
๊ธฐ์กด๊น์ง๋ nest.js์ ๊ตฌ์กฐ์ ๋ง์ถฐ ์ํคํ ์ฒ ์ ๊ฒฝ ์์ฐ๊ณ ๊ตฌํ์๋ง ์ ๊ฒฝ ์ผ์๋๋ฐ ์ง๊ธ ํ์ฌ์์ ์๊ตฌํ๋ ์ํคํ ์ฒ๋ mvc ํจํด์ด์๊ณ , TypeORM์ ์์จ์ orm ์์ด ์ด๋ป๊ฒ mysql ์ฐ๊ฒฐํ ์ง๋ถํฐ ๋ง๋งํ๋ค.
1. Nest.js, MySQL ์ฌ์ฉํด์ MVC ํจํด ๊ตฌ์กฐ ์ง๊ธฐ
- nestjs mvc ํจํด ๋ฌธ์๋ฅผ ๋ณด๋ ์ ๋ทฐ๋จ๋ง ์ฐ๊ฒฐํด์ฃผ๊ณ ๋ง๋๊ฑด๋ฐ..(๋ด๊ฐ ๊ถ๊ธํ๊ฑด model์ธ๋)
- ์ผ๋จ ์ฐธ๊ณ ํด์ ๋๋ ํ ๋ฆฌ๋ฅผ ๊ตฌ์ฑํ๊ณ model์ ๋นผ๊ณ service ํ์ผ ๋ถ๋ถ์ model์ด ๋ด๋นํ๋ ๊ธฐ๋ฅ๋ค์ ๋ค ์ถ๊ฐํด์ฃผ์๋ค.
- entity(typeorm ๋ฐฉ์)๋ ์ฌ์ฉํ์ง ์์๋ค.
- ๋ทฐ ํ ํ๋ฆฟ์ ejs๋ฅผ ์ฌ์ฉํ๋ค.
- fastify ์ฌ์ฉํ ๋ถ๋ถ๋ง ์์ด์ ๋ค๋ฅธ ๊ณณ์์๋ ์ฐพ์๋ดค๋๋ฐ ์ ์ผ ๋์ ๋์๋๊ฑด ์ด ์ ํ๋ธ ์์์ด์๋ค.
https://youtu.be/2h5NSwZ6neA?si=ZeQfCHsLiZU2PCfJ
2. MVC ํจํด
Model
- ๋ฐ์ดํฐ ๊ฐ๊ณต ๋ด๋น
View
- ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ง๋ ๋ถ๋ถ
Controller
- Model๊ณผ View๋ฅผ ์ด์ด์ฃผ๋ ์ฐ๊ฒฐ๋ค๋ฆฌ ์ญํ
3. DTO
- ์์ํ๊ฒ ๋ฐ์ดํฐ ์ ๋ฌ๋ง์ ๋ด๋นํ๋ ๊ฐ์ฒด

4. ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ


DTO(๋ฐ์ดํฐ ์ ๋ฌ ๊ฐ์ฒด)
- ๊ฐ๋จํ๊ฒ name, email, password๋ง ์ฃผ๊ณ ๋ฐ์๊ฑฐ๋ค.
export class CreateUserDto {
name: string;
email: string;
password: string;
}
Controller
/user/create | ์ ์ ์์ฑ |
/user/all | ์ ์ ์ ์ฒด ์กฐํ |
/user/find | ํน์ ์ ์ ์กฐํ(์ด๋ฉ์ผ ์ฌ์ฉ) |
import { Controller, Get, Post, Body } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UserService } from './user.service';
@Controller('user')
export class UserController {
constructor(private readonly userService: UserService) {}
// ์ ์ ์์ฑ
@Post('create')
async create(@Body() createUserDto: CreateUserDto) {
return await this.userService.create(createUserDto);
}
// ์ ์ ์ ์ฒด ์กฐํ
@Get('all')
async findAll() {
const users = await this.userService.findAll();
return { users };
}
// ํน์ ์ ์ ์กฐํ(์ด๋ฉ์ผ ์ฌ์ฉ)
@Post('find')
async findOne(@Body() data: object) {
const email = JSON.stringify(Object.values(data)[0]);
const user = await this.userService.findOneByEmail(email);
return { user };
}
}
Model, Service
- typeorm์ ์ฐ์ง ์๊ณ mysql ์ฐ๊ฒฐ ๋ฐ ์ฌ์ฉํด๋ณด๋๊ฒ ์ฌ๋ฌ ๋ชฉ์ ์ค ํ๋์๋ค.
- ๊ฐ์ฅ ๋์์ด ๋๋ ๊ธ์ ๊ณต์๋ฌธ์์๋ค.
https://sidorares.github.io/node-mysql2/docs/documentation/typescript-examples
Using MySQL2 with TypeScript | Quickstart
Installation
sidorares.github.io
import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { ConnectionOptions } from 'mysql2';
// mysql ์ฐ๊ฒฐ
const mysql = require('mysql2/promise');
const access: ConnectionOptions = {
host: '...',
user: '...',
password: '...',
database: '...',
port: 3306,
};
@Injectable()
export class UserService {
// ์ ์ ๋ฑ๋ก
async create(createUserDto: CreateUserDto) {
try {
const { name, email, password } = createUserDto;
const conn = mysql.createPool(access);
const sql =
'INSERT INTO `user`(`name`, `email`, `password`) VALUES (?, ?, ?)';
const values = [`${name}`, `${email}`, `${password}`];
const result = await conn.execute({
sql,
values,
});
return result;
} catch (err) {
console.log(err);
}
}
// ์ ์ ์ ์ฒด ์กฐํ
async findAll() {
try {
const conn = await mysql.createPool(access);
const findAllSql = 'SELECT * FROM user';
const users = await conn.query(findAllSql);
return users;
} catch (error) {
console.log(error);
}
}
// ํน์ ์ ์ ์์ด๋ ์กฐํ
async findOneById(id: number) {
try {
const conn = await mysql.createPool(access);
const findUserSql = 'SELECT * FROM `user` WHERE `id` = ' + id;
const user = await conn.query(findUserSql);
return user;
} catch (error) {
console.log(error);
}
}
// ํน์ ์ ์ ์ด๋ฉ์ผ ์กฐํ
async findOneByEmail(email: string) {
try {
const conn = await mysql.createPool(access);
const findUserSql = 'SELECT * FROM `user` WHERE `email` = ' + email;
const user = await conn.query(findUserSql);
return user[0];
} catch (error) {
console.log(error);
}
}
}
View
- ejs ํ ํ๋ฆฟ ์ฌ์ฉ
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<title>Basic Project</title>
</head>
<body>
<h1>BASIC PROJECT</h1>
<div class="inputWrap">
<div class="nameBox">
<p>name</p>
<input id="nameText" class="nameValue" type="text" />
</div>
<div class="emailBox">
<p>email</p>
<input id="emailText" class="emailValue" type="email" />
</div>
<div class="passwordBox">
<p>password</p>
<input id="passwordText" class="passwordValue" type="password" />
</div>
<button class="registerBtn">SIGN UP</button>
</div>
<br />
<hr />
<br />
<div class="findWrap">
<button class="findAllBtn">FIND ALL USER</button>
<div class="allUserBox"></div>
<div class="userTableWrap"></div>
<div class="emailBox">
<p>email</p>
<input id="findEmailValue" class="emailValue" type="email" />
<button class="findUserBtn">FIND USER</button>
<div class="userBox"></div>
</div>
</div>
<script src="/app.js"></script>
</body>
</html>
- app.controller.ts ํ์ผ์์ nest.js @Render() ๊ธฐ๋ฅ์ผ๋ก ๋ทฐ ํ์ด์ง ๋ ๋ํด์คฌ๋ค.
import { Body, Controller, Get, Post, Render, Req, Res } from '@nestjs/common';
import { AppService } from './app.service';
import { Response, Request } from 'express';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get('')
@Render('index')
getHello(): object {
return {};
}
}