JSP/Servlet_11) MyBatis프레임워크를 활용한 JDBC DAO 패턴 비교 분석
2025. 10. 17. 17:46

MyBatis 프레임워크 개요

MyBatis란?

MyBatis는 SQL 매핑 프레임워크로, Java 객체와 SQL 문 사이의 자동 매핑을 지원한다. 기존 JDBC의 복잡한 코드를 간소화하고, SQL과 Java 코드의 분리를 통해 유지보수성을 향상시킨다.

핵심 구성 요소

  • SqlSession: MyBatis의 핵심 인터페이스
  • Mapper XML: SQL 문을 정의하는 파일
  • Configuration: MyBatis 설정 파일

DAO 패턴 비교 분석

JDBC 방식의 DAO (기존 방식)

package com.kh.jsp.model.dao;

import static com.kh.jsp.common.JDBCTemplate.close;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import com.kh.jsp.model.vo.Member;

public class MemberDao {
    private Properties prop = new Properties();

    public MemberDao() {
        super();
        String path = JDBCTemplate.class.getResource("/db/sql/member-mapper.xml").getPath();
        try {
            prop.loadFromXML(new FileInputStream(path));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Member loginMember(String userId, String userPwd, Connection conn) {
        Member m = null;
        PreparedStatement pstmt = null;
        ResultSet rset = null;

        String sql = prop.getProperty("loginMember");

        try {
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, userId);
            pstmt.setString(2, userPwd);

            rset = pstmt.executeQuery();

            if(rset.next()) {
                m = new Member(
                    rset.getInt("MEMBER_NO"),
                    rset.getString("MEMBER_ID"),
                    rset.getString("MEMBER_PWD"),
                    rset.getString("MEMBER_NAME"),
                    rset.getString("PHONE"),
                    rset.getString("EMAIL"),
                    rset.getString("ADDRESS"),
                    rset.getString("INTEREST"),
                    rset.getDate("ENROLL_DATE"),
                    rset.getDate("MODIFY_DATE"),
                    rset.getString("STATUS")
                );
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(rset);
            close(pstmt);
        }

        return m;
    }
}

JDBC 방식의 특징

  • Connection 객체를 직접 관리
  • PreparedStatement, ResultSet 수동 처리
  • 예외 처리 코드가 복잡
  • SQL과 Java 코드가 분리되지 않음

MyBatis 방식의 DAO (현재 프로젝트)

package com.kh.mybatis.model.dao;

import org.apache.ibatis.session.SqlSession;
import com.kh.mybatis.model.vo.Member;
import java.util.HashMap;

public class MemberDao {
    public Member loginMember(SqlSession sqlSession, String userId, String userPwd) {
        HashMap<String, String> map = new HashMap<>();
        map.put("memberId", userId);
        map.put("memberPwd", userPwd);
        Member loginMember = sqlSession.selectOne("MemberMapper.loginMember", map);
        return loginMember;
    }

    public int updateMemberPwd(SqlSession sqlSession, String memberId, String updatePwd) {
        HashMap<String, String> map = new HashMap<>();
        map.put("memberId", memberId);
        map.put("updatePwd", updatePwd);

        return sqlSession.update("MemberMapper.updateMemberPwd", map);
    }
}

MyBatis 방식의 특징

  • SqlSession을 통한 간단한 데이터베이스 접근
  • 자동 매핑으로 코드 간소화
  • SQL과 Java 코드의 완전한 분리
  • 예외 처리 자동화

Mapper XML 파일 분석

MyBatis Mapper XML 구조

<!-- SELECT 쿼리 -->
<select id="loginMember" parameterType="hashmap" resultMap="memberResultMap">
    SELECT MEMBER_NO,
           MEMBER_ID,
           MEMBER_PWD,
           MEMBER_NAME,
           PHONE,
           EMAIL,
           ADDRESS,
           INTEREST,
           ENROLL_DATE,
           MODIFY_DATE,
           STATUS
    FROM MEMBER
   WHERE MEMBER_ID = #{memberId}
     AND MEMBER_PWD = #{memberPwd}
     AND STATUS = 'Y'
</select>

<!-- UPDATE 쿼리 -->
<update id="updateMemberPwd" parameterType="hashmap">
    UPDATE MEMBER
       SET MEMBER_PWD = #{updatePwd}
     WHERE MEMBER_ID = #{memberId}
</update>

<!-- INSERT 쿼리 -->
<insert id="insertMember" parameterType="Member">
    INSERT INTO MEMBER
    (
        MEMBER_NO,
        MEMBER_ID,
        MEMBER_PWD,
        MEMBER_NAME,
        PHONE,
        EMAIL,
        ADDRESS,
        INTEREST
    )
    VALUES(
        SEQ_MNO.NEXTVAL,
        #{memberId},
        #{memberPwd},
        #{memberName},
        #{phone},
        #{email},
        #{address},
        #{interest}
    )
</insert>

Service 계층 비교

JDBC 방식의 Service

public class MemberService {
    public Member loginMember(String userId, String userPwd) {
        Connection conn = JDBCTemplate.getConnection();
        Member m = new MemberDao().loginMember(userId, userPwd, conn);

        if(m != null) {
            JDBCTemplate.commit(conn);
        } else {
            JDBCTemplate.rollback(conn);
        }

        JDBCTemplate.close(conn);
        return m;
    }
}

MyBatis 방식의 Service

public class MemberService {
    private MemberDao memberDao = new MemberDao();

    public Member loginMember(String userId, String userPwd) {
        SqlSession sqlSession = Template.getSqlSession();
        Member m = memberDao.loginMember(sqlSession, userId, userPwd);
        sqlSession.close();
        return m;
    }

    public int updateMemberPwd(String memberId, String updatePwd) {
        SqlSession sqlSession = Template.getSqlSession();
        int result = memberDao.updateMemberPwd(sqlSession, memberId, updatePwd);

        if(result > 0) {
            sqlSession.commit();
        } else {
            sqlSession.rollback();
        }
        sqlSession.close();
        return result;
    }
}

핵심 차이점 분석

코드 복잡도 비교

구분 JDBC 방식 MyBatis 방식
코드 라인 수 50+ 라인 10-15 라인
예외 처리 수동 처리 자동 처리
Connection 관리 수동 관리 자동 관리
SQL 분리 Properties 파일 XML 파일

유지보수성 비교

JDBC 방식의 문제점

  • SQL 변경 시 Java 코드 수정 필요
  • 예외 처리 코드 중복
  • Connection 관리 복잡

MyBatis 방식의 장점

  • SQL과 Java 코드 완전 분리
  • 자동 매핑으로 개발 생산성 향상
  • 설정 기반으로 유연한 구조

MyBatis 설정 파일

mybatis-config.xml

<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
            <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"/>
            <property name="username" value="C##jsp"/>
            <property name="password" value="jsp"/>
        </dataSource>
    </environment>
</environments>

<mappers>
    <mapper resource="/mappers/member-mapper.xml"/>
</mappers>

Template 클래스 분석

MyBatis SqlSession 관리

package com.kh.mybatis.common;

import java.io.InputStream;
import java.io.IOException;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class Template {
    public static SqlSession getSqlSession() {
        String resource = "/mybatis-config.xml";
        SqlSession session = null;

        try {
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            session = sqlSessionFactory.openSession(false); // false : 수동 커밋
        } catch (IOException e) {
            e.printStackTrace();
        }

        return session;
    }
}

Template 클래스의 역할

  • SqlSessionFactory 생성
  • SqlSession 인스턴스 제공
  • 설정 파일 로드 및 관리

페이징 처리 비교

MyBatis의 RowBounds 활용

public ArrayList<Board> selectAllBoard(SqlSession sqlSession, PageInfo pi) {
    // MyBatis에서 제공하는 페이징 처리
    int offset = (pi.getCurrentPage() - 1) * pi.getBoardLimit();
    RowBounds rowBounds = new RowBounds(offset, pi.getBoardLimit());

    ArrayList<Board> list = (ArrayList)sqlSession.selectList("BoardMapper.selectAllBoard", null, rowBounds);
    return list;
}

MyBatis 페이징의 장점

  • RowBounds를 통한 간단한 페이징
  • SQL 수정 없이 페이징 처리
  • 메모리 효율적인 데이터 처리

정리 및 요약

MyBatis의 핵심 장점

  1. 코드 간소화: JDBC의 복잡한 코드를 간단하게 처리
  2. SQL 분리: XML 파일을 통한 SQL과 Java 코드 분리
  3. 자동 매핑: ResultSet을 객체로 자동 변환
  4. 유지보수성: 설정 기반의 유연한 구조