Express.js + Mongoose ODM
Express.js는 프로젝트 구조를 자유롭게 구성할 수 있기 때문에
어느 부분에 Mongoose ODM을 위치시키면 좋을지 적절한 위치를 결정하는 것이 중요하다.
Mongoose ODM 위치 정하기
일반적으로 models 디렉터리에 Schema와 Model을 같이 위치시킨다. app 객체는 어플리케이션 시작을 의미하는 부분이므로 해당 부분에 데이터베이스 연결을 명시하는 mongoose.connect를 위치한다.

Mongoose ODM 커넥션 이벤트
Express.js 어플리케이션은 종료되지 않고 동작하기 때문에 계속해서 데이터베이스가 정상적으로 동작하는지를 파악하기 위해 동작 중에 발생하는 데이터베이스 연결 관련 이벤트에 대한 처리를 하는 것이 좋다.

코드 | 설명 |
mongoose.connect('----'); | 이벤트 선언 |
'connected' | 연결 완료 |
'disconnected' | 연결이 끊김 |
'reconnected' | 재연결 완료 |
'reconnectFailed' | 재연결 시도 횟수 초과 |
Sequelize ORM
Object-Relational Mapping
MySQL, PostgreSQL 등의 RDBMS를 이용하는 간단한 방법이다. ODM이 단순히 모델에 집중하여 관리하는 것에 반해, ORM은 테이블 관계와 쿼리 등의 기능을 더욱 단순화하는 용도로 주로 사용한다. 복잡한 SQL을 단순화하는 것이다.
Sequelize ORM 작성과 사용 방법 예제코드
DB 연결

sequelize도 연결을 관리하는 간단한 방법을 제공한다. mongoose가 MongoDB만 연결이 가능한 데에 반해 sequelize는 MySQL, PostgreSQL, SQLite 등 다양한 RDBMS에 연결 가능하다. Mongoose는 MongoDB만을 위한 것이었는데 Sequelize는 dialect 부분에 어떤 데이터베이스를 활용할지 작성해주면 각각의 경우에 모두 대응할 수 있다. 이 또한 구조화가 되는 RDB의 장점이기도 하다.
스키마 작성

sequelize는 define을 통해 Schema를 생성한다. mongoose.Schema와 유사하지만 sequelize는 Schema가 DDL도 생성해준다. DDL은 Data Definition Language와 같이 가운데에 '정의하다' 라는 뜻을 갖고 있다. RDB에서 어떤 데이터베이스 혹은 테이블이 어떤 데이터를 가져야 하는지를 정의한 SQL 구문이 바로 DDL 이다. SQL의 단점이었던 구조화를 위해서 사용했던 복잡한 구문에 대한 부담이 줄어드는 것이다.
스키마 작성 - 관계 정의

sequelize를 이용하면 테이블 간의 관계를 Code-Level로 관리할 수 있다. 데이터베이스까지 가지 않아도 JavaScript 코드 내에서 쉽게 관리할 수 있다.
User.hasMany(Post); : User 하나가 Post를 여러 개 가진다.
Post.belongsTo(User); : Post는 User에게 귀속된다.
관계중심의 데이터베이스의 핵심인 '관계'를 코드 상에서 정리할 수 있다. 이를 이용하면 외래키 설정(foreign key, 어떤 정보를 다른 데이터베이스에서 접근할 때 사용)과 제약조건(글자수, allowNULL)까지 DDL로 생성해준다. 또한 다대다 관계 설정을 통해 relation table도 자동으로 생성해준다. Sequelize ORM이 자동으로 생성하여 데이터를 핸들링한다.
다대다 관계 : 어떤 요소가 다른 요소를 여러 개를 가질 수 있고, 또 역으로도 그런 관계를 가지는 것을 의미한다.
relation table : 복잡한 다대다 관계에서 두 테이블이 있을 때 이 테이블을 연결할 수 있는 하나의 테이블
쿼리

Operator를 이용해 ODM에서 했던 것과 유사하게 SQL 쿼리를 코드로 작성 가능하다. 예를 들어 User.findAll로 해당하는 요소를 전부 가져오라고 한 뒤, where을 통해 key-value 형태로 제한 조건을 명시할 수 있다. 스키마와의 관계 설정을 한 경우, include를 사용하여 자동으로 join 쿼리 생성 가능하다.
Synchronization

