1. 학습 주제
Java 애플리케이션에서 MyBatis를 이용해 데이터베이스에 접근하는 기본 흐름을 학습했다.
이번 범위의 핵심은 다음 세 가지다.
- MyBatis가 어떤 역할을 하는 프레임워크인지 이해하기
- Configuration → SqlSessionFactory → SqlSession 흐름 이해하기
- XML Mapper를 이용해 SQL과 Java 코드를 분리하고 CRUD 구조 만들기
즉 이번 내용은 JDBC를 직접 작성하지 않고, MyBatis를 통해 SQL 실행 구조를 정리하는 방법을 배우는 단계였다.
2. MyBatis란 무엇인가
MyBatis
영속성 프레임워크이자 SQL Mapper 프레임워크
영속성이란, Java 객체의 데이터를 데이터베이스에 저장하거나 데이터베이스에서 다시 조회하는 것을 의미한다.
MyBatis는 Java 코드와 SQL 사이를 연결해준다.
Java 코드
↓
MyBatis
↓
SQL 실행
↓
DB
JDBC를 직접 쓰면 개발자가 직접 해야 하는 일이 많다.
- DB 연결
- PreparedStatement 생성
- SQL 실행
- ResultSet 처리
- 객체에 값 담기
- 자원 close
MyBatis는 이 중 많은 부분을 대신 처리해준다.
개발자는 SQL을 Mapper에 작성하고, Java 코드에서는 MyBatis API를 통해 SQL을 호출한다.
3. SQL Mapper 프레임워크란 무엇인가
MyBatis는 ORM보다는 SQL Mapper에 가깝다.
ORM은 객체 중심으로 DB를 다루는 방식이고,
SQL Mapper는 SQL을 직접 작성하되 그 SQL과 Java 객체를 연결해주는 방식이다.
MyBatis에서는 SQL을 XML Mapper나 어노테이션에 작성한다.
<select id="selectAllMenu" resultMap="menuResultMap">
SELECT menu_code
, menu_name
, menu_price
, category_code
, orderable_status
FROM tbl_menu
WHERE orderable_status = "Y"
ORDER BY menu_code
</select>
Java에서는 이 SQL의 namespace.id를 이용해 호출한다.
sqlSession.selectList("MenuMapper.selectAllMenu");
4. MyBatis 핵심 흐름
가장 중요한 구조는 이것이다.
Configuration
↓
SqlSessionFactory
↓
SqlSession
↓
Mapper SQL 실행
↓
DB 작업
SqlSession
: 데이터베이스 작업을 실제 요청하기 위한 통로
SqlSessionFactory
: SqlSession을 만들기 위한 공장
Configuration
: SqlSessionFactory를 만들기 위한 설정 정보
XML config 또는 Java config로 작성 가능
즉 SqlSession을 바로 만들 수 있는 것이 아니라,
반드시 설정 정보를 바탕으로 SqlSessionFactory를 먼저 만들어야 한다.
5. Configuration
Configuration은 MyBatis 실행에 필요한 설정 묶음이다.
포함되는 정보:
- DB 연결 정보
- 트랜잭션 관리 방식
- DataSource 종류
- Mapper 등록 정보
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/menudb"/>
<property name="username" value="ohgiraffers"/>
<property name="password" value="ohgiraffers"/>
</dataSource>
</environment>
여기서 중요한 부분은 다음과 같다.
transactionManager type="JDBC"
→ 개발자가 commit, rollback을 직접 제어
dataSource type="POOLED"
→ DB 커넥션을 매번 새로 만들지 않고 풀에서 재사용
6. SqlSessionFactory
SqlSessionFactory는 SqlSession을 만들어내는 공장이다.
private static SqlSessionFactory sqlSessionFactory;
SqlSessionFactory는 애플리케이션 실행 중 여러 번 만들 필요가 없다.
그래서 static 필드로 두고 한 번만 생성해서 재사용한다.
if(sqlSessionFactory == null) {
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
정리하면:
SqlSessionFactory는 무겁다.
애플리케이션에서 한 번 만들어 재사용한다.
7. SqlSession
SqlSession은 실제 DB 작업을 요청하는 통로이다.
SqlSession sqlSession = sqlSessionFactory.openSession(false);
여기서 false는 auto commit을 끈다는 의미다.
openSession(false)
→ 자동 커밋 안 함
→ insert, update, delete 후 직접 commit 또는 rollback 필요
조회는 DB 내용을 변경하지 않기 때문에 보통 commit이 필요 없다.
하지만 등록, 수정, 삭제는 DB 상태를 바꾸기 때문에 성공하면 commit(), 실패하면 rollback()을 해야 한다.
8. SqlSession 생명주기
SqlSessionFactory
→ 한 번 만들고 계속 재사용
SqlSession
→ DB 작업이 필요할 때 열고
→ 작업이 끝나면 반드시 close
즉 SqlSessionFactory와 SqlSession의 생명주기는 다르다.
SqlSessionFactory: 애플리케이션 전체에서 공유
SqlSession: 요청/작업 단위로 생성 후 종료
9. XML Mapper
MyBatis에서는 SQL을 XML Mapper에 작성할 수 있다.
<mapper namespace="MenuMapper">
namespace는 Mapper 파일의 이름표 역할을 한다.
DAO에서는 이 이름표와 SQL id를 조합해서 호출한다.
sqlSession.selectList("MenuMapper.selectAllMenu");
구조는 다음과 같다.
MenuMapper → namespace
selectAllMenu → SQL id
MenuMapper.selectAllMenu
→ 실행할 SQL의 전체 이름
10. resultMap
DB 컬럼명과 Java 필드명이 다를 때는 resultMap을 사용한다.
DB 컬럼:
menu_code
menu_name
menu_price
category_code
orderable_status
Java 필드:
code
name
price
categoryCode
orderableStatus
이름이 다르기 때문에 MyBatis가 자동으로 정확히 매핑하기 어렵다.
그래서 직접 연결해준다.
<resultMap id="menuResultMap" type="com.ohgiraffers.section01.xmlconfig.MenuDTO">
<id property="code" column="menu_code"/>
<result property="name" column="menu_name"/>
<result property="price" column="menu_price"/>
<result property="categoryCode" column="category_code"/>
<result property="orderableStatus" column="orderable_status"/>
</resultMap>
정리하면:
property = Java 객체 필드명
column = DB 컬럼명
11. CRUD 계층 구조
역할을 나누어 작성되어 있다.
Application
↓
MenuController
↓
MenuService
↓
MenuDAO
↓
SqlSession
↓
menu-mapper.xml
↓
DB
각 역할은 다음과 같다.
Application
사용자 입력을 받음
MenuController
입력값을 변환하고 Service 호출
MenuService
SqlSession 생성, commit/rollback, close 처리
MenuDAO
SqlSession으로 Mapper SQL 실행
menu-mapper.xml
실제 SQL 작성
12. 조회 흐름
전체 메뉴 조회는 다음 흐름으로 실행된다.
[MenuController.java]
menuService.selectAllMenu();
[MenuService.java]
SqlSession sqlSession = getSqlSession();
try {
return menuDAO.selectAllMenu(sqlSession);
} finally {
sqlSession.close();
}
[MenuDAO.java]
return sqlSession.selectList("MenuMapper.selectAllMenu");
조회는 데이터를 변경하지 않기 때문에 commit/rollback 없이 close만 한다.
13. 등록 흐름
신규 메뉴 등록은 insert이므로 트랜잭션 처리가 필요하다.
int result = menuDAO.insertMenu(sqlSession, menuDTO);
if(result > 0) sqlSession.commit();
else sqlSession.rollback();
성공하면 commit으로 DB에 반영하고,
실패하면 rollback으로 되돌린다.
예외가 발생해도 rollback한다.
catch (RuntimeException e) {
sqlSession.rollback();
throw e;
}
이 구조가 중요한 이유는 insert, update, delete는 DB 상태를 바꾸기 때문이다.
14. #{} 파라미터 바인딩
Mapper XML에서 값을 넣을 때는 #{}를 사용한다.
VALUES (#{name}, #{price}, #{categoryCode}, 'Y')
여기서 name, price, categoryCode는 MenuDTO의 필드명과 연결된다.
menu.setName(name);
menu.setPrice(price);
menu.setCategoryCode(categoryCode);
즉 MyBatis가 DTO의 getter를 이용해 값을 꺼내 SQL 파라미터로 넣어준다.
15. Java Config 방식과 XML Config 방식
Java Config
[Application.java]
Java 코드에서 직접 설정한다.
Environment environment = new Environment(
"dev",
new JdbcTransactionFactory(),
new PooledDataSource(DRIVER, URL, USER, PASSWORD)
);
Configuration configuration = new Configuration(environment);
configuration.addMapper(Mapper.class);
XML Config
[Application.java]
XML 파일을 읽어서 설정한다.
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
둘 다 결국 목표는 같다.
Configuration 준비
↓
SqlSessionFactory 생성
↓
SqlSession 생성
↓
SQL 실행
16. 핵심 정리
- MyBatis는 영속성 프레임워크이자 SQL Mapper 프레임워크이다.
- Java 코드와 SQL을 분리하고, SQL 실행 결과를 Java 객체에 매핑해준다.
- Configuration은 MyBatis 실행에 필요한 설정 정보이다.
- SqlSessionFactory는 SqlSession을 만드는 공장이다.
- SqlSessionFactory는 애플리케이션에서 한 번 만들고 재사용하는 것이 좋다.
- SqlSession은 실제 DB 작업을 요청하는 통로이다.
- SqlSession은 작업 단위로 열고 반드시 닫아야 한다.
- openSession(false)는 auto commit을 끄는 설정이다.
- 조회는 commit이 필요 없지만 insert/update/delete는 commit 또는 rollback이 필요하다.
- XML Mapper의 namespace.id로 SQL을 호출한다.
- resultMap은 DB 컬럼명과 Java 필드명이 다를 때 매핑 정보를 제공한다.
- #{}는 DTO나 파라미터 객체의 값을 SQL에 바인딩할 때 사용한다.
- 이번 CRUD 구조는 Controller → Service → DAO → Mapper XML → DB 흐름으로 구성된다.
'TIL > [TIL]' 카테고리의 다른 글
| [TIL]MyBatis 동적 쿼리와 Spring MyBatis 기본 흐름 (0) | 2026.06.08 |
|---|---|
| [TIL]MyBatis Mapper 방식, #{}와 ${}, 동적 SQL (0) | 2026.06.05 |
| [TIL]Spring Boot 인터셉터 등록, REST API 응답 설계, Validation, Swagger (0) | 2026.06.02 |
| [TIL]Spring Boot 파일 업로드, 전역 예외 처리, 인터셉터 (0) | 2026.06.01 |
| [TIL]Spring Boot JSON 처리와 예외 흐름 기초 (0) | 2026.05.29 |