1. ORM
- ORM (객체 관계 매핑, Object Relational Mapping)
- 객체 지향 프로그래밍 언어에서 사용되는 객체와 관계형 데이터베이스 간의 불일치를 해결하기 위한 기술
- 객체 모델과 관계형 데이터베이스의 테이블 간의 매핑을 수행하여 개발자가 SQL 쿼리 대신 객체 지향 코드를 사용할 수 있도록 함
(데이터 베이스의 모든 쿼리를 객체로 만들어서 실행하는 매개체, Node.js에도 노드로 존재) - ODM(객체 문서 매핑, Object Document Mapping)
- NoSQL 데이터베이스와 객체 지향 프로그래밍 언어 간의 매핑을 제공하는 기술
- 주로 문서 지향 데이터베이스(MongoDB)와 함께 사용
(SQL 문법을 사용하지 않고 자바스크립트, 트리로 데이터를 넣는 방법)
2. Branch
- 현재 작업중인 브랜치 확인(목록확인)
git branch
* master
* 표시: 현재 작업중인 브랜치
|
- branch 생성하기
git branch [브랜치 이름]
- Master로 작업하다가 다른 branch 전환하기
git switch [브랜치 이름]
git checkout [브랜치 이름]
- checkout : 있으면 이동, 없으면 생성 |
- branch 생성과 동시에 전환
git checkout -b [브랜치 이름]
PS C:\Sarr\KDT\Web\Project\Server> git checkout -b mysql
Switched to a new branch 'mysql'
PS C:\Sarr\KDT\Web\Project\Server> git branch
master
* mysql
- mysql 모듈 설치
npm i mysql2
- sql 문법 사용가능 - table 단위로 처리: table 생성해야 함 : workbench로 이동 |
- Workbench에서 Table 생성
(폴더ㅣ server > script.sql 파일 생성)
|
3. DB와 연결하기
- db > database.js 생성
< database.js >
import mysql from 'mysql2';
import { config } from '../config.js';
const pool = mysql.createPool({
host: config.db.host,
port: config.db.port,
user: config.db.user,
database: config.db.database,
password: config.db.password
});
export const db = pool.promise();
- config.js 에 db 추가
< config.js >
db: {
host: required('DB_HST'),
user: required('DB_USER'),
database: required('DB_DATABASE'),
password: required('DB_PASSWORD'),
port: required('DB_PROT')
}
- .env 추가
< .env >
# DB
DB_DATABASE=kdt //추가
- app.js 연결 확인하고 삭제(주석처리)
< app.js >
import { db } from '.db/database.js'; //추가
db.getConnection().then(connection => console.log(connection)); //추가
- npm start 확인
4. 회원가입, 중복확인
- data > auth.js 변경
< auth.js >
//아이디 (username) 중복검사
export async function findByUsername(username){
return db.execute('selet * from users where username = ?', [username]).then
((result)=> result);
}
//id 중복검사
export async function findById(id){
return db.execute('selet * from users where id = ?', [id]).then((result)=> result);
}
//회원가입
export async function createUser(user){
const {username, password, name, email, url} = user;
return db.execute('insert into users (username,password, name, email, url) values (?,?,?,?,?)',
[username, password, name, email, url]).then((result)=>result);
[username, password, name, email, url]).then((result)=>result);
- 회원가입, 중복검사 오류수정
더보기
1. password -> hashed
2. controllar>auth.js 주석처리
3. terminal 확인
% 확인) 찍어보기
4. data > auth.js 수정
5. controlar > auth.js 수정
!! 회원가입, 중복체크 완료 !!
- Postman 확인
* 회원가입 완료 * 중복검사 + 회원가입 |
- SQL 확인
5. 로그인, 본인확인
- controllar > auth.js 변경
< controllar > auth.js >
// 로그인하는 함수
export async function login(req, res, next){
const {username, password} = req.body;
// const user = await authRepository.login(username);
const user = await authRepository.findByUsername(username);
console.log(user);
if(!user){
return res.status(401).json({message: `아이디를 찾을 수 없음`});
}
const isValidpassword = await bcrypt.compareSync(password, user.password);
if(!isValidpassword){
return res.status(401).json({message: `비밀번호가 틀렸음`});
}
const token = createJwtToken(user.id);
res.status(200).json({token, username});
}
- data > auth.js 변경
< data > auth.js >
import { db } from '../db/database.js';
//아이디 (username) 중복검사
export async function findByUsername(username){
return db.execute('select * from users where username = ?', [username]).then((result) => {
console.log(result);
return result[0][0];
});
}
//id 중복검사
export async function findById(id){
return db.execute('select * from users where id = ?', [id]).then((result) => {
console.log(result);
return result[0][0];
});
}
//회원가입
export async function createUser(user){
console.log(user);
const {username, hashed, name, email, url} = user;
return db.execute('insert into users (username, password, name, email, url) values (?, ?, ?, ?, ?)', [username, hashed, name, email, url]).then((result) => {
console.log(result); // result[0].insertId
return result[0].insertId;
});
}
// //로그인
// export async function login(username){
// return users.find((users) => users.username === username);
// }
|
6. DB와 tweet 연결하기
- data > tweet.js
: 데이터 삭제, 코드 추가
< data > tweet.js >
import { db } from '../db/database.js';
const SELECT_JOIN = 'select tw.id, tw.text, tw.createdAt, tw.userId, us.username, us.email, us.url from tweets as tw join users as us on tw.userId = us.id';
const ORDER_DESC = 'order by tw.createdAt desc';
- data > tweet.js
: 코드 변경
< data > tweet.js >
// 모든 트윗을 리턴
export async function getAll() {
return db.execute(`${SELECT_JOIN} ${ORDER_DESC}`).then((result) => {
console.log(result);
return result;
});
}
// 해당 아이디에 대한 트윗을 리턴
export async function getAllByUsername(username){
return db.execute(`${SELECT_JOIN} where username = ? ${ORDER_DESC}`, [username]).then((result) => {
console.log(result);
return result;
});
}
// 글번호에 대한 트윗을 리턴
export async function getById(id){
return db.execute(`${SELECT_JOIN} where tw.id = ? ${ORDER_DESC}`, [id]).then((result) => {
console.log(result);
return result;
});
}
// 트윗을 작성
export async function create(text, userId){
return db.execute('insert into tweets (text, userId) values (?, ?)', [text, userId]).then((result) => {
console.log(result);
return getById(result[0].insertId);
});
}
// 트윗을 변경
export async function update(id, text){
return db.execute('update tweets set text = ? where id = ?', [text, id]).then((result) => {
console.log(result);
return getById(id);
});
}
// 트윗을 삭제
export async function remove(id){
return db.execute('delete from tweets where id = ?', [id]);
}
- data > tweet.js 원래 코드
- controllar > auth.js 변경
< controllar > auth.js >
// 트윗을 생성하는 함수
export async function createTweet(req, res, next) {
const { text } = req.body;
const tweet = await tweetRepository.create(text, req.userId);
res.status(201).json(tweet);
}
</js >
* 원래 코드 |
- Postman으로 확인하기
* 로그인해서 나온 토큰 넣기 * 트윗 생성하기 * 생성한 트윗 확인 * 트윗 변경하기 * 변경한 트윗 확인 * 트윗 삭제하기 |
- git 에 commit하기
더보기
'MYSQL 적용'으로 커밋
❗ 전체코드
- controllar 폴더
더보기
- auth.js
import * as authRepository from '../data/auth.js';
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import { config } from '../config.js';
//삭제
//const secretKey = "abcd1234%^&*" ;
//const jwtExpiresInDays = '2d';
//const bcryptSaltRounds = 10;
/*
문제
jwt.js를 참고하여 controller/auth.js 에 토큰을 발행하고 login()에 로그인 완료되면 클라이언트에 토큰을 출력하는 프로세스를 만들어보자
*/
// jwt 토근생성
function createJwtToken(id){
return jwt.sign({id}, config.jwt.secretKey, {expiresIn: config.jwt.expiresInSec});
}
/*
문제.
회원가입시 아이디 중복체크 하기
단. 중복이라면 409을 리턴
*/
// 회원가입 함수
export async function signup(req, res, next){
const {username, password, name, email, url} = req.body;
const found = await authRepository.findByUsername(username);
if(found){
return res.status(409).json({message:`${username}이 이미 있습니다`});
}
const hashed = await bcrypt.hash(password, config.bcrypt.saltRounds);
const userId = await authRepository.createUser({username, hashed, name, email, url});
const token = createJwtToken(userId);
res.status(201).json({token, username});
}
/*
문제
controller/auth.js 에서 login()를 bcrypt를 적용하여 로그인 프로세스를 만들어보자
*/
// 로그인하는 함수
export async function login(req, res, next){
const {username, password} = req.body;
// const user = await authRepository.login(username);
const user = await authRepository.findByUsername(username);
console.log(user);
if(!user){
return res.status(401).json({message: `아이디를 찾을 수 없음`});
}
const isValidpassword = await bcrypt.compareSync(password, user.password);
if(!isValidpassword){
return res.status(401).json({message: `비밀번호가 틀렸음`});
}
const token = createJwtToken(user.id);
res.status(200).json({token, username});
}
// export async function verify(req, res, next){
// const token = req.header['Token'];
// if(token){
// res.status(200).json(token);
// }
// }
//me
export async function me(req, res, next){
const user = await authRepository.findById(req.userId);
console.log(user);
if(!user){
return res.status(404).json({message: `일치하는 사용자가 없음`});
}
res.status(200).json({token: req.token, username: user.username});
}
- tweets.js
import * as tweetRepository from '../data/tweet.js';
// 여러 트윗을 가져오는 함수
export async function getTweets(req, res){
const username = req.query.username;
const data = await (username ? tweetRepository.getAllByUsername(username)
: tweetRepository.getAll());
res.status(200).json(data);
}
// 하나의 트윗을 가져오는 함수
export async function getTweet(req, res, next) {
const id = req.params.id;
const tweet = await tweetRepository.getById(id);
if(tweet){
res.status(200).json(tweet);
}else{
res.status(404).json({message: `${id}의 트윗이 없습니다`})
}
}
// 트윗을 생성하는 함수
export async function createTweet(req, res, next) {
const { text } = req.body;
const tweet = await tweetRepository.create(text, req.userId);
res.status(201).json(tweet);
}
// 트윗을 변경하는 함수
export async function updateTweet(req, res, next) {
const id = req.params.id;
const text = req.body.text;
const tweet = await tweetRepository.update(id, text);
if(tweet){
res.status(201).json(tweet);
}else{
res.status(404).json({message: `${id}의 트윗이 없습니다`})
}
}
// 트윗을 삭제하는 함수
export async function deleteTweet(req, res, next) {
const id = req.params.id;
await tweetRepository.remove(id);
res.sendStatus(204);
}
- data 폴더
더보기
- auth.js
import { db } from '../db/database.js';
//아이디 (username) 중복검사
export async function findByUsername(username){
return db.execute('select * from users where username = ?', [username]).then((result) => {
console.log(result);
return result[0][0];
});
}
//id 중복검사
export async function findById(id){
return db.execute('select * from users where id = ?', [id]).then((result) => {
console.log(result);
return result[0][0];
});
}
//회원가입
export async function createUser(user){
console.log(user);
const {username, hashed, name, email, url} = user;
return db.execute('insert into users (username, password, name, email, url) values (?, ?, ?, ?, ?)', [username, hashed, name, email, url]).then((result) => {
console.log(result); // result[0].insertId
return result[0].insertId;
});
}
// //로그인
// export async function login(username){
// return users.find((users) => users.username === username);
// }
- tweets.js
import { db } from '../db/database.js';
const SELECT_JOIN = 'select tw.id, tw.text, tw.createdAt, tw.userId, us.username, us.name, us.email, us.url from tweets as tw join users as us on tw.userId = us.id';
const ORDER_DESC = 'order by tw.createdAt desc';
// 모든 트윗을 리턴
export async function getAll() {
return db.execute(`${SELECT_JOIN} ${ORDER_DESC}`).then((result) => {
console.log(result);
return result;
});
}
// 해당 아이디에 대한 트윗을 리턴
export async function getAllByUsername(username){
return db.execute(`${SELECT_JOIN} where username = ? ${ORDER_DESC}`, [username]).then((result) => {
console.log(result);
return result;
});
}
// 글번호에 대한 트윗을 리턴
export async function getById(id){
return db.execute(`${SELECT_JOIN} where tw.id = ? ${ORDER_DESC}`, [id]).then((result) => {
console.log(result);
return result;
});
}
// 트윗을 작성
export async function create(text, userId){
return db.execute('insert into tweets (text, userId) values (?, ?)', [text, userId]).then((result) => {
console.log(result);
return getById(result[0].insertId);
});
}
// 트윗을 변경
export async function update(id, text){
return db.execute('update tweets set text = ? where id = ?', [text, id]).then((result) => {
console.log(result);
return getById(id);
});
}
// 트윗을 삭제
export async function remove(id){
return db.execute('delete from tweets where id = ?', [id]);
}
- db 폴더
더보기
- database.js
import mysql from 'mysql2';
import { config } from '../config.js';
const pool = mysql.createPool({
host: config.db.host,
port: config.db.port,
user: config.db.user,
database: config.db.database,
password: config.db.password
});
export const db = pool.promise();
- middleware 폴더
더보기
- auth.js
import jwt from 'jsonwebtoken';
import * as authRepository from '../data/auth.js';
const AUTH_ERROR = {message: "인증에러"};
export const isAuth = async (req, res, next) => {
const authHeader = req.get('Authorization');
console.log(authHeader);
if(!(authHeader && authHeader.startsWith('Bearer '))){
console.log('에러1');
return res.status(401).json(AUTH_ERROR);
}
const token = authHeader.split(' ')[1];
jwt.verify(
token, 'abcd1234%^&*', async(error, decoded) => {
if(error){
console.log('에러2');
return res.status(401).json(AUTH_ERROR);
}
const user = await authRepository.findById(decoded.id);
if(!user){
console.log('에러3');
return res.status(401).json(AUTH_ERROR);
}
req.userId = user.id;
next();
}
);
}
- validator.js (동일)
import { validationResult } from 'express-validator';
export const validate = (req, res, next) => {
const errors = validationResult(req);
if(errors.isEmpty()){
return next();
}
return res.status(400).json({message:errors.array()[0].msg})
}
- router 폴더
더보기
- auth.js
import express from 'express';
import { body } from 'express-validator';
import * as authController from '../controller/auth.js';
import { validate } from '../middleware/validator.js';
import { isAuth } from '../middleware/auth.js';
const router = express.Router();
const validateLogin = [
body('username').trim().notEmpty().withMessage('username을 입력하세요'),
body('password').trim().isLength({min:4}).withMessage('password는 최소 4자 이상 입력하세요'), validate
];
const validateSignup = [
... validateLogin,
body('name').trim().notEmpty().withMessage('name을 입력하세요'),
body('email').isEmail().withMessage('이메일 형식을 확인하세요'),
body('url').isURL().withMessage('URL 형식을 확인하세요'), validate
]
router.post('/signup', validateSignup, authController.signup);
router.post('/login', authController.login);
router.get('/me', isAuth, authController.me);
export default router;
- tweets.js
import express from "express";
import * as tweetController from '../controller/tweet.js';
import { body } from 'express-validator';
import { validate } from "../middleware/validator.js";
import { isAuth } from "../middleware/auth.js"
const router = express.Router();
/*
Post, Put에 text에 대해 빈문자열을 없애고, 최소 3자 이상 입력해야 데이터를 저장하도록 API에 적용
*/
const validateTweet = [
body('text').trim().isLength({min: 3}).withMessage('최소 3자 이상 입력'), validate
]
// 해당 아이디에 대한 트윗 가져오기
// GET
// http://localhost:8080/tweets?username=:username
router.get('/', isAuth, tweetController.getTweets);
// 글번호에 대한 트윗 가져오기
// GET
// http://localhost:8080/tweets/:id
router.get('/:id', isAuth, tweetController.getTweet);
// 트윗하기
// POST
// http://localhost:8080/tweets
// name, username, text
// json 형태로 입력 후 추가된 데이터까지 모두 json으로 출력
router.post('/', validateTweet, isAuth, tweetController.createTweet);
// 트윗 수정하기
// PUT
// http://localhost:8080/tweets/:id
// id, username, text
// json 형태로 입력 후 변경된 데이터까지 모두 json으로 출력
router.put('/:id', validateTweet, isAuth, tweetController.updateTweet);
// 트윗 삭제하기
// DELETE
// http://localhost:8080/tweets/:id
router.delete('/:id', isAuth, tweetController.deleteTweet);
export default router;
- app.js
더보기
import express from "express";
import morgan from "morgan";
import tweetsRouter from './router/tweets.js';
import authRouter from './router/auth.js';
import { config } from './config.js';
// import { db } from './db/database.js'; //추가
const app = express();
app.use(express.json());
app.use(morgan("dev"));
app.use('/tweets', tweetsRouter);
app.use('/auth', authRouter);
app.use((req, res, next) => {
res.sendStatus(404);
});
// db.getConnection().then(connection => console.log(connection)); //추가
app.listen(config.host.port);
- .env
더보기
# DB
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USER=root
DB_PASSWORD=1234
DB_DATABASE=kdt
# JWT
JWT_SECRET=abcd1234%^&*
JWT_EXPIRE_SEC=172800
# BCRYPT
BCRYPT_SALT_ROUNDS=10
# SERVER
PORT=8080
- .ignore
더보기
node_modules/
.gitignore
.env
package-lock.json
memo.txt
validation.js
bcrypt.js
jwt.js
client.html
server.js
script.sql
- bycrpt.js (동일)
더보기
import * as bcrypt from "bcrypt";
const password = 'abcd1234';
const hashed = bcrypt.hashSync(password, 10)
//hashSync(매개변수, 솔트값) // 솔트값: 숫자가 높을 수록 속도가 느림 // 10이하 추천
console.log(`password: ${password}, hashed: ${hashed}`);
const result = bcrypt.compareSync('abcd1234',hashed);
console.log(result);
- client.html (동일)
더보기
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>클라이언트</title>
<script src="https://cdn.socket.io/4.7.5/socket.io.min.js" integrity="sha384-2huaZvOR9iDzHqslqwpR87isEmrfxqyWOF7hr7BY6KG0+hVKLoEXMPUJw3ynWuhO" crossorigin="anonymous"></script>
<script>
const socket = io();
function setNickname(){
const nickname = document.getElementById('nickname').value;
socket.emit('setNickname', nickname);
}
function sendMessage(){
const message = document.getElementById('message').value;
socket.emit('message', message);
}
function addEmoji(emoji){
const message = document.getElementById('message');
message.value += emoji;
}
function setChannel(){
const channel = document.getElementById('channel').value;
socket.emit('setChannel', channel);
}
// 메세지 수신 이벤트 처리
socket.on('setNickname', (message) => {
const chatBox = document.getElementById('chatBox');
const newMessage = document.createElement('p');
newMessage.textContent = message;
chatBox.appendChild(newMessage);
});
socket.on('message', (message) => {
console.log(message);
const chatBox = document.getElementById('chatBox');
const newMessage = document.createElement('p');
newMessage.textContent = `${message.sender}: ${message.message}`;
chatBox.appendChild(newMessage);
document.getElementById('message').value = '';
});
socket.on('updateChannelList', (channelList) => {
const channelListElement = document.getElementById('channelList');
channelListElement.innerHTML = '';
channelList.forEach((channel) => {
const channelItem = document.createElement('li');
channelItem.textContent = channel;
channelListElement.appendChild(channelItem);
});
})
</script>
</head>
<body>
<h2>간단한 채팅</h2>
<form>
<p>닉네임: <input type="text" id="nickname"> <button type="button" onclick="setNickname()">설정</button></p>
<p>채널: <input type="text" id="channel"> <button type="button" onclick="setChannel()">입장</button></p>
<p><ul id="channelList"></ul></p>
<p><input type="text" id="message"> <button type="button" onclick="sendMessage()">보내기</button> <button type="button" onclick="addEmoji('😎')">😎</button> <button type="button" onclick="addEmoji('🎃')">🎃</button> <button type="button" onclick="addEmoji('😛')">😛</button> <button type="button" onclick="addEmoji('😊')">😊</button> <button type="button" onclick="addEmoji('🤣')">🤣</button></p>
</form>
<div id="chatBox"></div>
</body>
</html>
- config.js(동일)
더보기
import dotenv from 'dotenv';
dotenv.config();
function required(key, defaultValue=undefined){
const value = process.env[key] || defaultValue
// process.env() : 시스템에 접근 관련한 모듈
// env 다룰 수 있는 기능이 들어있음
// 먼저 전달받은 키가 있는지 확인,
// or 앞의 값이 True로 판별되면 앞의 값이 대입,
// or 앞의 값이 False로 판별되면 뒤의 값이 대입
if(value == null){
throw new Error(`키 ${key}는 undefined!!`);
}
return value;
}
//외부에서 가져다 쓸 수 있게 작성
export const config = {
jwt: {
secretKey: required('JWT_SECRET'),
expiresInSec: parseInt(required('JWT_EXPIRES_SEC', 172800))
},
bcrypt: {
saltRounds: parseInt(required('BCRYPT_SALT_ROUNDS', 10))
},
host: {
port: parseInt(required('HOST_PORT', 8080))
},
db: {
host: required('DB_HOST'),
user: required('DB_USER'),
database: required('DB_DATABASE'),
password: required('DB_PASSWORD'),
port: required('DB_PORT')
}
}
- jwt.js(동일)
더보기
import jwt from 'jsonwebtoken';
const secret='abcdefg1234%^&*';
const token = jwt.sign(
{
id:'apple',
isAdmin:false
},
secret,
{expiresIn: "1h"} // 얼마만큼 토근이 유지될 것인가
);
//expiresIn: "1h"
//expiresIn: 2 유지되다 에러
setTimeout(()=>{
jwt.verify(token,secret,(error,decoded)=>{
console.log(error,decoded);
});
}, 3000); // 3초마다 찍어주기
console.log(token);
// 일단 토큰찍고 4초 뒤에 set timeout에서 토큰, 시크릿 확인해보니 에러
// (4초 지나서 만료시간 지남 jwt expired)
// 2초로 바꾸면 decoded 잘 뜸
- script.sql(추가)
더보기
use kdt;
drop table tweets;
create table users (
id int auto_increment primary key,
username varchar(50) unique not null,
password varchar(150) not null,
name varchar(50) not null,
email varchar(50) not null,
url varchar(200)
);
create table tweets (
id int auto_increment primary key,
userId int,
createdAt datetime default now(),
text varchar(2000) not null,
foreign key(userId) references users(id)
);
select * from users;
select * from tweets;
delete from users where username='apple';
- server.js
더보기
import express from 'express';
import http from 'http';
import { Server } from 'socket.io';
import path from 'path';
import { fileURLToPath } from 'url';
import { channel } from 'diagnostics_channel';
const app = express();
const server = http.createServer(app);
const io = new Server(server);
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// 정적 파일 서빙
// localhost:8080/client.html
app.use(express.static(__dirname));
const channels = new Set(); //추가
io.on('connection', (socket) => {
console.log('사용자가 연결되었습니다');
let nickname = '';
let channel = ''; //추가
// 닉네임 설정
socket.on('setNickname', (name) => {
nickname = name;
console.log(`닉네임 설정: ${nickname}`);
io.emit('setNickname', `알림: 닉네임 설정됨 ${nickname}`);
});
// 메세지 설정
socket.on('message', (message) => {
console.log(`클라이언트: ${nickname} -> ${message}`)
io.to(channel).emit('message', {sender: nickname, message})
});
//채널 설정 //추가
socket.on('setChannel', (ch) => {
channel = ch;
socket.join(channel);
channels.add(channel);
console.log(`클라이언트: ${nickname}님이 채널 ${channel}에 입장`);
io.emit('updateChannelList', Array.from(channels))
});
// 소켓 종료
socket.on('disconnect', () => {
console.log(`클라이언트: ${nickname} 접속 종료`)
});
});
server.listen(8080, () => {
console.log('서버가 8080포트에서 실행중!!');
})
- validation.js(동일)
더보기
import express from 'express';
import { body, param, validationResult } from "express-validator";
const app = express();
app.use(express.json());
const validate = (req, res, next) => {
const errors = validationResult(req);
if(errors.isEmpty()){
return next();
}
console.log(errors.array());
return res.status(400).json({message: errors.array()[0].msg});
}
app.get('/:email', [param('email').isEmail().withMessage('이메일을 입력하세요!'), validate], (req, res, next) => {
res.send(':연애편지:');
});
//[]: validation 기능을 안에다 쓸 수 있다
// 메서드 체이닝으로 벨리데이션 쓰기
// trim: 공백 없애기
// isLength: 최대최소 설정
// post: 자료를 bbody로 받음
// get: param로 받음
app.post('/users', [
body('name').trim().isLength({min:2}).withMessage('이름은 두글자 이상으로 입력!'),
body('age').isInt().withMessage('나이는 숫자로 입력!'),
body('height').isInt({min:100, max:200}).withMessage('키는 100이상 200이하로 입력하세요!'),
body('job').notEmpty(),
validate
], (req, res, next) => {
console.log(req.body);
res.sendStatus(201);
})
app.listen(8080);
'Web > Node.js' 카테고리의 다른 글
18. MongoDB (0) | 2024.05.09 |
---|---|
17. Sequelize (0) | 2024.05.08 |
15. 환경변수, 웹소켓 (0) | 2024.05.03 |
14. Postman 정리, 아이디 중복체크 (0) | 2024.05.02 |
13. Authentication, bcrypt, JWT (0) | 2024.04.29 |