#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

+ Recent posts