데이터베이스 : 관련성을 가지며 중복이 없는 데이터들의 집합
DBMS(Database Management System) : 데이터베이스를 관리하는 시스템
RDBMS(Relational DBMS) : 관계형 DBMS -> 많이 사용됨
- 대표적인 RDBMS : Oracle, MySQL, MSSQL => SQL 언어를 사용해 데이터를 관리
(1) 윈도
(2) 맥
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
$ brew install mysql
$ brew services start mysql
$ mysql_secure_installation
(3) 리눅스(우분투)
$ sudo apt-get update
$ sudo apt-get install -y mysql-server
$ sudo mysql_secure_installation
(1) 윈도
MySQL과 함께 워크벤치 설치했으므로 생략
(2) 맥
$ brew cask install mysqlworkbench
(3) 리눅스(우분투)
GUI를 사용하지 않으므로 워크벤치 설치하지 않음
(4) 커넥션 생성하기
(1) 데이터베이스 생성하기
CREATE SCHEMA [데이터베이스명] : 데이터베이스를 생성
+) DEFAULT CHARACTER SET utf8 : 한글 사용할 수 있게 만들고 싶을 때
use [데이터베이스명] : 앞으로 해당 데이터베이스를 사용하겠다는 것을 MySQL에 알림
예약어 : MySQL이 기본적으로 알고 있는 구문 ex) CREATE SCHEMA
- 소문자로 써도 되지만, 대문자 권장
(2) 테이블 생성하기
테이블 : 데이터가 들어갈 수 있는 틀 -> 테이블에 맞는 데이터만 들어갈 수 있음
CREATE TABLE [데이터베이스명.테이블명] (컬럼명 컬럼자료형 컬럼옵션, ...) : 테이블 생성
- use 데이터베이스명; 명령어를 실행하였다면 데이터베이스명은 생략 가능
컬럼 자료형
1) INT : 정수 / FLOAT, DOUBLE : 소수까지 저장
2) VARCHAR(자릿수) : 가변 길이 문자열
3) CHAR(자릿수) : 고정길이 문자열
4) TEXT : 긴 글을 저장 (VARCHAR 보다 길 때)
5) TINYINT : -128~127까지의 정수, 1 또는 0만 저장하면 Boolean과 같은 역할
6) DATETIME : 날짜와 시간
DATE : 날짜 정보, TIME : 시간 정보
컬럼 옵션
1) NULL/NOT NULL : 빈칸 허용 여부
2) AUTO_INCREMENT : 숫자 자동 부여
3) UNSIGNED : 음수가 나올 수 없음
4) ZEROFILL : 자릿수 중에 비어있는 자리에 모두 0을 넣음
5) DEFAULT : 데이터베이스에 저장 시 해당 컬럼에 값이 없다면 MySQL이 기본값을 대신 넣음
- CURRENT_TIMESTAMP / now() : 현재 시각을 넣음
6) PRIMARY KEY(컬럼명) : 해당 컬럼을 기본키(로우를 대표하는 고유한 값)로 설정함
7) UNIQUE INDEX 인덱스 이름 (컬럼명 조건): 해당 컬럼은 고유한 값이어야 함
테이블 자체 설정
1) COMMENT : 테이블에 대한 보충 설명
2) DEFAULT CHARACTER SET = utf8; : 한글이 입력될 수 있게 설정
3) ENGINE [MyISAM or InnoDB] : 엔진 지정
제약 조건
1) CONSTRAINT FOREIGN KEY(컬럼명) REFERENCES 참고할 테이블 명(참고할 컬럼 명) : 해당 컬럼에 다른 테이블의 기본키를 저장 -> 외래키
- ON UPDATE CASCADE : 정보가 수정되면 연결된 정보도 같이 수정됨
- ON DELETE CASCADE : 정보가 삭제되면 연결된 정보도 같이 삭제됨
DESC [테이블명] : 만들어진 테이블을 확인
DROP TABLE [테이블명] : 테이블 삭제
SHOW TABLES : 테이블 목록 확인
CRUD : Create, Read, Update, Delete의 첫 글자를 모은 두문자어 / 데이터베이스에서 많이 수행하는 네 가지 작업
(1) Create(생성)
Create(생성) : 데이터를 생성해서 데이터베이스에 넣는 작업
INSERT INTO 데이터베이스명.테이블명 (컬럼1, 컬럼2, ...) VALUES (컬럼1값, 컬럼2값, ...);
: 해당 테이블에 데이터 삽입
- use 데이터베이스명; 명령어를 사용했다면 데이터베이스명 생략 가능
(2) Read(조회)
Read(조회) : 데이터베이스에 있는 데이터를 조회하는 작업
SELECT * FROM [테이블명] : 테이블의 모든 데이터를 조회
SELECT [특정컬럼] FROM [테이블명] WHERE [조건] ORDER BY [컬럼명] [ASC|DESC]
: 테이블에서 조건에 해당하는 컬럼만 조회하는데 특정 컬럼의 오름차순 혹은 내림차순으로 정렬
- LIMIT [숫자] : 조회할 로우 개수 설정
- OFFSET [건너뛸 숫자] : 건너뛸 로우 개수 설정
(3) Update(수정)
Update(수정) : 데이터베이스에 있는 데이터를 수정하는 작업
UPDATE [테이블명] SET [컬럼명=바꿀 값] WHERE [조건]
: 테이블에서 조건에 해당하는 로우의 컬럼 값만 원하는 값으로 수정
(4) Delete(삭제)
Delete(삭제) : 데이터베이스에 있는 데이터를 삭제하는 작업
DELETE FROM [테이블명] WHERE [조건] : 테이블에서 조건에 해당하는 로우를 제거
시퀄라이즈 : 노드와 MySQL을 연동해주고 SQL문을 작성하는 것을 도와주는 라이브러리
- ORM(Object-relational Mapping)으로 분류
-> ORM : 자바스크립트 객체와 데이터베이스의 릴레이션을 매핑해주는 도구
- 다른 데이터베이스도 같이 쓸 수 있어서, 프로젝트를 다른 SQL 데이터베이스로 전환할 때도 편리
=> 자바스크립트 구문을 알아서 SQL로 바꿔주기 때문
1) sequelize와 sequelize-cli, mysql2 패키지 설치
$ npm i express morgan nunjucks sequelize sequelize-cli mysql2
$ npm i -D nodemon
2) 설치 완료 후 sequelize init 명령어 호출
$ npx sequelize init
3) models 폴더 안의 index.js 코드 수정
(1) MySQL 연결하기
const express = require("express");
const path = require("path");
const morgan = require("morgan");
const nunjucks = require("nunjucks");
const { sequelize } = require("./models");
const app = express();
app.set("port", process.env.PORT || 3001);
app.set("view engine", "html");
nunjucks.configure("views", {
express: app,
watch: true,
});
sequelize
.sync({ force: false })
.then(() => {
console.log("데이터베이스 연결 성공");
})
.catch((err) => {
console.error(err);
});
app.use(morgan("dev"));
app.use(express.static(path.join(__dirname, "public")));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use((req, res, next) => {
const error = new Error(`${req.method} ${req.url} 라우터가 없습니다.`);
error.status = 404;
next(error);
});
app.use((err, req, res, next) => {
res.locals.message = err.message;
res.locals.error = process.env.NODE_ENV !== "production" ? err : {};
res.status(err.status || 500);
res.render("error");
});
app.listen(app.get("port"), () => {
console.log(app.get("port"), "번 포트에서 대기 중");
});
{
"development": {
"username": "root",
"password": "[root 비밀번호]",
"database": "nodejs",
"host": "127.0.0.1",
"dialect": "mysql"
},
"test": {
"username": "root",
"password": null,
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
=> 배포 환경(process.env.NODE_ENV가 production)을 위해 데이터베이스 설정할 때는 config/config.json의 production 속성을 수정
=> 테스트 환경(process.env.NODE_ENV가 test) 일 때는 test 속성을 수정
(2) 모델 정의하기
시퀄라이즈의 역할 : 시퀄라이즈의 모델과 MySQL의 테이블을 연결
=> MySQL의 테이블이 시퀄라이즈의 모델과 대응됨
시퀄라이즈 모델의 메서드
1) static init 메서드 : 테이블에 대한 설정
- super.init 메서드
1. 첫 번째 인수 : 테이블 컬럼에 대한 설정
-> MySQL 테이블과 컬럼 내용이 일치해야 정확하게 대응됨
2. 두 번째 인수 : 테이블 자체에 대한 설정
2) static associate 메서드 : 다른 모델과의 관계 기재
시퀄라이즈의 컬럼 자료형
1) INTEGER : MySQL의 INT
2) STRING : MySQL의 VARCHAR
3) BOOLEAN : MySQL의 TINYINT
4) DATE : MySQL의 DATETIME
시퀄라이즈의 컬럼 옵션
1) 자료형.UNSIGNED : UNSIGNED 옵션이 적용된 자료형
2) 자료형.ZEROFILL : ZEROFILL 옵션이 적용된 자료형
3) allowNull : NOT NULL 옵션과 동일
- false : NOT NULL
- true : NULL 허용
4) unique : UNIQUE 옵션
- true : UNIQUE
5) defaultValue : 기본값(DEFAULT)
시퀄라이즈의 테이블 옵션
1) sequelize : static init 메서드의 매개변수와 연결되는 옵션, db.sequelize 객체를 넣어야 함
2) timestamps
- true : 시퀄라이즈에서 createdAt, updatedAt 컬럼을 추가 (시간이 자동으로 입력됨)
- false : 자동으로 날짜 컬럼을 추가하는 기능 해제
3) underscored
- true : 테이블명과 컬럼명을 스네이크 케이스로 바꿈
- false : 테이블명과 컬럼명을 캐멀 케이스로 만듦
4) modelName : 모델 이름 설정 -> 노드 프로젝트에서 사용
5) tableName : 실제 데이터베이스의 테이블 이름
6) charset, collate : utf8과 utf8_general_ci로 설정해서 한글이 입력되게 함
const Sequelize = require("sequelize");
module.exports = class User extends Sequelize.Model {
static init(sequelize) {
return super.init(
{
name: {
type: Sequelize.STRING(20),
allowNull: false,
unique: true,
},
age: {
type: Sequelize.INTEGER.UNSIGNED,
allowNull: false,
},
married: {
type: Sequelize.BOOLEAN,
allowNull: false,
},
comment: {
type: Sequelize.TEXT,
allowNull: true,
},
created_at: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.NOW,
},
},
{
sequelize,
timestamps: false,
underscored: false,
modelName: "User",
tableName: "users",
paranoid: false,
charset: "utf8",
collate: "utf8_general_ci",
}
);
}
static associate(db) {}
};
const Sequelize = require("sequelize");
module.exports = class Comment extends Sequelize.Model {
static init(sequelize) {
return super.init(
{
comment: {
type: Sequelize.STRING(100),
allowNull: false,
},
created_at: {
type: Sequelize.DATE,
allowNull: true,
defaultValue: Sequelize.NOW,
},
},
{
sequelize,
timestamps: false,
modelName: "Comment",
tableName: "comments",
paranoid: false,
charset: "utf8mb4",
collate: "utf8mb4_general_ci",
}
);
}
static associate(db) {}
};
const Sequelize = require("sequelize");
const User = require("./user");
const Comment = require("./comment");
const env = process.env.NODE_ENV || "development";
const config = require("../config/config")[env];
const db = {};
const sequelize = new Sequelize(
config.database,
config.username,
config.password,
config
);
db.sequelize = sequelize;
db.User = User;
db.Comment = Comment;
User.init(sequelize);
Comment.init(sequelize);
User.associate(db);
Comment.associate(db);
module.exports = db;
(3) 관계 정의하기
시퀄라이즈에 테이블 간 관계를 알려주어서 JOIN 기능으로 여러 테이블 간의 관계를 파악하게 함
1. 1:N
예시
사용자 한 명은 댓글을 여러 개 작성할 수 있으나, 댓글 하나에 사용자(작성자)가 여러 명일 수는 없음.
이때, 사용자가 1이고, 댓글이 N
(in 시퀄라이즈 모델 각각의 static associate 메서드)
=> hasMany 메서드로 표현 : users 테이블의 로우 하나를 불러올 때 연결된 comments 테이블의 로우들 불러옴
=> belongsTo 메서드 : comments 테이블의 로우를 불러올 때 연결된 users 테이블의 로우를 가져옴 (다른 모델의 정보가 들어가는 테이블에 사용)
// models/user.js
static associate(db) {
db.User.hasMany(db.Comment, { foreignKey: "commenter", sourceKey: "id" });
}
// models/comment.js
static associate(db) {
db.Comment.belongsTo(db.User, { foreignKey: "commenter", targetKey: "id" });
}
2. 1:1
예시
사용자 한 명은 자신의 정보를 담고 있는 테이블과만 관계가 있고, 정보 테이블도 한 사람만을 가리킴.
(in 시퀄라이즈 모델 각각의 static associate 메서드)
=> hasOne 메서드를 사용
=> belongsTo 메서드 : 다른 모델의 정보가 들어가는 테이블에 사용
db.User.hasOne(db.Info, { foreignKey: 'UserId', sourceKey: 'id' });
db.Info.belongsTo(db.User, { foreignKey: 'UserId', targetKey: 'id' });
3. N:M
예시
한 게시글에는 해시태그가 여러 개 달릴 수 있고, 한 해시태그도 여러 게시글에 달릴 수 있음.
(in 시퀄라이즈 모델 각각의 static associate 메서드)
=> belongsToMany 메서드 사용 : 양쪽 모델에 모두 사용
- through 속성 : 생성되는 새로운 모델의 이름
db.Post.belongsToMany(db.Hashtag, { through: 'PostHashtag' });
db.Hashtag.belongsToMany(db.Post, { through: 'PostHashtag' });
db.sequelize.models.PostHashtag
(4) 쿼리 알아보기
// 시퀄라이즈 쿼리
const { User } = require('../models');
User.create({
name: 'zero',
age: 24,
married: false,
comment: '자기소개1',
});
// 시퀄라이즈 쿼리
User.findAll({});
// 시퀄라이즈 쿼리
User.findOne({});
// 시퀄라이즈 쿼리
User.findAll({
attributes: ['name', 'married'],
});
// 시퀄라이즈 쿼리
const { Op } = require('sequelize');
const { User } = require('../models');
User.findAll({
attributes: ['name', 'age'],
where: {
married: 1,
age: { [Op.gt]: 30 },
},
});
시퀄라이즈 연산자 종류 - Op 객체를 불러와 사용
1) Op.gt : 초과
2) Op.gte : 이상
3) Op.lt : 미만
4) Op.lte : 이하
5) Op.ne : 같지 않음
6) Op.or : 또는
7) Op.in : 배열 요소 중 하나
8) Op.notIn : 배열 요소와 모두 다름
// 시퀄라이즈 쿼리
User.findAll({
attributes: ['id', 'name'],
order: [['age', 'DESC']],
});
// 시퀄라이즈 조회
User.findAll({
attributes: ['id', 'name'],
order: [['age', 'DESC']],
limit: 1,
});
// 시퀄라이즈 쿼리
User.findAll({
attributes: ['id', 'name'],
order: ['age', 'DESC'],
limit: 1,
offset: 1,
});
// 시퀄라이즈 쿼리
User.update({
comment: '바꿀 내용',
}, {
where: { id: 2 },
});
// 시퀄라이즈 쿼리
User.destory({
where: { id: 2 },
});
1. 관계 쿼리
const user = await User.findOne({
include: [{
model: Comment,
}]
});
console.log(user.Comments);
// where나 attribute 옵션을 사용한 include
const user = await User.findOne({
include: [{
model: Comment,
where: {
id: 1,
},
attributes: ['id'],
}]
});
[관계 설정한 뒤에 사용 가능한 관계 쿼리 메서드]
const comments = await user.getComments();
console.log(comments);
// where나 attributes 같은 옵션을 사용한 관계 쿼리 메서드
const comments = await user.getComments({
where: {
id: 1,
},
attributes: ['id'],
});
const user = await User.findOne({});
const comment = await Comment.create();
await user.addComment(comment);
// 또는
await user.addComment(comment.id);
2. SQL 쿼리하기
const [result, metadata] = await sequelize.query('SELECT * from comments');
console.log(result);
(5) 쿼리 수행하기
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>시퀄라이즈 서버</title>
<style>
table { border: 1px solid black; border-collapse: collapse; }
table th, table td { border: 1px solid black; }
</style>
</head>
<body>
<div>
<form id="user-form">
<fieldset>
<legend>사용자 등록</legend>
<div><input id="username" type="text" placeholder="이름"></div>
<div><input id="age" type="number" placeholder="나이"></div>
<div><input id="married" type="checkbox"><label for="married">결혼 여부</label></div>
<button type="submit">등록</button>
</fieldset>
</form>
</div>
<br>
<table id="user-list">
<thead>
<tr>
<th>아이디</th>
<th>이름</th>
<th>나이</th>
<th>결혼여부</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.age}}</td>
<td>{{ '기혼' if user.married else '미혼'}}</td>
</tr>
{% endfor %}
</tbody>
</table>
<br>
<div>
<form id="comment-form">
<fieldset>
<legend>댓글 등록</legend>
<div><input id="userid" type="text" placeholder="사용자 아이디"></div>
<div><input id="comment" type="text" placeholder="댓글"></div>
<button type="submit">등록</button>
</fieldset>
</form>
</div>
<br>
<table id="comment-list">
<thead>
<tr>
<th>아이디</th>
<th>작성자</th>
<th>댓글</th>
<th>수정</th>
<th>삭제</th>
</tr>
</thead>
<tbody></tbody>
</table>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="/sequelize.js"></script>
</body>
</html>
<h1>{{message}}</h1>
<h2>{{error.status}}</h2>
<pre>{{error.stack}}</pre>
// 사용자 이름 눌렀을 때 댓글 로딩
document.querySelectorAll('#user-list tr').forEach((el) => {
el.addEventListener('click', function () {
const id = el.querySelector('td').textContent;
getComment(id);
});
});
// 사용자 로딩
async function getUser() {
try {
const res = await axios.get('/users');
const users = res.data;
console.log(users);
const tbody = document.querySelector('#user-list tbody');
tbody.innerHTML = '';
users.map(function (user) {
const row = document.createElement('tr');
row.addEventListener('click', () => {
getComment(user.id);
});
// 로우 셀 추가
let td = document.createElement('td');
td.textContent = user.id;
row.appendChild(td);
td = document.createElement('td');
td.textContent = user.name;
row.appendChild(td);
td = document.createElement('td');
td.textContent = user.age;
row.appendChild(td);
td = document.createElement('td');
td.textContent = user.married ? '기혼' : '미혼';
row.appendChild(td);
tbody.appendChild(row);
});
} catch (err) {
console.error(err);
}
}
// 댓글 로딩
async function getComment(id) {
try {
const res = await axios.get(`/users/${id}/comments`);
const comments = res.data;
const tbody = document.querySelector('#comment-list tbody');
tbody.innerHTML = '';
comments.map(function (comment) {
// 로우 셀 추가
const row = document.createElement('tr');
let td = document.createElement('td');
td.textContent = comment.id;
row.appendChild(td);
td = document.createElement('td');
td.textContent = comment.User.name;
row.appendChild(td);
td = document.createElement('td');
td.textContent = comment.comment;
row.appendChild(td);
const edit = document.createElement('button');
edit.textContent = '수정';
edit.addEventListener('click', async () => { // 수정 클릭 시
const newComment = prompt('바꿀 내용을 입력하세요');
if (!newComment) {
return alert('내용을 반드시 입력하셔야 합니다');
}
try {
await axios.patch(`/comments/${comment.id}`, { comment: newComment });
getComment(id);
} catch (err) {
console.error(err);
}
});
const remove = document.createElement('button');
remove.textContent = '삭제';
remove.addEventListener('click', async () => { // 삭제 클릭 시
try {
await axios.delete(`/comments/${comment.id}`);
getComment(id);
} catch (err) {
console.error(err);
}
});
// 버튼 추가
td = document.createElement('td');
td.appendChild(edit);
row.appendChild(td);
td = document.createElement('td');
td.appendChild(remove);
row.appendChild(td);
tbody.appendChild(row);
});
} catch (err) {
console.error(err);
}
}
// 사용자 등록 시
document.getElementById('user-form').addEventListener('submit', async (e) => {
e.preventDefault();
const name = e.target.username.value;
const age = e.target.age.value;
const married = e.target.married.checked;
if (!name) {
return alert('이름을 입력하세요');
}
if (!age) {
return alert('나이를 입력하세요');
}
try {
await axios.post('/users', { name, age, married });
getUser();
} catch (err) {
console.error(err);
}
e.target.username.value = '';
e.target.age.value = '';
e.target.married.checked = false;
});
// 댓글 등록 시
document.getElementById('comment-form').addEventListener('submit', async (e) => {
e.preventDefault();
const id = e.target.userid.value;
const comment = e.target.comment.value;
if (!id) {
return alert('아이디를 입력하세요');
}
if (!comment) {
return alert('댓글을 입력하세요');
}
try {
await axios.post('/comments', { id, comment });
getComment(id);
} catch (err) {
console.error(err);
}
e.target.userid.value = '';
e.target.comment.value = '';
});
const express = require("express");
const path = require("path");
const morgan = require("morgan");
const nunjucks = require("nunjucks");
const { sequelize } = require("./models");
const indexRouter = require("./routes");
const usersRouter = require("./routes/users");
const commentsRouter = require("./routes/comments");
const app = express();
app.set("port", process.env.PORT || 3001);
app.set("view engine", "html");
nunjucks.configure("views", {
express: app,
watch: true,
});
sequelize
.sync({ force: false })
.then(() => {
console.log("데이터베이스 연결 성공");
})
.catch((err) => {
console.error(err);
});
app.use(morgan("dev"));
app.use(express.static(path.join(__dirname, "public")));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use("/", indexRouter);
app.use("/users", usersRouter);
app.use("/comments", commentsRouter);
app.use((req, res, next) => {
const error = new Error(`${req.method} ${req.url} 라우터가 없습니다.`);
error.status = 404;
next(error);
});
app.use((err, req, res, next) => {
res.locals.message = err.message;
res.locals.error = process.env.NODE_ENV !== "production" ? err : {};
res.status(err.status || 500);
res.render("error");
});
app.listen(app.get("port"), () => {
console.log(app.get("port"), "번 포트에서 대기 중");
});
const express = require('express');
const User = require('../models/user');
const router = express.Router();
router.get('/', async (req, res, next) => {
try {
const users = await User.findAll();
res.render('sequelize', { users });
} catch (err) {
console.error(err);
next(err);
}
});
module.exports = router;
const express = require('express');
const User = require('../models/user');
const Comment = require('../models/comment');
const router = express.Router();
router.route('/')
.get(async (req, res, next) => {
try {
const users = await User.findAll();
res.json(users);
} catch (err) {
console.error(err);
next(err);
}
})
.post(async (req, res, next) => {
try {
const user = await User.create({
name: req.body.name,
age: req.body.age,
married: req.body.married,
});
console.log(user);
res.status(201).json(user);
} catch (err) {
console.error(err);
next(err);
}
});
router.get('/:id/comments', async (req, res, next) => {
try {
const comments = await Comment.findAll({
include: {
model: User,
where: { id: req.params.id },
},
});
console.log(comments);
res.json(comments);
} catch (err) {
console.error(err);
next(err);
}
});
module.exports = router;
const express = require('express');
const { Comment } = require('../models');
const router = express.Router();
router.post('/', async (req, res, next) => {
try {
const comment = await Comment.create({
commenter: req.body.id,
comment: req.body.comment,
});
console.log(comment);
res.status(201).json(comment);
} catch (err) {
console.error(err);
next(err);
}
});
router.route('/:id')
.patch(async (req, res, next) => {
try {
const result = await Comment.update({
comment: req.body.comment,
}, {
where: { id: req.params.id },
});
res.json(result);
} catch (err) {
console.error(err);
next(err);
}
})
.delete(async (req, res, next) => {
try {
const result = await Comment.destroy({ where: { id: req.params.id } });
res.json(result);
} catch (err) {
console.error(err);
next(err);
}
});
module.exports = router;
1. 노드와 MySQL을 연동해주는 라이브러리는?
2. 시퀄라이즈 모델의 메서드 중 다른 모델과의 관계를 기재하는 메서드는?
3. 시퀄라이즈 모델의 메서드 중 테이블에 대한 설정을 하는 메서드는?
1. 시퀄라이즈
2. static associate
3. static init
[Node.js] 9장 익스프레스로 SNS 서비스 만들기 (0) | 2021.12.27 |
---|---|
[Node.js] 8장 몽고디비 (0) | 2021.12.01 |
[Node.js] 6장 익스프레스 웹 서버 만들기 (0) | 2021.11.15 |
[Node.js] 5장 패키지 매니저 (0) | 2021.11.08 |
[Node.js] 4장 http 모듈로 서버 만들기 (0) | 2021.11.08 |