서버 구현
미니 블로그의 글, 댓글 데이터를 관리할 서버를 구현해보겠습니다.
server 폴더를 만들고 npm init
을 실행하여 npm을 사용할 수 있는 초기 환경을 설정합니다.
express + MVC
참고 글 : MVC 패턴
참고 글을 토대로 MVC 패턴을 활용해 구현해보겠습니다.
View 부분은 앞서 구현한 React를 활용하므로 Router, Controller, Model을 구현해보겠습니다.
폴더 구성
client
src
component
ui
server
src
config
controllers
models
routes
body-parser 설정
server 폴더에 app.js
파일을 만들어 작성합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// app.js
import express from "express";
import bodyParser from "body-parser";
import "dotenv/config";
const app = express();
// 미들웨어
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// 3000 포트로 서버 오픈
app.listen(3000, () => {
console.log("express server on port 3000");
});
Router 설정
Routes 폴더에 route_post.js
파일을 만들어 express router를 작성합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
import express from "express";
import ctrl from "../controllers/controller_post.js";
const router = express.Router();
router.get("/post", ctrl.getPost); // 전체 글 조회
router.get("/post/:id", ctrl.getPostById); // 특정 글 조회
router.get("/comment/:id", ctrl.getComment); // 댓글 조회
router.post("/post", ctrl.addPost); // 글 추가
router.post("/comment/:id", ctrl.addComment); // 댓글 추가
export default router;
서버 파일인 app.js
와 라우터 파일 route_post.js
파일을 미들웨어로 연결합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// app.js
import express from "express";
import bodyParser from "body-parser";
import "dotenv/config";
import postRouter from "./src/routes/route_post.js";
const app = express();
// Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// router
app.use("/board", postRouter);
app.listen(5000, () => {
console.log("Server On");
});
DB 테이블 생성
먼저 기존에 data.json
파일에 작성해둔 글, 댓글 데이터를 기반으로 데이터 모델링을 해보겠습니다.
단계별 산출물(명세서)들을 간단하게 작성해보겠습니다.
개념적 데이터 모델링
논리적 데이터 모델링
물리적 데이터 모델링
Mysql에 EERD 모델을 만들어서 테이블을 생성합니다.
생성한 테이블에 데이터 추가
data.json
파일에 작성해둔 글, 댓글 데이터를 생성한 테이블에 추가해보겠습니다.
client 폴더의 data.json 파일을 server 폴더로 가져와 처리하겠습니다.
mysql2/promise 모듈의 createPool을 활용해 생성한 테이블을 연동해보겠습니다.
참고 글 : Mysql2
ES 모듈에서 json파일을 import해서 사용할 떄는
assert{ type: "json" }
을 붙여야만 모듈이 정상적으로 작동합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import mysql from "mysql2/promise";
import data from "./data.json" assert { type: "json" };
import "dotenv/config";
const pool = await mysql.createPool({
host: process.env.DB_HOST, //실제로 연결할 데이터베이스의 위치
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: "posts", //데이터베이스 이름
port: 3306,
connectionLimit: 30,
});
const conn = await pool.getConnection(async (conn) => conn);
data.forEach(async (post, i) => {
let { id: post_id, title, content: post_content, comments } = post;
try {
let [rows] = await conn.query(
"INSERT INTO post (post_id, title, content) VALUES (?, ?, ?)",
[post_id, title, post_content]
);
return rows;
} catch (err) {
console.log(err);
} finally {
conn.release();
}
comments.forEach(async (comment, i) => {
let { id: comment_id, content: comment_content } = comment;
try {
let [rows] = await conn.query(
"INSERT INTO comment (comment_id, content, post_id) VALUES (?, ?, ?)",
[comment_id, comment_content, post_id]
);
return rows;
} catch (err) {
console.log(err);
} finally {
conn.release();
}
});
});
Controller 설정
controllers 폴더에 controller_post.js
파일을 만들어 작성하겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import postStorage from "../models/model_post.js";
export default {
getPost: async (req, res) => {
const data = await postStorage.getPosts();
res.json(data);
},
getPostById: async (req, res) => {
let postId = req.params.id;
const data = await postStorage.getPostById(postId);
res.json(data[0]);
},
addPost: async (req, res) => {
let { title, content } = req.body;
const data = await postStorage.addPost(title, content);
res.json(data);
},
getComment: async (req, res) => {
let postId = req.params.id;
const data = await postStorage.getComments(postId);
res.json(data);
},
addComment: async (req, res) => {
let postId = req.params.id;
let content = req.body.content;
const data = await postStorage.addComment(postId, content);
res.json(data);
},
};
Models 설정
Model은 Controller로 부터 요청을 받아 DB에 접근해 CRUD 로직을 처리합니다.
models 폴더에 model_post.js
파일을 만들고 작성해보겠습니다.
- 위에서 데이터 추가할 때 작성한
mysql2/promise
모듈로 커넥션 풀을 생성하고 연동하는 부분은 config 폴더에 따로 빼주고 import해서 사용하겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import conn from "../config/db_pool.js";
class postStorage {
static async getPosts() {
try {
const [rows] = await conn.query("SELECT * FROM post");
return rows;
} catch (err) {
console.log(err);
} finally {
conn.release();
}
}
static async getPostById(postId) {
try {
const [rows] = await conn.query("SELECT * FROM post WHERE post_id = ?", [
postId,
]);
return rows;
} catch (err) {
console.log(err);
} finally {
conn.release();
}
}
static async addPost(title, content) {
try {
const [rows] = await conn.query(
"INSERT INTO post (title, content) VALUE (?,?)",
[title, content]
);
return rows;
} catch (err) {
console.log(err);
} finally {
conn.release();
}
}
static async getComments(postId) {
try {
const [rows] = await conn.query(
"SELECT (content) FROM comment WHERE post_id = ?",
[postId]
);
return rows;
} catch (err) {
console.log(err);
} finally {
conn.release();
}
}
static async addComment(postId, content) {
try {
const [rows] = await conn.query(
"INSERT INTO comment (content, post_id) VALUE (?, ?) ",
[content, postId]
);
return rows;
} catch (err) {
console.log(err);
} finally {
conn.release();
}
}
}
export default postStorage;
결과 테스트
응답이 잘 오는 것을 확인했습니다.
다음 포스트에서는 React에서 Server에 요청해서 받은 데이터들로 출력하도록 구현해보겠습니다.