Sequelize 세팅
0 . npm init 명령 first
1. npm install express nunjucks sequelize sequelize-cli mysql2 설치하기
책에는 install morgan / npm i -D nodemon 도 적혀있다.
npm install nodemon -> 은 나중에! server 켰다 껐다 연습해야해서
-nunjucks : html render를 위한 패키지
-Sequelize-cli : sequelize 명령어를 실행하기 위한 패키지
-mysql2 : MySQL과 Sequelize를 이어주는 드라이버 역할 (DB프로그램x)
2. npx sequelize init
npm - 우리가 다운받지 않은 상태에서 폴더 다운 받는 개념 (기본적인 틀 제공)
npx - 다운받은 폴더를 실행시켜서 세팅해주기
* 전역없이 명령어로 사용하려면 앞에 npx 붙이기
* config.json 분석
config, migrations, models, node_modules, seeders, package-lock.json 폴더가 생겼다.
config폴더 안 config.json 에는
"development" - 실제 서버 연결시
"test" - 테스트용
"production" - 상품 정보 담는 3가지 객체가 생성되어 있다.
config - 접속 정보를 저장해주는 객체
* models- index.js 분석
'use strict'; //없어도 상관 없다.
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize'); //Sequelize
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development'; //test할 때 development를 test로 바꿔
const config = require(__dirname + '/../config/config.json')[env];
// env 위에 정의되어 있음. 우리는env 설정안했음. 지금 env = development 값
// config는 요걸 가져옴
// config = config파일 안 development 의 객체 값이 된다.
const db = {}; //빈 객체로 선언
let sequelize; //sequelize
if (config.use_env_variable) { // config에 use_env_variable이라는 정보가 있으면 ~
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else { //요게 우리가 실행될 것
sequelize = new Sequelize(config.database, config.username, config.password, config);
} // new = 함수가 객체로 변한다 / 결과적으로 요 값이 객체로 변하겠구나~ 알 수 있음.
//config 어디서 가져왓냐면 위에 8번줄
// development 객체 안의 내용을 내 db 내용과 같도록 정보 바꾸기
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize; //sequelize, Sequelize 두가지 속성 값을 db에 넣었다.
db.Sequelize = Sequelize;
module.exports = db; // db라는 변수를 결과적으로 넘기는구나
//db라는 파일을 불러왔을 때 객체로 받는구나 알 수 있음.
//팁 : 얘는 결국 무엇을 넘기나 아랫줄에 module을 쳌! 그거에 대한 결과값이 무엇인가
//무언가를 담아서 보냈는가 를 쳌
models - index.js에서 실질적으로 쓸 부분
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
3. config.json 파일 안 development 내용을 나의 컴퓨터 mysql 정보로 바꾸기
{
"development": {
"username": "root",
"password": "d", //비밀번호 변경
"database": "joinn", //table을 생성할 database명 입력 (새거or 기존 상관없이 새로운table을 만듬)
"host": "127.0.0.1",
"dialect": "mysql"
},
4. Sequelize를 통해 express app과 mySQL 연결하기
app.js 파일 만들고 코드 작성 (서버 실행할 때 쓸 server JS)
const express=require('express');
const app = express();
const {sequelize}=require('./models'); // 이 부분 추가
app.get('/', (req,res)=>{
res.send('hello');
})
app.listen(3000,()=>{
console.log('server start : 3000')
})
기본 express 서버 구조에
const sequelize = require('./models') 요 부분 추가 -> models 파일 안 index를 가져와서 sequelize 변수에 넣었다.
* 변수 명이 sequelize가 아닌 {sequelize}인 이유
models - index.js 파일을 가져오면 db를 가져오는데 그 결과값을 선택해서 가져오겠다.
질문: {sequelize} 하면 sequelize가 아닌 Sequelize객체를 가져옴
sequelize 만 쓰고 console.log를 찍으면 Sequelize, sequelize 부분ㅇ ㅣ 쭉 - 나옴
5. Sequelize db접속 하기 / DB접속 server test code 작성
작성 후, 터미널에 node app.js 입력 -> db 성공 / 실패 check
const express=require('express');
const app = express();
const {sequelize}=require('./models'); // models - index.js 가져온다.
sequelize.sync({force:false}) // 추가
.then(()=>{
console.log('db접속 성공')
})
.catch(()=>{
console.log('db접속 실패')
})
app.get('/', (req,res)=>{
res.send('hello');
})
app.listen(3000,()=>{
console.log('server start : 3000')
})
code 분석
sequelize.sync({force:false})
sequelize = 객체 , .sync ( ) method를 사용함 .sync( )의 결과값은 new Promise 객체 -> .then, .catch 사용 가능
force: false : 접속했을 때 table이 존재하는가 안하는가에 따라 table을 새로 만들지를 세팅해주는 부분
force: true = > 생성하지않음 / force:true => 생성함
5. User model 정의하기 (models 폴더 -> user.js 파일 생성 및 코드 작성 )
node.js 교과서 개정2판 320p 내용 작성
sequelize는 보통 table명은 복수형, model 이름은 단수형으로 쓴다.
sequelize는 model과 mySQL의 table을 연결해 주는 역할
user.js 파일 작성
const Sequelize=require('sequelize'); //sequelize가져오기
module.exports=class User extends Sequelize.Model{ //class 던져주기
static init(sequelize){
//User라는 class에서 정적으로 사용하는 , 쉽게 말하면constructor
//처음 생성할 때 요기가 실행된다~
//User라는class가 객체 생성없이 바로 사용 가능하다~ 라는 뜻
return super.init({ // super : 부모에 있는 method 가져옴 / 부모의 init이라는 method가져옴
name:{ //name varchar(20) NOT NULL UNIQUE
type:Sequelize.STRING(20), //부모로부터 받아 Sequelize.STRING 이라고 적기
//== varchar(20)
allowNull:false, // == not null 무적권 이름은 null값이 있으면 안된다.
unique:true, // unique 사용하겠다 ~
},
age:{ // age라는 field를 만들거고 sql 구문 = age INT UNSIGNED NOT NULL
type:Sequelize.INTEGER.UNSIGNED, // 숫자만 사용할건데 양수만 사용할거야 + 값만
allowNull:false, // NOT NULL
},
married:{ // married TINYINT(1) NOT NULL
type:Sequelize.BOOLEAN, // tinyint 한자리수 정수 숫자 받는 뜻
allowNull:false, //not null
},
comment:{ /// comment TEXT NOT NULL
type:Sequelize.TEXT,
allowNull:true,
},
created_at:{ // created_at DATETIME NOT NULL default NOW()
type:Sequelize.DATE,
allowNull:false,
defaultValue:Sequelize.NOW,
},
},{
sequelize,// 사용할 때 인자값 내용 넣는거
timestamps:false, // true 하게 되면 createdAt과 updatedAt columns 자동 추가함
underscored:false, // true하면 camel case -> snake case 로 전환하게됨(영문대소문자)
modelName:'User', // express에서 JS 사용하기위한 이름 설정
tableName:'users', // 실제 table 이름 요걸로 사용하겠다.
paranoid:false, // true 하면 deletedAt column생김 row 삭제할 때 완전히 지워지지않고
//지워진 시각 기록 -> row 조회 명령 시 deletedAt column value = Null값만 불러와짐
// 삭제한 row 복원하고 싶다면 true!
charset:'utf8', //한글 입력 가능하게 utf8mb4 쓰면 이모티콘도 가능
collate:'utf8_general_ci', //or utf8mb4쓰기
});
}
static associate(db){} // 아직은 사용안함
};
index.js 수정
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const User = require('./user'); //result = class / user.js 가져옴
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
db.User=User;//app.js에서 User라는 class 가져올 수 있도록 db객체에 User property넣음
User.init(sequelize);
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
app.js force:true로 변경
const express=require('express');
const app=express();
const {sequelize} = require('./models')
sequelize.sync({force:true});
app.get('/',(req,res)=>{
res.send('hello');
})
app.listen(3000,()=>{
console.log('server start : 3000')
})
-> node app.js 실행 하고 아래 읽어보기
mySQL prompt 창에 가서 show tables 해보면
요렇게 jonn이라는 기존에 있었던 database에 2번째 새로운 table 'users'를 만들었다.
그리고 fields도 만들어졌다.
---> table 만들었으니 app.js 의 force:false로 다시 변경하기
sequelize.sync({force:false});
6. 생성한 table안에 DB 추가 = SQL명령 insert 해보기
app.js 에 User.create문구 (SQL insert into구문 넣기)
const express=require('express');
const app=express();
const {sequelize, User} = require('./models')
sequelize.sync({force:false});
app.get('/',(req,res)=>{
User.create({
name:'zero',
age:'24',
married:false,
comment:'자기소개1',
})
res.send('hello');
})
app.listen(3000,()=>{
console.log('server start : 3000')
})
-> 터미널에 app.js 키고 -> localhost:3000 브라우저에 새로고침하고 -> 다시 mysql 보면
내용이 잘 들어갔다.
* 이 부분도 삭제 가능
sequelize.sync({force:false});
7. 생성한 table 안에 Select문 해보기
먼저 console.log로 User.findAll({}) 결과값 확인 해보기
const express=require('express');
const app=express();
const {sequelize} = require('./models')
const {User} = require('./models');
app.get('/',(req,res)=>{
/*User.create({
name:'zero',
age:'24',
married:false,
comment:'자기소개1',
})*/
console.log(User.findAll({}));
res.send('hello');
})
app.listen(3000,()=>{
console.log('server start : 3000')
})
결과가 Promise 객체로 떨어짐을 알 수 있다.
async & await 넣어서 console.log 찍어보기
const express=require('express');
const app=express();
const {sequelize} = require('./models')
const {User} = require('./models');
app.get('/', async (req,res)=>{
/*User.create({
name:'zero',
age:'24',
married:false,
comment:'자기소개1',
})*/
console.log(await User.findAll({}));
res.send('hello');
})
app.listen(3000,()=>{
console.log('server start : 3000')
})
배열, 객체로 담아서 나온다. => User.findAll({}) -> 비동기임을 알 수 있음-결과가 Promise 객체 값이므로
변수에 담아서 특정 값 가져와보기
const express=require('express');
const app=express();
const {sequelize} = require('./models')
const {User} = require('./models');
app.get('/', async (req,res)=>{
/*User.create({
name:'zero',
age:'24',
married:false,
comment:'자기소개1',
})*/
const userList = await User.findAll({})
console.log(userList[0].name);
res.send('hello');
})
app.listen(3000,()=>{
console.log('server start : 3000')
})
name, married만 뽑아오기
const express=require('express');
const app=express();
const {sequelize} = require('./models')
const {User} = require('./models'); //질문 -> 요기 파일은 index? of user?
app.get('/', async (req,res)=>{
/*User.create({
name:'zero',
age:'24',
married:false,
comment:'자기소개1',
})*/
const userList = await User.findAll({
attributes:['name','married']
})
res.send('hello');
})
app.listen(3000,()=>{
console.log('server start : 3000')
})
이 외의 구문 skill은 node.js 교과서 개정2판 230-231p 참고
-------------------------------------------------------여기까지가 Models 부분 ------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------
MVC
Model
- Data를 받고 저장, DB에 있던 내용, 내가 사용할 DB를 객체로 저장하는 곳
- 데이터를 저장한 객체 - > 요 Data 가지고 모든걸 표현할 수 없다. ex) 게시판의 paging etc. => 이 때 controller가 필요한 logic을 추가해서 view로 보낸다.
-> Data가 뭔가 잘못된거 같다싶으면 model 쪽 체크
View
- 화면에 뿌려주는 , 실질적으로 Client가 보는 부분
- nunjucks의 활용, nunjucks를 쓰면 MVC 패턴 중 view부분
-> 뭔가 화면이 이상하면 view 쪽 체크
Controllers
- model에서 받은 걸 조작해서 view로 보냄 (model & view를 연결하는 곳)
- 최소한의 코드들만 따로 뽑아서 business logic 만 처리할 수 있게 만든게 controllers
-> paging이 이상하면 controllers 쪽 체크
-----------------------------------------------------------------------------------------------------------------------------------
8. ROUTER + nunjucks 추가, views 폴더 - index.html 등 폴더& 파일들 추가 작업
app.js 에 nunjucks 추가
const nunjucks = require('nunjucks');
nunjucks.configure('views',{
express:app,
})
app.set('view engine','html');
nunjucks에서 views 폴더에 있는걸 사용하겠다고 했으니 views 폴더 + index.html 추가
router 폴더 만들기
router 폴더 안 index.js 파일 만들기
router 폴더 안 main 폴더 만들기 - 그 안에 index.js 파일 만들기
app.js
const express=require('express');
const app=express();
const {sequelize} = require('./models')
const {User} = require('./models');
const nunjucks = require('nunjucks');
const indexRouter=require('./router'); //indexRouter는 router - index.js이다.
nunjucks.configure('views',{
express:app,
})
app.set('view engine','html');
app.use('/', indexRouter); // '/'를 받으면 indexRouter 로 가라
app.listen(3000,()=>{
console.log('server start : 3000')
})
router-index.js
const express = require('express');
const router=express.Router();
const mainRouter=require('./main/index.js'); // mainRouter는 main - index.js 이다.
router.use('/',mainRouter); // '/'를 받으면 mainRouter 로 가라
module.exports = router;
router-main-index.js
const express = require('express');
const router = express.Router();
router.get('/',(req,res)=>{
res.render('index.html'); // index.html (views폴더 안) 을 render해라
})
module.exports=router;
app.js 에서 '/'을 받으면 indexRouter (router-index.js) -> router-index.js에서 '/'을 받으면 mainRouter (router-main-index.js) -> router-main-index.js에서 '/' 을 받으면 res.render('index.html') -> views - index.html 열림
9. business logic Controllers 부분 나누기
router-main - index.js (index.html render해주는 마지막 js 파일 )
const express = require('express');
const router = express.Router();
const controller = require('./main.controller');
router.get('/',controller.main)
module.exports=router;
main폴더에 main.controller.js 파일 만들기
main.controller.js
const {User} = require('../../models')
let main = async (req,res) =>{
let user = await User.findAll({}) // 요 줄의 의미? 질문
res.render('index.html')
}
exports.main=main;
// 보낼 명 // 보낼 함수
router - index.js /board 내용 추가
const express = require('express');
const router=express.Router();
const mainRouter=require('./main/index.js');
const boardRouter=require('./board/index'); //이 부분 만들기
router.use('/',mainRouter);
router.use('/board',boardRouter);
module.exports = router;
router - board 폴더 생성 - index.js 파일 만들기
router-board-index.js
const express = require('express');
const router=express.Router();
const controller = require('./board.controller'); //이 파일 만들기
router.get('/list', controller.list);
router.get('/view', controller.view);
router.get('/write', controller.write);
router.get('/modify', controller.modify);
module.exports=router;
router - board - board.controller.js 파일 만들기
let list = (req,res)=>{
res.render('list.html');
}
let view = (req,res)=>{
res.render('view.html');
}
let write = (req,res)=>{
res.render('write.html');
}
let modify = (req,res)=>{
res.render('modify.html');
}
module.exports={
list:list,
view:view,
write:write,
modify:modify
}
이제 views 폴더 안에 list, view, write, modify 파일 만들기
modify.html입니다.
->node app.js 실행 -> localhost:3000 & 3000/board/list, write, view, modify 확인
routers- board - board.controller.js 에 async , await 적용
const {User} = require('../../models')
//요걸 가져오면
let list = async (req,res)=>{
//select
let UserList = await User.findAll({})
res.render('list.html')
}
let view = (req,res)=>{
//select
let UserList = await User.findAll({})
res.render('view.html')
}
//board/write POST
let write = (req,res)=>{
//insert
let rst = await User.create({
//....req 요청값에 나왔던 부분을 넣어주면 됨
})
res.render('write.html')
}
let modify = (req,res)=>{
//update
let rst = await User.update({
//필드 : '바뀔내용'..
},{
where: { //필드:값} 이런 nunjucks의 결과를 떤져주면됨
})
res.render('modify.html')
}
module.exports={
list:list,
view:view,
modify:modify, //modify 라는 속성값을 modify 라는 method로
write:write
}
----------------------------------------------------------------------------------------------------------------------------------
질문 이부분이 잘 이해가 안감
class test{
constructor(){
this.name="a"
}
init(){
console.log('29');
}
static init(){
this.age="20"
console.log('50');
}
}
console.log(test);
console.log(new test);
test.init();
let a = new test();
a.init();