이번에는 Spring MVC 구조는 그대로 유지하면서 데이터 접근 방식을 JdbcTemplate에서 MyBatis로 변경하였다. 처음에는 Repository가 사라지고 Mapper 인터페이스만 존재하는 구조가 낯설었지만, 프로젝트를 진행하면서 MyBatis가 Mapper와 XML을 연결하여 SQL을 실행해 준다는 점을 이해하게 되었다.
또한 DTO와 Entity를 적절히 분리하고 Service 계층에서 필요한 변환을 수행하면서 이전 프로젝트보다 더욱 객체지향적인 구조를 경험할 수 있었다.
게시글 등록은 다음과 같은 순서로 진행된다.
사용자 입력
↓
BoardController
↓
BoardService
↓
BoardFormDTO.toEntity()
↓
BoardMapper.insert()
↓
BoardMapper.xml
↓
INSERT SQL
↓
Database
게시글 작성 요청이 들어오면 Controller는 DTO를 전달하고, Service는 toEntity()를 이용하여 Entity로 변환한 뒤 Mapper를 호출한다. Mapper는 연결된 XML의 INSERT SQL을 실행하여 게시글을 저장한다.
조회 과정에서는 Entity를 화면에 필요한 DTO로 변환하는 과정이 추가된다.
Database
↓
BoardMapper.findAll()
↓
List<Board>
↓
BoardService
↓
BoardViewDTO.fromEntity()
↓
List<BoardViewDTO>
↓
Controller
↓
JSP
BoardService에서는 Stream API를 사용하여 Entity 목록을 ViewDTO 목록으로 변환한다. 이 과정을 통해 화면에는 필요한 데이터만 전달할 수 있으며, Entity가 View와 직접 연결되지 않도록 설계하였다.
수정 기능은 기존 데이터를 조회한 뒤 필요한 값만 변경하는 방식으로 구현하였다.
BoardMapper.findById()
↓
Board Entity
↓
값 수정
↓
BoardMapper.update()
↓
UPDATE SQL
기존 Entity를 재사용함으로써 필요한 필드만 변경하고 다시 저장할 수 있어 코드의 중복을 줄일 수 있었다.
삭제 기능은 가장 단순한 흐름을 가진다.
Controller
↓
Service
↓
BoardMapper.delete()
↓
DELETE SQL
↓
Database
Controller는 삭제 요청만 전달하고 실제 SQL 실행은 Mapper가 담당한다.
이번 프로젝트를 통해 MyBatis가 내부적으로 어떻게 동작하는지 이해할 수 있었다.
Controller
↓
Service
↓
Mapper Interface
↓
MyBatis
↓
Mapper XML
↓
SQL 실행
↓
Database
개발자는 Mapper 인터페이스만 작성하지만, 실행 시 MyBatis가 인터페이스의 구현 객체를 생성하여 XML에 작성된 SQL을 실행한다. 이 덕분에 SQL 실행 코드나 JDBC 객체를 직접 작성하지 않아도 된다.
| Spring JDBC | MyBatis |
|---|---|
| JdbcTemplate 호출 | Mapper 메서드 호출 |
| SQL을 Java 코드에서 관리 | SQL을 XML에서 관리 |
| Repository 구현 필요 | Mapper 인터페이스만 작성 |
| RowMapper 작성 | 자동 매핑 지원 |
MyBatis를 사용하면서 SQL과 Java 코드가 명확하게 분리되어 프로젝트 구조가 더욱 깔끔해졌음을 확인할 수 있었다.
프로젝트를 진행하면서 가장 어려웠던 부분은 Mapper 인터페이스만으로 SQL이 실행되는 원리를 이해하는 것이었다.
처음에는 구현 클래스가 존재하지 않는데도 boardMapper.insert()나 boardMapper.findAll()이 정상적으로 동작하는 이유를 이해하지 못했다. 또한 SQL을 Java 코드가 아닌 XML에서 관리하는 이유도 쉽게 와닿지 않았다.
공식 문서와 프로젝트 코드를 함께 분석하면서 MyBatis는 실행 시 Mapper 인터페이스의 구현 객체를 자동으로 생성하고, 인터페이스의 메서드와 XML의 SQL을 연결하여 실행한다는 점을 이해하게 되었다.
또한 SQL을 XML에 분리하면 SQL 수정이 필요한 경우 Java 코드를 변경하지 않아도 되므로 유지보수가 훨씬 쉬워진다는 장점도 알게 되었다.
| 배운 내용 | 느낀 점 |
|---|---|
| MyBatis | SQL과 Java 코드를 분리하여 관리할 수 있다. |
| Mapper | 구현 클래스를 직접 작성하지 않아도 데이터 접근 계층을 구성할 수 있다. |
| DTO 변환 | Service에서 Entity와 DTO를 변환하여 계층 간 역할을 명확히 분리할 수 있다. |
| Stream API | Entity를 DTO로 간결하게 변환할 수 있다. |
| MVC | 데이터 접근 방식이 바뀌어도 전체 MVC 구조는 그대로 유지된다. |