Node.JS에서 MyBatis3 Mapper XML 파일을 이용하기

1. Mybatis Mapper 설치하기 (터미널에서 실행합니다.)
npm install mybatis-mapper --save

2. src\db에 mappers\mariadb\lunchmenu 디렉터리를 생성하고 lunchmenu-sql.xml 파일을 생성합니다.

XML은 MyBatis3 구문과 동일합니다.
<?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>
<mapper>의 namespace(네임스페이스) 속성은 Mapper XML 파일들을 서로 구분하기 위해서 사용됩니다. 그래서 하나의 Mapper XML 파일만 가리켜야 하기 때문에 중복되지 않아야 합니다.
여기서는 namespace(네임스페이스)를 프로젝트 명과 XML 파일이 있는 경로를 조합하여 사용하겠습니다.
프로젝트 명 : apiserver
XML 파일이 있는 경로 : db\mappers\mariadb\lunchmenu
그래서 mapper namespace는 apiserver.db.mappers.mariadb.lunchmenu입니다.
<?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="apiserver.db.mappers.mariadb.lunchmenu">
<select id="">
</select>
<insert id="">
</insert>
<update id="">
</update>
<delete id="">
</delete>
</mapper>
<mapper> 안에서는 <select>(SELECT 쿼리문), <insert>(INSERT 쿼리문), <update>(UPDATE 쿼리문), <delete>(DELEETE 쿼리문)를 설정할 수 있습니다.
<select>, <insert>, <update>, <delete>의 id 속성 값은 식별자로 중복되지 않는 이름으로 입력합니다.
id 속성은 mybatisMapper.getStatement() 함수에서 구문을 찾을 때 사용됩니다.
id 속성 값에 대한 접두사(Prefix)와 접미사(suffix)를 이용하여 다음과 같은 명명 규칙(NamingRule)을 정합니다.
DB : Insert, Select, Update, Delete
- SELECT 쿼리문으로 여러 로우를 가져오면 select<모델명>List
- SELECT 쿼리문으로 로우 수를 가져오면 select<모델명>ListCount
- SELECT 쿼리문으로 한 로우만 가져오면 select<모델명>Item
- SELECT 쿼리문으로 하나의 값만 가져오면 select<모델명>Value
- INSERT 쿼리문은 insert<모델명>Item
- UPDATE 쿼리문으로 한 로우만 수정하면 update<모델명>Item
- UPDATE 쿼리문으로 여러 로우를 수정하면 update<모델명>List
- DELEETE 쿼리문으로 한 로우만 삭제하면 delete<모델명>Item
- DELEETE 쿼리문으로 여러 로우를 삭제하면 delete<모델명>List
CRUD : Create, Read, Update, Delete (CRUDL : Create, Read, Update, Delete, List)
- SELECT 쿼리문으로 여러 로우를 가져오면 read<모델명>List (list<모델명>)
- SELECT 쿼리문으로 로우 수를 가져오면 read<모델명>ListCount (list<모델명>Count)
- SELECT 쿼리문으로 한 로우만 가져오면 read<모델명>Item
- SELECT 쿼리문으로 하나의 값만 가져오면 read<모델명>Value
- INSERT 쿼리문은 create<모델명>Item
- UPDATE 쿼리문으로 한 로우만 수정하면 update<모델명>Item
- UPDATE 쿼리문으로 여러 로우를 수정하면 update<모델명>List
- DELEETE 쿼리문으로 한 로우만 삭제하면 delete<모델명>Item
- DELEETE 쿼리문으로 여러 로우를 삭제하면 delete<모델명>List
ABCD : Add, Browse, Change, Delete
- SELECT 쿼리문으로 여러 로우를 가져오면 browse<모델명>List
- SELECT 쿼리문으로 로우 수를 가져오면 browse<모델명>Count
- SELECT 쿼리문으로 한 로우만 가져오면 browse<모델명>Item
- SELECT 쿼리문으로 하나의 값만 가져오면 browse<모델명>Value
- INSERT 쿼리문은 add<모델명>Item
- UPDATE 쿼리문으로 한 로우만 수정하면 change<모델명>Item
- UPDATE 쿼리문으로 여러 로우를 수정하면 change<모델명>List
- DELEETE 쿼리문으로 한 로우만 삭제하면 delete<모델명>Item
- DELEETE 쿼리문으로 여러 로우를 삭제하면 delete<모델명>List
BREAD : Browse, Read, Edit, Add, Delete
- SELECT 쿼리문으로 여러 로우를 가져오면 browse<모델명>
- SELECT 쿼리문으로 로우 수를 가져오면 browse<모델명>Count
- SELECT 쿼리문으로 한 로우만 가져오면 read<모델명>
- SELECT 쿼리문으로 하나의 값만 가져오면 read<모델명>Value
- INSERT 쿼리문은 add<모델명>Object
- UPDATE 쿼리문으로 한 로우만 수정하면 edit<모델명>Object
- UPDATE 쿼리문으로 여러 로우를 수정하면 edit<모델명>List
- DELEETE 쿼리문으로 한 로우만 삭제하면 delete<모델명>Object
- DELEETE 쿼리문으로 여러 로우를 삭제하면 delete<모델명>List
DAVE : Delete, Add, View, Edit
- SELECT 쿼리문으로 여러 로우를 가져오면 view<모델명>List
- SELECT 쿼리문으로 로우 수를 가져오면 view<모델명>Count
- SELECT 쿼리문으로 한 로우만 가져오면 view<모델명>Object
- SELECT 쿼리문으로 하나의 값만 가져오면 view<모델명>Value
- INSERT 쿼리문은 add<모델명>Object
- UPDATE 쿼리문으로 한 로우만 수정하면 edit<모델명>Object
- UPDATE 쿼리문으로 여러 로우를 수정하면 edit<모델명>List
- DELEETE 쿼리문으로 한 로우만 삭제하면 delete<모델명>Object
- DELEETE 쿼리문으로 여러 로우를 삭제하면 delete<모델명>List
GRADE : Get, Remove, Add, Delete, Edit
- SELECT 쿼리문으로 여러 로우를 가져오면 get<모델명>List
- SELECT 쿼리문으로 로우 수를 가져오면 get<모델명>ListCount
- SELECT 쿼리문으로 한 로우만 가져오면 get<모델명>Object
- SELECT 쿼리문으로 하나의 값만 가져오면 get<모델명>Value
- INSERT 쿼리문은 add<모델명>Object
- UPDATE 쿼리문으로 한 로우만 수정하면 edit<모델명>Object
- UPDATE 쿼리문으로 여러 로우를 수정하면 edit<모델명>List
- UPDATE 쿼리문으로 한 로우만 사용(검색)되지 않게 수정하면 remove<모델명>Object
- UPDATE 쿼리문으로 여러 로우가 사용(검색)되지 않게 수정하면 remove<모델명>List
- DELEETE 쿼리문으로 한 로우만 삭제하면 delete<모델명>Object
- DELEETE 쿼리문으로 여러 로우를 삭제하면 delete<모델명>List
DB 명명 규칙으로 사용하겠습니다.
3. lunchmenu-sql.xml 파일에 src\api\v1\lunchmenu.js 파일에 있는 query를 <select>, <insert>, <update>, <delete> 구문으로 추가합니다.

