// 시퀄라이즈 orm(객체 관계 매핑)
// 겍체와 데이터 베이스를 orm 라이브러리가 매핑을 시켜주어서 자바스크립트 구문으로 sql을 제어할수 있다.
// 자바스크립트로만 sql작업을 할수있도록 도와주는 라이브러리.
// 프로젝트 시작 package.json
// 설치할 모듈은 express ejs sequelize mysql2
// 서버 객체 만들고
// 서버 대기상태
// view 엔진 경로 설정
// view엔진 ejs 사용
// body 객체 사용
const express = require("express");
const app = express();
const path = require("path");
const dot = require("dotenv").config();
const {sequelize,User,Post} = require('./models');
app.set("views",path.join(__dirname,"page"));
app.set("view engine","ejs");
app.use(express.urlencoded({extended:false}));
// 시퀄라이즈 구성 연결 매핑
// sync 함수는 데이터 베이스를 동기화 시켜주는 메서드
// true 값일때 초기화
// false 값일때 초기화 안됨
sequelize.sync({focus : false}).then(()=>[
// 연결 성공
console.log("연결 성공")
]).catch((err)=>{
// 연결 실패
console.log(err);
})
app.get('/',(req,res)=>{
res.render("create");
})
app.post('/create',(req,res)=>{
const {name,age,msg} = req.body;
// create insert 문을 실행 시켜주는 메서드
// 매개변수로 컬럼의 내용을 객체로 만들어서 전달
User.create({
// name 컬럼의 값
name : name,
// age 컬럼의 값
age : age,
// msg 컬럼의 값
msg : msg
})
res.send("값 추가 되었음");
})
app.get('/main',(req,res)=>{
// 유저 전체 조회
// findall 메서드 매개변수로 검색 조건을 객체로 추가할수있다.
// select * from User 한거랑 같구나.
User.findAll({})
.then((e)=>{
// 성공시
res.render("main",{ data : e });
}).catch((e)=>{
// 실패시
res.send("유저 조회 실패")
})
})
app.post('/create_post',(req,res)=>{
const {name, value} = req.body;
console.log(name, value);
// findOne 한개의 값을 조회 메서드
User.findOne({
// 검색 조건 추가
where : {name : name}
}).then((e)=>{
Post.create({
msg : value,
user_id : e.id
})
}).catch((err)=>{
console.log(err)
})
res.send();
})
app.get('/view/:name', (req,res)=>{
// 유저를 조회하고 가지고 있는 글을 볼거임
User.findOne({
where : {
// 해당 이름의 유저를 조회하면서
name : req.params.name
},
// raw 속성을 주면 관계형으로 불러온 값을 다 풀어서 볼수가 있는데
// raw : true,
// 해당 유저의 id로 참조된 user_id가 있는 post 테이블의 값을 같이 조회한다.
include : [
// 조회 할 모듈 post 모델
{ model : Post }
]
}).then((e)=>{
console.log(e);
e.dataValues.Posts = e.dataValues.Posts.map((i) => i.dataValues);
const Posts = e.dataValues;
console.log(Posts)
res.render("view", {data : Posts});
})
})
app.listen(8000,()=>{
console.log("서버 잘 열림");
})
express.js를 사용하여 서버를 생성하고 설정
sequelize.sync() 메서드를 사용하여 Sequelize ORM과 데이터베이스를 동기화한다.
라우트를 정의하고 http 요청에 따른 처리를 수행한다.
라우트 경로를 설정하고, 해당 경로로 요청이 들어올 때 실행할 함수를 정의합니다. '/' 경로로 GET 요청이 들어오면 'create' 뷰를 렌더링합니다. '/create' 경로로 POST 요청이 들어오면 사용자 정보를 데이터베이스에 추가합니다. '/main' 경로로 GET 요청이 들어오면 사용자 목록을 조회하여 'main' 뷰에 데이터를 전달합니다. '/create_post' 경로로 POST 요청이 들어오면 사용자와 연결된 글을 생성합니다. '/view/:name' 경로로 GET 요청이 들어오면 해당 사용자의 정보와 글을 조회하여 'view' 뷰에 데이터를 전달합니다.-app.js
위의 코드에서 then() 메서드를 사용하여 User.findOne() 메서드의 작업이 완료되면 결과를 처리하고 있다.
then() 메서드의 콜백 함수는 e라는 파라미터를 받아와서 결과를 처리하고 있다.
이 콜백함수는 User.findOne() 작업이 완료된 후에 실행되므로 해당 유저의 데이터를 가공하고 렌더링하는 등의
작업을 수행할 수 있다.
비동기 함수를 사용하여 데이터베이스 조화와 같은 오래 걸리는 작업을 비차단적으로 처리할 수 있으며
작업이 완료된 후에 결과를 적절하게 처리할수 있다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="/create" method="post">
<label for="">이름</label>
<input type="text" name="name"/>
<label for="">나이</label>
<input type="text" name="age">
<label for="">문자</label>
<input type="text" name="msg">
<button>유저 등록</button>
</form>
</body>
</html>
사용자 등록을 위한 html 템플릿 파일 이름,나이,문자를 입력받을수 있는 폼이 있다.-create.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
</head>
<body>
<h1>유저 페이지</h1>
<% data.forEach((el)=>{ %>
<li>
<span class="name"><%= el.name %></span>님 <%= el.age %>살 코멘트 <%= el.msg %>
<input type="text" class="item-input"><button class="item-btn"> 글 등록</button>
</li>
<% }); %>
</body>
<script>
// ajax : 요청과 응답에 대한 처리를 할수 있게 도와주는 메서드
window.onload= function(){
let btns = document.querySelectorAll('.item-btn');
btns.forEach((el,index)=>{
el.onclick = ()=>{
let value = document.querySelectorAll('.item-input')[index].value;
let name = document.querySelectorAll(".name")[index].innerText;
console.log("value",value);
console.log("names",name);
// 요청해서 값을 넣자 from tag 사용 x
// ajax 메서드 사용
$.ajax({
// 요청할 url
url : "/create_post",
// 요청 방식
type : "post",
// 전달할 데이터
data : {name,value}
})
}
})
}
</script>
</html>
사용자 목록을 보여주는 html 템플릿 파일
서버에서 조회한 데이터를 동적으로 출력한다.-main.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
작성자 : <%= data.name %>
<ul>
<% data.Posts.forEach((el)=>{ %>
<li>
<span><%= el.id %></span>
<span><%= el.msg %></span>
</li>
<% }); %>
</ul>
</body>
</html>
특정 사용자의 정보와 해당 사용자의 글 목록을 보여주는 html 템플릿 파일-view.ejs
const Sequelize = require("sequelize");
// user클래스에 시퀄리아즈 안의 Model클래스를 상속 시켜준다.
class User extends Sequelize.Model {
static init(sequelize){
// super 상속받은 부모의 함수를 실행 init 실행시켜서 반환
// init 메서드는 첫 번째 매개변수로 컬럼의 대한 설정 값이 들어가고
// 두 번째 매개변수로 테이블의 자체 설정 값이 들어간다.
return super.init({
// 컬럼의 대한 설정
// name 컬럼
// VARCHAR == STRING
// alloweNull : null을 허용할지
// unique : 고유키로 사용할 것인지 중복되지 않는 값.
name : {
type : Sequelize.STRING(20),
allowNull : false,
unique : true,
// primaryKey : true
// primaryKey : 고유키로 설정할 것인지 유무
},
// INT == INTEGER
age : {
type : Sequelize.INTEGER,
allowNull : false
},
// TEXT == TEXT
msg : {
type : Sequelize.TEXT
}
},{
// 테이블의 자체 설정
// 매개변수로 전달받은 _sequelize먼저 작성 해주고
sequelize,
// 테이블에 row 추가 했을때 생성시간과 업데이트 시간을 표기 해준다
// created_at과 updatad_at 이라는 컬럼이 자동으로 추가된다.
// 우리가 row추가했을때 시간을 기록해주고 수정했을때도 시간을 기록해준다.
timestamps : true,
// 표기법을 바꿔준다 기본적으로 스네이크 표기법으로 되어있는데 컬럼이
// 카멜 표기법으로 바꿔준다. created_at => createdAt
underscored : false,
modelName : "User", // 모듈의 이름을 설정 노드 프로젝트에서 사용
tableName : "users", // 복수형으로 설정해주자 왠만하면 추가될 테이블의 이름
paranoid : false, // paranoid true로 설정하면 deleted_at이라는 컬럼도 생성이 됩니다. 값이 남아있는데 삭제 시간이 표기 된다.
charset : "utf8", // 인코딩 방식 꼭 작성해줘야함
collate : "utf8_general_ci" // 인코딩 방식 꼭 작성해줘야함
});
}
static associate(db){
// 1 : N : 예) 하나의 유저가 여러개의 글을 만드는 경우
// 1 : N 관계
// 시퀄라이즈에서 1 : N 관계를 hasMany 메서드로 정의 한다
// hasMany 메서드는 테이블의 관계를 정의 해준다.
// sourceKey : user테이블 안에 어떤 키를 foreignKey와 연결 해줄지.
// hasMany 메서드의 첫번째 매개변수 넘긴 테이블이 foreignKey 연결이 되고 이름은 user_id다.
db.User.hasMany(db.Post, { foreignKey : "user_id" , sourceKey : "id"});
}
};
module.exports = User;
sequelize.model을 상속받아 init 메서드를 사용하여 컬럼의 설정과 테이블의 설정을 정의
User 모델과 Post 모델 간의 1:N 관계를 정의하고 있음 -users.js
const Sequelize = require("sequelize");
class Post extends Sequelize.Model {
static init(sequelize){
// 첫번째 매개변수 컬럼의 내용, 두번째 테이블의 내용
return super.init({
msg : {
type : Sequelize.STRING(100),
allowNull : false
}
},{
sequelize,
timestamps : true,
modelName: "Post",
tableName : "posts",
charset : "utf8",
collate : "utf8_general_ci"
});
}
static associate(db){
// 1 : N : 예) 하나의 유저가 여러개의 글을 만드는 경우
// 1 : N 관계
// 시퀄라이즈에서 1 : N 관계를 hasMany 메서드로 정의 한다
// hasMany 메서드는 테이블의 관계를 정의 해준다.
// sourceKey : user테이블 안에 어떤 키를 foreignKey와 연결 해줄지.
// hasMany 메서드의 첫번째 매개변수 넘긴 테이블이 foreignKey 연결이 되고 이름은 user_id다.
// belongsTo 메서드를 사용해서 user에 id를 forenignKey로 연결 한다.
// 유저의 id가 따라갈 키 참조키는 user_id
db.Post.belongsTo(db.User,{ foreignKey : "user_id", targetKey : "id"});
}
}
module.exports = Post;
post 모델을 정의한 파일 User 모델과의 1:N 관계를 정의하고 있다. - post.js
const Sequelize = require("sequelize");
const config = require("./config");
const User = require("./users");
const Post = require('./post')
console.log(config)
// 시퀄라이즈 객체 생성
const _sequelize = new Sequelize(
config.dev.database,
config.dev.username,
config.dev.password,
config.dev
)
// 내보내줄 빈 객체
const db = {};
db.sequelize = _sequelize;
db.User = User;
db.Post = Post;
User.init(_sequelize);
Post.init(_sequelize);
User.associate(db);
Post.associate(db);
// 테이블을 초기화 하는 부분
// User.init(_sequelize);
module.exports = db;
sequelize 객체를 생성하고 모델과 연결하는 파일 - index.js
const config = {
dev : {
username : "root",
password : "nonbanonfj",
database : "test",
host : "127.0.0.1",
// 사용하는 데이터 베이스
dialect : "mysql"
}
}
module.exports = config;
데이터베이스 연결 정보를 설정하는 파일
이 코드는 sequelize orm을 사용하여 mysql 데이터베이스와 연동하여
유저 정보와 글 정보를 저장하고 조회하는 기능을 구현한 예제
필요한 모듈들을 설치하고 설정을 적절히 변경한 뒤
실행해보면 동작 가능
처음 보는 내용
Sequelize ??
node.js 기반의 orm으로 javascript 객체와 데이터베이스 테이블 간의 매핑을 쉽게 처리할수 있도록 도와준다.
User.findOne()??
Sequelize ORM라이브러리에서 제공하는 메서드
User 모델에서 단일 레코드를 찾을때 사용되며, 인자로는 조회할 조건을 포함하는 객체를 전달한다.
위의 예시에서는 where 옵션을 사용하여 name이 요청된 이름과 일치하는 유저를 조회하고 있다.
이 메서드는 데이터베이스 조회가 비동기적으로 이루어지기 때문에 (일반적으로 오래걸려서) then()를 사용한다.
include ??
다른 모델과의 관계를 정의하고 해당 관계된 모델의 데이터를 함께 조회하도록 지정하는 역할을 한다.
여기서는 User 모델과 Post 모델이 관계를 가지고 있으며
User 모델을 조회할때 연결된 Post 모델의 데이터도 함께 조회하고 있다.
then() ??
javascript의 promise 객체에서 제공하는 메서드 중 하나이다.
promise는 비동기 작업의 결과를 나타내는 객체로 비동기 작업이 완료되었을 때 결과 값을 처리하거나 다음 작업을
수행할수 있도록 도와준다.
for each 함수에 대해서
var arr = [1, true, "JavaScript"]; function printArr(value, index, array) { document.write("arr[" + index + "] = " + value + "<br>"); //arr[0]=1; //arr[1] = true //arr[2] = javascript } arr.forEach(printArr); // 배열 arr의 각 요소마다 printArr() 함수가 호출됨. // arr.forEach() 메서드는 배열의 각 요소에 대해 주어진 함수를 순차적으로 실행하는 메서드 // printArr 함수는 document.write()를 사용하여 각 요소의 인덱스와 값을 출력한다. // arr.forEach(printArr)를 실행하면 forEach()메서드가 배열 arr의 첫 번째 요소부터 // 마지막 요소까지 반복하면서 printArr()함수가 호출된다. // //foreach 함수의 매개변수 1번째는 배열 요소의 value 2번째는 배열 요소의 index로 정해져있다. (바꿀수 없음)
arr.foreach(printArr) = function printArr(value, index, array){ ... ) 이다.
for each 메서드는 배열의 각 요소에 대해 주어진 함수를 순차적으로 실행하는 메서드
arr = [1,true,"javascript"] 이니까
arr.foreach(printArr)을 실행하면 document.write 에 index가 먼저오니 arr[0] 그다음 value은 값이니까 1 그래서 arr[0]=1
계속 실행해보면 arr[1] = true, arr[2] = "javascript" 이렇게 결과가 나온다.
'node.js' 카테고리의 다른 글
| node.js에 관한것 (1) | 2023.05.23 |
|---|---|
| 로그인 게시판 혼자 만들수있게 연습 (0) | 2023.05.23 |
| node.js 로그인 회원가입 까지 토큰 만료기간 설정 (0) | 2023.05.17 |
| node.js의 crypto 모듈(암호화) ,(해시,솔트) 등등 (0) | 2023.05.16 |
| node.js 접근 토큰과 갱신 토큰 발급 (0) | 2023.05.15 |