[DB]Mybatis 사용해보기

Inung_92·2023년 1월 11일
1

DB

목록 보기
3/3
post-thumbnail

Mybatis란?

개발자가 지정한 SQL저장 프로시저 및 고급 Mapping을 지원하여 개발 생산성을 높이는 Persistence Framework

⚡️Presistence는 영속성 이란 뜻으로 프로그램이 종료되어도 데이터가 유지되는 DB를 뜻함.

Java에서 DB 프로그래밍을 하기 위하여 JDBC를 제공한다. 다양한 API를 제공하지만 점차 데이터가 방대해지고 각 데이터들의 관계가 복잡해지면서 다수의 메서드를 호출하고 관련 객체를 호출 및 해제해야하는 문제점이 빈번하게 발생하게 된다. 이러한 문제점을 해결하고, 더욱 효과적으로 DB를 관리하기 위해 Mybatis가 등장했다.

사용하는 이유

기존 JDBC만을 이용한 DB 프로그래밍 방식은 프로그램 소스안에서 직접 연결(Connection)을 맺고, 쿼리문을 수행하고, 다시 반납하기를 반복하면서 비슷한 성격의 코드를 작성하는데 있어서 효과적이지 못했다. 또한, 코드가 길어지고 유지보수 측면에서 java 프로그램 자체를 수정하기 때문에 코드의 유연성이 좋지 못하다. 아래 코드를 보자.

//insert문 수행예시
	public int insert(Gallery gallery) {
		int result = 0;
		Connection conn = null;
		PreparedStatement pstmt = null; //쿼리수행 객체 생성

		conn = pool.getConnection(); //메서드 내부에서 Connection 연결

		String sql = "insert into gallery(gallery_idx, title, writer, content, filename)";
		sql += " values(seq_gallery.nextval, ?, ?, ?, ?)";
        //쿼리문 작성

		try {
			pstmt = conn.prepareStatement(sql); //쿼리문 수행
            
            //바인드변수 연결
			pstmt.setString(1, gallery.getTitle());
			pstmt.setString(2, gallery.getWriter());
			pstmt.setString(3, gallery.getContent());
			pstmt.setString(4, gallery.getFileName());

			result = pstmt.executeUpdate(); //결과 반환
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			pool.release(conn, pstmt); //사용자원 반납
		}
		return result;
	}

반면 Mybatis를 사용할 경우 상당부분의 코드와 파라미터 설정 등과 쿼리문 결과에 대한 처리를 대신해주어 코드의 중복을 방지하고 간소화된 코드를 작성하는 효과가 있다. 또한, 수정이 필요한 경우 xml 파일에 작성된 쿼리문만 수정하면 되기에 변환이 자유롭고 가독성이 좋아진다. Mybatis로 작성한 아래 코드를 보자.

	public int insert(Board board) {
    	//싱글턴 패턴을 이용해 세션 객체 호출
		SqlSession session = config.getSqlSession();
        //xml에 쿼리문을 기반으로 메서드 실행
		int result = session.insert("board.insert", board);
        //쿼리문 트랜잭션 확정
		session.commit();
        //세션 객체 반납
		config.release(session);
		
		return result;
	}

위의 두 코드를 눈으로만 봐도 코드가 간결해지고 쿼리문과 분리되어있다는 것이 보일 것이다. 이러한 이유로 프로젝트가 크면 클수록 Mybatis를 이용하는 것이 좋다.

특징

  • JDBC로 처리하는 파라미터 설정결과 매핑 기능을 대신해준다.
  • SQL문이 xml파일에 작성되어 유지되므로 가독성이 좋다.
  • 서비스 로직에서 특정 메서드가 필요할 때마다 호출하여 사용할 수 있어 재사용성이 좋다.
  • POJO(Plain Old Java Object)를 데이터베이스 레코드에 매핑이 가능하다.
    ⚡️POJO : 순수한 자바코드를 의미 / 예) DTO 등
  • 쿼리문을 Java의 메서드처럼 구성해서 유지보수성을 높일 수 있다.
  • 쿼리문의 입력 파라미터 및 수행 결과를 객체(Map, DTO 등)로 자동 Mapping 해준다.

설치 및 사용

이제 본격적으로 Mybatis를 사용하는 방법에 대해서 알아보자.

설치

가장 먼저 해야할 일은 'maven repository'에 접속하여 maven dependency로 등록해 줄 mybatis를 다운받는 것이다. 아래 경로로 들어가 다운을 받아주자. 참고로 나는 3.4.6 버전을 받았다.

