추석 동안 개인 프로젝트 과제를 주셨다. 리액트하다가 다시 express를 할려니까 기억이 잘 안난다. 그동안 했던거 찾아보면서 해야한다..ㅠㅠ 차근차근 하면서 복습하자
폴더를 새로 생성해주고 위의 폴더들을 만들어준다. 먼저 백엔드 작업을 해야하기에 server/ 폴더를 만든다.
만든 후에
npm init -y
express와 데이터베이스와 씨퀄라이즈를 사용할 것이기 때문에 함께 설치해준다.
npm i express mysql2 sequelize sequelize-cli
씨퀄라이즐를 사용하기 위해 아래 명령어도 작성해준다.
npx sequelize init
이를 설치하던 중에
npm ERR! code E404
npm ERR! 404 Not Found - GET https://registry.npmjs.org/seqeulize-cli - Not found
npm ERR! 404
npm ERR! 404 'seqeulize-cli@*' is not in this registry.
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.
npm ERR! A complete log of this run can be found in: C:\Users\82103\AppData\Local\npm-cache\_logs\2023-10-02T05_39_37_969Z-debug-0.log
위와 같은 에러가 발생해서 찾아봤는데 오픈소스 패키지를 npm 명령어로 설치하려 할 경우, 설정되어 있는 default registry에 패키지가 존재하지 않아 404 에러가 발생되는 것이었다. 이를 해결하기 위해선 npm install 시에 --registry 옵션을 넣어주면 다른 registry에서 패키지 다운로드가 가능하다. 일반적인 npm 패키지는 --registry https://registry.npmjs.org/ 를 넣어주면 된다.
npm install --save-dev (설치하고자하는 패키지 이름) --registry https://registry.npmjs.org/
완료 후 상태
빠르게 워크밴치로 만들었다.
이제 위의 api에 맞는 백엔드 기능들과 데이터베이스를 연결해보자
데이터 베이스 연결하기
1. config 파일 수정
먼저 씨퀄라이즈를 설치하면서 생기 config 파일에 들어가 설정한 유저 정보를 입력하여 나의 로컬에 있는 데이터배아스와 연결해준다.
# 사용자 등록
create user '유저이름'@'%' identified by '비밀번호';
grant all privileges on *.* to '유저이름'@'%' with grant option;
FLUSH privileges;
# 사용자 허가
select host, user, plugin, authentication_string from mysql.user;
alter user '유저이름'@'%' identified WITH mysql_native_password by '비밀번호';
데이터베이스를 가져오기 위한 유저를 등록하는 방법은 위와같다. 위를 통해 유저 등록을 한 뒤에 config에 사용할 데이터베이스와 유저이름 그리고 비밀 번호를 입력하면 원하는 데이터 베이스를 사용할 수 있다.
2. models파일의 index.js 수정
그리고 만들어진 models안의 index.js를 필요한 부분만 남긴다.
'use strict';
const Sequelize = require('sequelize');
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
3. mysql과 연결
models 파일에 연결할 데이터베이스의 테이블과 대응되는 모델을 정의해준다.
models 파일의 todolist.js
const { DataTypes } = require('sequelize');
const Model = (sequelize) => {
return sequelize.define(
'todo',
{
id : {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true,
},
title : {
type: DataTypes.STRING(100),
allowNull: false,
},
done : {
type: DataTypes.TINYINT(1),
allowNull: false,
},
},
//아무것도 정의해주지 않으면 시간도 같이 들어가기 때문에 아래의 코드를 작성해 없애줌
{
tablename: "todo",
timestamps: false,
}
);
};
module.exports = Model;
위에서는 바로 리턴을 해줬는데 더 많은 테이블이 있고, 관계 정의를 해줘야하는 경우에는 아래와 같이 작성하면 된다.
const { DataTypes } = require('sequelize');
const Model = (sequelize) => {
const Todo = sequelize.define(
'todo',
{
id : {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true,
},
title : {
type: DataTypes.STRING(100),
allowNull: false,
},
done : {
type: DataTypes.TINYINT(1),
allowNull: false,
},
},
//아무것도 정의해주지 않으면 시간도 같이 들어가기 때문에 아래의 코드를 작성해 없애줌
{
tablename: "todo",
timestamps: false,
}
);
관계정의
return{
Todo,
},
};
module.exports = Model;
모델을 정의 했으니 app.js를 만들어서 연결해준다. 여기서는 index.js로 사용했다.
index.js
const express = require('express');
const app = express();
const PORT = 8080;
const db = require('./models');
app.set('view engine', 'ejs'); //ejs를 사용할 때 설정
//body-parser
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
//router
const useRouter = require('./routes/router');
app.use('/', useRouter);
//404
app.use('*', (req, res)=>{
res.render('404');
});
//서버 오픈
db.sequelize.sync({force : true}).then(()=>{
app.listen(PORT, () => {
console.log(`http://localhost:${PORT}`);
});
});
- body-parser
body-parser는 미들웨어이다. 즉, 요청(request)과 응답(response) 사이에서 공통적인 기능을 수행하는 소프트웨어이고, 요청의 본문을 지정한 형태로 파싱해주는 미들웨어이다. 원래 Express는 요청을 처리할때 기본적으로 body를 undefined로 처리하기 때문에 바디파서로 요청의 body 부분을 원하는 형태로 파싱할 수 있다.
위에서는 json 파일로 파싱을 하고 있다.
- router
mvc 구조로 사용하기 위해 라우터 파일을 만들어서 연결해준다.
- 서버오픈
force를 false로 두면 기존 데이터베이스를 연결하는 것이고 true로 한다면 서버를 실행할때마다 연결된 데이터베이스를 갱신한다.
4. todo 리스트 보여주기와 추가하는 기능 만들기
라우터와 컨트롤러에서 작업을 진행한다. 먼저 /todos를 만들어주자 현재 폴더의 구조는 다음과 같다.
여기서 라우터와 컨트롤러 그리고 모델을 연결하여 투두리스트를 가져와보자 임의의 값을 mysql워크밴치로 넣어준다.
1은 투두리스트를 했다고 체크한 것이고 0은 못한것인다.
a. 데이터베이스에서 투두리스트 데이터 가지고 오기
일단 데이터베이스에서 가져오기 위해서
router.js
const express = require('express');
const router = express.Router();
const controller = require('../controller/Ctodo');
router.get('/todos', controller.get_todo);
module.exports = router;
models의 index.js
'use strict';
const Sequelize = require('sequelize');
const env = process.env.NODE_ENV || 'development';
// 지정된 환경변수가 없다면 'development'로 지정한다.
const config = require(__dirname + '/../config/config.json')[env];
// config/config.json 파일에 있는 설정값들을 불러온다.
// config객체의 env변수(development)키 의 객체값들을 불러온다.
// 즉, 데이터베이스 설정을 불러오는 것이다.
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.User = require('./todolist')(sequelize);
// 이렇게 정의한 모델과 연결해준다. 이를 컨트롤러로 가져와서 사용할 수 있다
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
Ctodo.js
const db = require('../models');
const models = db.User;
//위에서 만든 User를 가지고 온것이다.
const get_todo = async () => {
const todolist = await models.Todo.findAll({});
console.log('Ctodo에서 데이터 받아오는지 확인')
console.log(todolist);
}
module.exports = {
get_todo,
};
이를 node index.js로 실행했는데,
오류 내용 : The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received type number (1234)
이 오류가 났었다. 이유를 알아보니까 config.json 파일에 문자열 대신 다른 것이 들어가 생기는 오류라고 한다.
필자의 경우는 비밀번호를 문자열로 안적고 그냥 적어서 생기는 오류였다. 문자열로 처리해주니 잘 실행되었다.
근데 계속 테이블 이름을 todo로 정의했는데 계속 todos로 이름이 바뀌어서 정의가 됐었다 이는 시퀄라이즈가 테이블명을 자동으로 복수형으로 바꾸기 때문에 위에 timestamp를 정의한 option객체에서 tableName으로 이름을 고정해 주어야한다.
위의 작업을 모두 끝낸 후 node index.js를 실행하면 데이터베이스의 데이터들이 넘어오는 것을 확인할 수 있다.
이렇게 받아온 데이터를 json 형태로 변환시켜야한다.
기존에 내가 했던 방식은 빈 객체를 만든 후에 for문을 사용해 직접 데이터를 넣어서 만들었었다. 하지만 저번에 2번째 프로젝트를 하며 형들이 사용했던 forEach를 사용해서 객체에 넣은 뒤에 res.json을 통해 json 형식으로 보내주는 방식을 사용해볼 예정이다.
forEach문이란?
기본적으로 for문을 사용할려면 규칙을 다 적어줘야하는 번거로움이 있다. 이러한 번거로움을 해결해주는 녀석이 forEach문이다.
for(let i=0; i<배열명.length; i++){
console.log(i);
}
위와 같이 적는 for문을 forEach문으로 적으면
배열명.forEach(i => {
console.log(i);
});
이처럼 정말 간결하게 작성할 수 있다.
즉, 얼마나 반복을 돌아야하는지 정해주지 않아도 선택한 배열이 가지고 있는 요소만큼 반복을 돌아주는 것이다.
사용예시를 통해 더 자세히 알아보자
const arr = ['a','b','c','d'];
arr.forEach(function(item: 현재 돌고 있는 배열의 값, index: 앞의 값의 인덴스, arrnow: 현재 돌고 있는 배열 전체)
{
console.log(item,index,arrnow);
})
//출력 => a,0,['a','b','c','d'] // b,1,['a','b','c','d'] // c,2,['a','b','c','d']
// d,3,['a','b','c','d']
//응용하면 arrnow[index+1] 등을 입력하여 현재 돌고있는 값의 다음값을 출력 할 수도 있다.
이를 적용해 불러온 데이터를 객체에 넣어주었다.
Ctodo.js
const db = require('../models');
const models = db.User;
let todolist;
const set = async () => {
todolist = await models.todo.findAll({});
}
const get_todo = async (req, res) => {
await set();
const tododata = await todolist;
const todoarr = {};
tododata.forEach((data) => {
todoarr[data.id - 1] = {
id : data.id,
title: data.title,
done: data.done,
}
});
console.log('Ctodo에서 데이터 받아오는지 확인')
// console.log(tododata);
console.log(todoarr);
}
module.exports = {
get_todo,
};
이제 이 객체를 res.json으로 보내주면된다.
b. 투두리스트 업데이트하기
post로 보낸 값은 req.body로 받을 수 있다. 먼저 잘 받는지 console을 찍어보자 아직 프론트엔트 페이지를 완성하지 못했기 때문에 포스트맨을 사용하여 데이터를 보내준다.
Ctodo.js
const db = require('../models');
const models = db.User;
let todolist;
const set = async () => {
todolist = await models.todo.findAll({});
}
const get_todo = async (req, res) => {
await set();
const tododata = await todolist;
const todoarr = {};
tododata.forEach((data) => {
todoarr[data.id - 1] = {
id : data.id,
title: data.title,
done: data.done,
}
});
console.log('Ctodo에서 데이터 받아오는지 확인')
// console.log(tododata);
console.log(todoarr);
res.json(todoarr);
}
const post_todo = async (req, res) => {
const update_todo = req.body;
console.log(update_todo);
res.send(update_todo);
}
module.exports = {
get_todo,
post_todo,
};
잘 주고받는 것을 확인했다. 이제 받은 데이터를 데이터베이스로 보내는 기능을 완성해보자
매우 간단하다. models에서 todo 데이터베이스를 불러오고 create로 받은 데이터를 보내주면 된다.
포스트맨으로 데이터를 보냈을때,
터미널에 이렇게 뜨고 워크밴치에 업데이트된 것을 확인할 수 있다.
이제 업데이트된 데이터를 바로 적용시켜줘야하기 때문에 다시 데이터 베이스를 가져와서 res.json으로 프론트엔드 페이지에 보내준다.
이렇게 데이터를 가져오는 것과 업데이트 하는 기능을 만들었다.
아직 프론트엔드가 완성된 것이 아니라 다한 것은 아니다. 그전에 삭제와 수정 기능도 만들어보자.
'포스코x코딩온 KDT 8기 풀스택 과정 회고록' 카테고리의 다른 글
[포스코 코딩온 KDT 8기] 웹 풀스택 과정 76일(23.10.05)차 회고 | React - Redux (2) | 2023.10.05 |
---|---|
[포스코 코딩온 KDT 8기] 웹 풀스택 과정 리액트 개인 프로젝트 | 백엔드(2) - todolist 수정하기, 삭제하기 (0) | 2023.10.03 |
[포스코 코딩온 KDT 8기] 웹 풀스택 과정 66일(09.18)차 회고 | React-JSX (0) | 2023.10.01 |
[포스코 코딩온 KDT 8기] 웹 풀스택 과정 2차 프로젝트 | 서버 배포 >> 메인페이지 개발 시작 (0) | 2023.09.02 |
[포스코 코딩온 KDT 8기] 웹 풀스택 과정 48일(08.28)차 회고 | Soket (0) | 2023.08.28 |