define된 model 데이터를 바탕으로 DDL을 자동으로 실행해준다. 데이터베이스에도 실제로 해당하는 정보의 데이터를 담을 수 있는 구조가 짜여진다. 직접 데이터베이스에 접속하여 테이블 생성 및 관리를 할 필요가 없다. 하지만 자동으로 생성된 DDL을 따르지 않으면 테이블 관리가 어려워진다. Sync 과정을 통해서 테이블의 형태를 정하게 되면 어떻게 만들었는지를 잘 기억했다가 활용하는 것이 좋다.
Sequelize ORM 정리
Mongoose ODM과 달리 Sequelize ORM은 RDB를 다룰 수 있는 ORM이었다.
Sequelize ORM 을 사용하면 데이터베이스에 직접 DDL을 하지 않고
JavaScript 코드로 테이블 및 관계를 관리할 수 있다.
또한 RDB의 어려운 점 중 하나인 join을 간단하게 사용할 수 있다.
특정 조건이 포함된 GET 요청을 처리하는 API 만들기
MongoDB에서 특정 조건에 해당하는 데이터를 반환하는 GET 요청을 처리하기 위한 API를 작성해봅니다.
현재 MongoDB에는 학생의 데이터가 담겨져있습니다.
router에서 /students 경로를 통해 GET 요청을 하고, URI에 입력된 조건으로 특정 학생 정보를 반환하는 코드를 완성해봅시다.
지시사항
- routes/students.js에서 특정 전공(major) 을 GET 요청으로 받아, 해당 전공의 학생들만 JSON 형태로 내보내는 코드를 작성하세요.
- URI에 입력되는 형태는 /students?major=전공입니다.
- DB에서 데이터를 가져오기 위해서 비동기 처리를 해줘야 합니다.
실행 결과
/students?major=컴퓨터공학과 입력 시,

Tips!
- 조건을 추가해 GET 요청을 처리하는 방법은 Path Variable과 Query Parameter 두 가지가 있습니다. 각각 아래와 같은 상황에서 주로 사용합니다.
- Path Variable: 경로를 변수로 사용하여 /student/1과 같이 나타내어 id가 1번인 데이터를 넘깁니다. 특정 리소스를 찾을 때 주로 사용합니다.
- Query Parameter: 경로 뒤에 데이터를 함께 념겨 /student?id=1과 같이 나타냅니다. 리소스를 정렬하거나 필터링할 때 주로 사용합니다.
- express에서 Path Variable은 request.params를 이용해 가져오고, Query Parameter는 request.query를 이용해 가져옵니다.
- 엘리스 실습 창에 플랫폼을 구동하기 위한 URI가 포함되어 있어 작은 화면에서 진행하는 경우, 결과를 제대로 확인할 수 없습니다. 반드시 창을 키워서 확인해보세요.
students.js
const { Router } = require("express");
const { Student } = require("../models");
const router = Router();
// 지시사항을 참고하여 코드를 완성하세요.
router.get("/", async (req, res) => {
const search_major = req.query.major;
const students = await Student.find({major:
search_major})
res.json(students)
});
module.exports = router;
index.js
const express = require("express");
const mongoose = require("mongoose");
// router와 model을 불러옵니다.
const studentRouter = require("./routes/students");
const { Student } = require("./models");
// app을 생성하고 mongoDB를 연결합니다.
const app = express();
mongoose.connect("mongodb://localhost:27017/college");
// JSON 데이터를 제대로 파싱하기 위한 코드입니다.
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// "/" 경로 페이지에서 기본 문구를 띄웁니다.
app.get("/", (req, res) => {
res.send("Home Page");
});
// router를 연결합니다.
app.use("/students", studentRouter);
// favicon 에러를 해결하기 위한 코드입니다.
app.get("/favicon.ico", (req, res) => res.status(204));
// 8080번 포트에 연결합니다.
app.listen(8080);
// 학생 데이터를 데이터베이스에 삽입합니다.
async function run() {
let students = [
{
name: "하병지",
age: 20,
major: "컴퓨터공학과",
},
{
name: "양기현",
},
{
name: "전진수",
age: 23,
},
{
name: "강현숙",
major: "기계공학과",
},
{
name: "허선진",
age: 21,
major: "컴퓨터공학과",
},
{
name: "박지석",
age: 21,
major: "화학공학과",
},
{
name: "송형빈",
major: "컴퓨터공학과",
},
{
name: "설효주",
age: 23,
major: "화학공학과",
},
{
name: "윤동윤",
age: 25,
major: "컴퓨터공학과",
},
{
name: "장지민",
major: "기계공학과",
},
{
name: "추재영",
age: 23,
major: "기계공학과",
},
];
await Student.create(students);
}
run();
'AI / DL > 엘리스 SW 코딩 훈련 트랙' 카테고리의 다른 글
[SW 코딩 훈련] Express.js와 MongoDB 03. MongoDB와 Mongoose (0) | 2022.11.29 |
---|---|
[SW 코딩 훈련] Express.js와 MongoDB 02. REST API (0) | 2022.11.28 |
[SW 코딩 훈련] Express.js와 MongoDB 01. Express.js의 미들웨어 (0) | 2022.11.26 |
[SW 코딩 훈련] Node.js와 Express.js 04. 웹과 Express.js (0) | 2022.11.25 |
[SW 코딩 훈련] Node.js와 Express.js 03. NPM과 모듈 (0) | 2022.11.24 |
댓글