maven repository 경로
https://mvnrepository.com/artifact/org.mybatis/mybatis

아래의 사진에서 처럼 다운받고 싶은 버전을 클릭하면 된다.

만약 maven repository 접속이 불가능하다면 아래 코드를 복사해서 사용하여도 무방하다.

위 그림에서 처럼 maven의 pom.xml 파일을 열어 해당 코드를 입력하고 저장을 해주면 된다. 저장이 완료되었다면 프로젝트 내 maven라이브러리에 mybatis가 포함되어있는지 확인하자. 포함되어있다면 정상적으로 설치가 된 것이다.

사용

설치가 완료되었으니 이제 이클립스에서 사용을 해보겠다.

가장 먼저 해야하는 것은 선택사항이지만 있으면 편한 플러그인을 설치하는 것이다. 아래 설명한 방법을 따라 들어가 설치를 진행하자.

이클립스 'help' 탭에서 'marketplace' 클릭하여 접속

'mybatis' 검색 후 두번째에 보이는 'mybatipse' 플러그인 설치 후 이클립스 재시작

새 xml파일 생성에서 사진과 동일한 파일을 선택 후 파일명 지정(환경설정이라는 의미에서 config.xml로 생성하였다.) 후 공식홈페이지의 xml 형식 붙여넣어준다.

공식홈페이지의 xml 양식 경로
https://mybatis.org/mybatis-3/getting-started.html

그림에서 보이는 것처럼 property 영역의 각 value들을 자신이 사용중인 JDBC 환경에 맞게 수정해주면된다. 나는 Oracle을 사용하기 때문에 Oracle에 대한 DB연결 정보를 입력하였다.

이제 DAO와 1:1로 대응하는 xml을 매핑해주어야한다. 나는 테이블명이 Board이기 때문에 BoardMapper라고 xml 파일을 생성하고 맵핑해주었다. 여기서 매핑을 해주어야 Mybatis가 해당 연결정보에서 매핑된 xml을 기반으로 쿼리문을 수행할 수 있도록 도와준다.

매핑을 완료해준 뒤 생성한 xml로 돌아와 parameterType을 지정해준다. 여기서 사용되는 parameter는 DTO이다. 위에서 설명한 POJO의 일부이다. 반드시 ""내에 패키지명클래스의 이름을 정확하게 입력하여 주어야한다.
다음으로 해당 xml에서 실행할 쿼리문을 작성한다. 예시로 insert에 대해서 쿼리문을 작성하였다. values에 들어가는 각 컬럼의 값은 parameter로 매핑된 Board의 멤버변수로 넘겨받는다. 즉, values에서 각 컬럼에 들어가는 값은 DTO의 멤버변수와 동일한 이름이어야한다.

기존의 JDBC에서 바인드변수가 차지하던 자리를 매핑된 DTO의 멤버변수가 차지하는 것이다.

이제 xml의 준비는 끝났다. Java에서 생성한 DAO에서 mybatis를 parsing해보자.

SqlSession 객체 생성준비

아래 코드는 mybatis 공식홈페이지에 있는 SqlSessionFactory를 생성하는 코드이다. SqlSession은 기존 JDBC에서 Connection 및 PreparedStatement 등의 역할을 하는 객체로 메서드 내에서 계속 새로운 연결이 필요하다면 기존과 mybatis가 다를 것이 없을 것이다. 이러한 부분을 해결하기 위해 아래 공식홈페이지의 설명도 함께 보자.

  • SqlSessionFactoryBuilder : 설정파일(xml)을 읽어와 SqlSessionFactory 객체를 생성
  • SqlSessionFactory : SqlSession을 생성하고 관리하는
  • SqlSession : Mapping파일을 통해 실제 DB에 대한 동작을 수행
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

공식홈페이지의 설명을 읽어보면 '싱글톤 패턴'으로 생성하는 것을 권장하고 있다. 그렇다면 클래스로 싱글톤 패턴을 적용하여 만들면서 Connection Pool을 사용하는 것처럼 Factory에서 SqlSession을 필요할때 꺼내서 사용할 수 있도록 클래스를 구성해볼 것이다. 주의 해야하는 점은 Sqlsession은 매 요청마다 얻어오고 반납을 반복해줘야함. 즉, 멤버변수 등으로 보유하거나, 참조를 엮지 말아야한다는 점이다.

