#1. 객체지향 데이터베이스 프로그래밍
1. SQL Mapper
1) SQL Mapper란?
- Object와 SQL의 필드를 매핑하여 데이터를 객체화 하는 기술을 말한다.
- 객체와 데이블 간의 관계를 매핑 하는것은 아니다.
- SQL문을 직접 작성하고 쿼리 수행 결과를 어떠한 객체에 매핑할지 바인딩(적용) 하는 방법이다.
※ DAO(Data Access Object)
- 데이터를 처리해야하는 부분만 따로 분리하여 처리하는 것.
- 커넥션을 하나만 두고(싱글톤 패턴), 여러 사용자가 DAO interface를 사용하여 필요한 자료에 접근하는 것이다.
2) 사용 예시
- 아래와 같이 SQL 구문의 템플릿을 작성한다.
const sql = "INSERT INTO department (dname, loc) VALUES (#{dname}, #{loc})";
- 템플릿의 치환자에 적용될 값을 객체로 구성한다.
const input = {dname: 'hello', loc: 'world'};
- SQL에 데이터 객체를 맵핑하면 아래와 같이 완성된 SQL문을 얻을 수 있다.
INSERT INTO department (dname, loc) VALUES ('hello', 'world')
3) MyBatis
- 자바에서 사용하는 가장 대표적인 SQL Mapper Framework이다.
- 데이터를 데이터 전달을 위한 객체(DTO, Data Transfer Object)에 담아서 전달하고, SQL 수행 결과를 미리 정의해 놓는 클래스에 대한 객체에 매핑된 상태로 반환받는다.
- 자바스크립트에서는 JSON으로 표현하기 때문에 크게 어렵지 않다.
장점
- 쿼리문을 XML로 분리 할 수 있다.
- 복잡한 쿼리문을 작성 할 수 있다.
- 데이터 캐싱 기능으로 성능이 향샹된다.
- node와 java에서 둘 다 사용이 가능하다.
단점
- 객체와 쿼리문 모두 관리해야 한다.
- CRUD 메소드를 직접 다 구현해야 한다.
2. ORM
1) ORM이란?
- Object와 DB테이블을 매핑하여 데이터를 객체화 하는 방식이다.
- DBMS에 종속적이지 않는다.
- 복잡한 쿼리문은 처리하기 어렵다. (SQL Mapper와 혼용하여 처리 가능)
- 테이블 구조를 미리 클래스로 정의해 놓아야 하는 번거로움이 있다.
- 다루고자 하는 데이터베이스 테이블의 구조를 자바스크립트 클래스로 똑같이 만들어 놓아야 한다.
2) Sequelize
- Node.js에서 사용하는 대표적인 ORM 프레임워크이다.
- CRUD 메소드를 기본으로 제공한다.
- 1차 캐싱, 쓰기 지연, 변경 감지, 지연 로딩 등을 제공
- 그렇기 때문에 쿼리를 만들지 않아도 된다. (객체 중심으로 개발 가능)
const Sequelize = require('sequelize');
class Department extends Sequelize.Model {
static init(sequelize) {
return super.init({
deptno: {
type: Sequelize.INTEGER,
allowNull: false,
unique: true,
},
dname: {
type: Sequelize.STRING(50),
allowNull: false,
},
loc: {
type: Sequelize.STRING(50),
allowNull: true,
}
}, {
sequelize,
timestamps: false,
underscored: false,
modelName: 'Department',
tableName: 'department',
paranoid: false,
charset: 'utf8',
collate: 'utf8_general_ci'
});
}
static associate(db) {}
};
module.exports = Department;
3. Mybatis 사용하기
1) Mybatis
- 위에서 설명한 자바에서 사용하는 대표적인 SQL Mapper 프레임워크이다.
- 자바, Node 둘다 사용 가능
- SQL문을 XML 파일에 미리 정의해두 고, 치환자에 적용될 변수를 전달하여 완성된 SQL문을 반환 받는 프레임워크.
2) Mapper XML 작성 구조
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="Mapper의 식별자">
<select id="SQL문 식별값">
SELECT deptno, dname, loc FROM department WHERE deptno=#{deptno}
</select>
<insert id="SQL문 식별값">
...
</insert>
<update id="SQL문 식별값">
...
</update>
<delete id="SQL문 식별값">
...
</delete>
</mapper>
- SQL Mapper에서 변수로 치환되는 부분의 경우 #{변수명} 방식고 ${변수명} 방식이 있다.
- #{변수명} 의 경우, SQL Injection 공격에 대응하기 위해 모든 변수값에 홑따옴표를 강제로 적용하기 때문에 LIMIT절에서 사용할 수 없다.
- ${변수명} 의 경우, 전달 된 변수값을 원본 그대로 적용하기 때문에 SQL Injection 공격에 노출되어 있지만, 원문을 그대로 핸들링 할 수 있어서 복잡한 SQL 작성이 가능하다.
3) 패키지 참조
- 패키지 설치
yarn add mybatis-mapper
- 패키지 참조
// ES5
const mybatisMapper = require('mybatis-mapper');
// ES6
import mybatisMapper from 'mybatis-mapper';
4) Mapper 불러오기
- mapper는 용도에 따라 여러 개의 파일로 나누어 작성할 수 있다.
- 주로 단위 기능이나 테이블 단위로 분할하여 작성한다.
mybatisMapper.createMapper([
'mapper-1의 경로',
'mapper-2의 경로',
...
'mapper-n의 경로'
]);
4) SQL문 조합하기
let params = {테이블에 연결할 값}; // ex) #{deptno}
let query = mybatisMapper.getStatement('Mapper의 식별자', 'SQL문의 식별값', params);
// 어떤 mapper에서 sql문을 가져와서 params값 적용
console.log(query);
- 조합된 SQL문은 일반 DB 처리 방식으로 수행한다.
5) 사용 예시
- mappers/test.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="testMapper">
<!-- 단일행 조회를 위한 기능 정의 -->
<select id="selectItem">
SELECT deptno, dname, loc FROM department WHERE deptno=#{deptno};
</select>
<!-- 다중행 조회를 위한 기능 정의 -->
<select id="selectList">
SELECT deptno, dname, loc FROM department
<!-- where절 사용 -->
<where>
<if test="dname != null and dname != ' '">
dname LIKE concat('%', #{dname}, '%')
</if>
<if test="loc != null and loc != ' '">
OR loc LIKE concat('%', #{loc}, '%')
<!-- or 을 통해 둘 또는 둘중에 하나만 적용(알아서 해줌) -->
</if>
</where>
ORDER BY deptno DESC
<!-- 페이지 구현을 위한 LIMIT절 추가 -->
<if test="listCount > 0">
LIMIT ${offset}, ${listCount}
</if>
</select>
</mapper>
- test.js
// mybatis 모듈 참조
import MybatisMapper from 'mybatis-mapper';
// mapper 불러오기
MybatisMapper.createMapper([
'./mappers/test.xml',
]);
// 단일행 조회를 위한 기능 정의
let params = {deptno: 201};
let query = MybatisMapper.getStatement('DepartmentMapper', 'selectItem', params);
console.log('단일행 조회 쿼리문 ::' + query);
// 다중행 조회를 위한 기능 정의
params = {dname: '풀스텍', offset: 0, listCount: 3};
query = MybatisMapper.getStatement('DepartmentMapper', 'selectList', params);
console.log('다중행 조회 쿼리문 ::' + query);
※ 출력결과
'국비수업 > Node.js' 카테고리의 다른 글
[Node.js] Service Layer / 페이지 번호 구현 (0) | 2022.07.11 |
---|---|
[Node.js] CORS / MVC 패턴 (0) | 2022.07.10 |
[Node.js] MySQL 연동하기 (0) | 2022.07.06 |
[Node.js] SingleTon 패턴 (0) | 2022.07.06 |
[Node.js/express] File Upload (0) | 2022.07.04 |