<?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="apiserver.db.mappers.mariadb.lunchmenu">
<select id="selectLunchMenuList">
SELECT *
FROM tb_lunch_menu
ORDER BY REG_DTM DESC
</select>
<select id="selectLunchMenuItem">
SELECT *
FROM tb_lunch_menu
WHERE seq = ${seq}
</select>
<insert id="insertLunchMenuItem">
INSERT INTO tb_lunch_menu
(
menu_name
)
VALUES
(
#{menuName}
)
</insert>
<update id="updateLunchMenuItem">
UPDATE tb_lunch_menu
SET menu_name = #{menuName}
WHERE seq = ${seq}
</update>
<delete id="deleteLunchMenuItem">
DELETE
FROM tb_lunch_menu
WHERE seq = ${seq}
</delete>
</mapper>
SQL 문에 있는 #{}, ${}는 전달되는 변수가 들어갈 곳입니다.
#{}은 변수에 들어 갈 값이 따옴표로 묶여 변환됩니다. → 문자열에 사용
${}은 변수 그대로 변환됩니다. → 숫자에 사용
API 수정
1. src\api\v1\lunchmenu.js 파일을 수정합니다.
const express = require('express');
const router = express.Router();
const getDBConnection = require('../../db/mariadb/connection');
const mybatisMapper = require('mybatis-mapper');
// XML 파일 경로는 상대 경로가 아닌 절대 경로(Root 경로)로 './' 또는 '/' 없이 입력해야 합니다.
mybatisMapper.createMapper(['./src/db/mappers/mariadb/lunchmenu/lunchmenu-sql.xml']);
// SQL 언어 형식과 들여쓰기를 설정
const format = {language: 'mariadb', indent: ' '};
createMapper([XML Files])
- [XML Files]은 XML 파일 경로들이 있는 배열입니다.
- XML 파일 경로는 상대 경로가 아닌 절대 경로(Root 경로)로 './' 또는 '/' 없이 입력해야 합니다.
- Root에 있다면 ./test.xml, test.xml
- Root의 하위 디렉터리인 src에 있다면 ./src/test.xml, src/test.xml
- 지정된 xml 파일을 읽고 구문 분석하여 SQL 문을 생성할 준비를 합니다.
format 변수의 language 옵션
(https://github.com/sql-formatter-org/sql-formatter/blob/HEAD/docs/language.md#options)

// 전체 점심 메뉴 리스트를 리턴합니다.
router.get('/', async function(req, res, next) {
:
//const query = "SELECT * FROM tb_lunch_menu ORDER BY REG_DTM DESC";
const query = mybatisMapper.getStatement('apiserver.db.mappers.mariadb.lunchmenu',
'selectLunchMenuList', {}, format);
:
data = await conn.query(query);
:
});
getStatement(namespace: string, sql: string, param?: mybatisMapper.Params, format?: mybatisMapper.Format)
- namespace은 네임스페이스로 XML 파일에 있는 <mapper>의 namespace 속성 값입니다.
- sql는 XML 파일에 있는 <select>, <insert>, <update>, <delete>의 id 속성 값입니다.
- Parameters는 XML 파일에 있는 SQL 문에 있는 #{}, ${} 변수에 들어갈 값입니다.
- format은 옵션입니다. SQL 언어와 들여쓰기를 설정할 수 있습니다. (https://www.npmjs.com/package/sql-formatter)
// 점심 메뉴 번호로 검색하여 점심 메뉴를 리턴합니다.
router.get('/:no', async function(req, res, next) {
:
const params = {
seq : req.params.no
};
//const query = "SELECT * FROM tb_lunch_menu WHERE seq = ?";
const query = mybatisMapper.getStatement('apiserver.db.mappers.mariadb.lunchmenu',
'selectLunchMenuItem', params, format);
:
data = await conn.query(query);
:
});
// 점심 메뉴를 등록합니다.
router.post('/', async function(req, res, next) {
:
const params = {
menuName : req.body.menuName
};
//const query = "INSERT INTO tb_lunch_menu (menu_name) VALUES(?)";
const query = mybatisMapper.getStatement('apiserver.db.mappers.mariadb.lunchmenu',
'insertLunchMenuItem', params, format);
:
data = await conn.query(query);
:
});
// 점심 메뉴를 수정합니다.
router.put('/:no', async function(req, res, next) {
:
const params = {
menuName : req.body.menuName,
seq : req.params.no
};
//const query = "UPDATE tb_lunch_menu SET menu_name = ? WHERE seq = ?";
const query = mybatisMapper.getStatement('apiserver.db.mappers.mariadb.lunchmenu',
'updateLunchMenuItem', params, format);
:
data = await conn.query(query);
:
});
// 점심 메뉴를 삭제합니다.
router.delete('/:no', async function(req, res, next) {
:
const params = {
seq : req.params.no
};
//const query = "DELETE FROM tb_lunch_menu WHERE seq = ?";
const query = mybatisMapper.getStatement('apiserver.db.mappers.mariadb.lunchmenu',
'deleteLunchMenuItem', params, format);
:
data = await conn.query(query);
:
});
'Vue.js 3 & NodeJS > 사내교육 - 점심 메뉴' 카테고리의 다른 글
| [6] Frontend 개발 - 등록 뷰 (AddView) 생성 (0) | 2026.08.03 |
|---|---|
| [5] Backend 개발 - API Server 개발, Node.JS + Search (0) | 2026.08.03 |
| [4] Backend 개발 - API Server 개발, Node.JS + Paging (0) | 2026.08.03 |
| [2] Frontend 개발 (0) | 2026.08.02 |
| [1] Backend 개발 - API Server 개발 (0) | 2026.08.02 |