다음 코드는 싱글톤 패턴을 적용한 SqlSessionFactory 생성 클래스이다.

//SqlSessionFactory를 싱글턴 패턴으로 관리하기 위한 클래스
public class MybatisConfig {
	//싱글톤 패턴을 위한 인스턴스 선언
	private static MybatisConfig instance;
	//인스턴스가 보유할 Factory 선언
	SqlSessionFactory sqlSessionFactory;

	private MybatisConfig() {
		// DB 연결 및 Mapper 정보(본인이 설정한 패키지 경로와 파일명 입력)
		String resource = "board/mybatis/config.xml";
		// 순수 JDBC 코드의 쿼리실행 객체 = PreparedStatement
		// Mybatis는 JDBC를 매핑해서 쿼리를 실행 = SqlSession

		try {
			// 로컬의 xml파일을 읽어드리기
			InputStream inputStream = Resources.getResourceAsStream(resource);
			
            // 생성자를 통해 인스턴스가 생성될 때 Factory 생성
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	//SqlSession을 반환해주는 메서드
	public SqlSession getSqlSession() {
		return sqlSessionFactory.openSession();
	}
	
	//SqlSession을 반납하는 메서드
	public void release(SqlSession sqlSession) {
		if(sqlSession != null) {
			sqlSession.close();
		}
	}
	//인스턴스 생성 메서드
	public MybatisConfig getInstance() {
		if (instance == null) {
			instance = new MybatisConfig();
		}
		return instance;
	}
}

SqlSession 사용

	//insert문 예시
	public int insert(Board board) {
    	//싱글턴 패턴을 이용해 세션 객체 호출
		SqlSession session = config.getSqlSession();
        //xml에 쿼리문을 기반으로 메서드 실행
		int result = session.insert("board.insert", board);
        //쿼리문 트랜잭션 확정
		session.commit();
        //세션 객체 반납
		config.release(session);
		
		return result;
	}

위에서 비교에 사용한 코드와 동일한 코드다. 메서드를 실행할 때 SqlSession을 Factory 인스턴스(config)로부터 받아오며 해당 쿼리문을 수행하고 트랜잭션을 확정지은 뒤 반납한다. 쿼리문이 수정되는 경우에는 xml파일로 이동하여 쿼리문만 수정해주면 되기 때문에 유지보수 및 코드의 분리와 재사용 측면에서 훨씬 유연해졌다고 할 수 있다.


Mybatis의 동작원리

설치 및 사용에 대하여 알아보았으니 마지막으로 동작원리에 대해서 알아보고 마무리하자.

위 그림을보면 동작원리는 두가지로 나뉜다. 먼저 어플리케이션 실행 시 수행되는 프로세스가 상단 부분이며, 그 다음은 어플리케이션이 실행되는 동안 클라이언트의 요청 시 수행되는 프로세스이다. 프로세스별 동작순서 및 원리를 간단하게 표현해보겠다.

  • 어플리케이션 실행 시 수행되는 프로세스
    • SqlSessionFactoryBuilder가 xml 설정파일(config)을 읽어와 SqlSessionFactory 객체를 생성
    • 생성된 SqlSessionFactory는 컨테이너에 저장되어 요청 시까지 대기
  • 클라이언트 요청 시 수행되는 프로세스
    • 특정 쿼리 수행 요청이 들어오면 SqlSessionFactory는 SqlSession 객체생성
    • 어플리케이션은 Mapper Interface 객체를 호출하여 보유
    • Mapper Interface 객체가 SqlSession 객체의 메서드 지시
    • SqlSession은 Mapper File의 정보를 읽어와 해당 SQL문 실행

마무리

기존 JDBC를 사용할 때보다 코드의 분리로 인한 가독성이 확실히 좋아졌다. 또한, 코드가 간소화되어 이전에 반복적인 코드들이 간소화되고 생산성이 올라간 것이 느껴진다. 아직 공부해야 할 부분은 많지만 왜 사용하는지에 대해서는 확실히 알 수 있었다.

이번 글에서는 수업에 배운 내용을 바탕으로 Mybatis의 기초적인 부분들을 작성하였다. 혹시 틀리거나 잘못된 부분이 있다면 이야기해주길 바란다.

참고

https://velog.io/@jonghne/MyBatis-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC
https://mybatis.org/mybatis-3/index.html
https://hyejin.tistory.com/261

profile
서핑하는 개발자🏄🏽

0개의 댓글