처음 만드는 MyBatis - JDBC와 Config.java

홍지범·2023년 4월 10일
0

일반적으로 스프링 기반 애플리케이션 개발을 한다면 애플리케이션과 DB를 연결하는데는 Mybatis나 JPA 외에는 크게 고민을 해보지 않을 겁니다.(주니어 기준)
또 블로그, 책 등에 설정방법에 관한 레퍼런스가 많아 가이드 대로 잘 동작한다면 그 이상 고민하지 않아본 경험이 많을 겁니다.

글쓴이가 그랬거든요...😥

그래서 준비했습니다.

바로 Java 언어의 데이터베이스 연결 기술과 ORM의 추상적인 동작 원리를 이해하고 설정 방법까지!

시작해볼까요?

Java의 데이터베이스 연결 기술

우리가 애플리케이션을 만들면 중요한 데이터는 데이터베이스에 저장합니다.
애플리케이션이 DB와 통신할 때에는 보통 세가지 과정을 거치죠.

  1. 커넥션 연결(App -> DB)
  2. 질의문(SQL) 전달(App -> DB)
  3. 결과 응답(DB <- App)

이 과정을 실제 코드로 만든다면 아래와 같습니다.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public void exampleSQL() throw SQLException {
	String sql = "select * from example where id = 1"
    
    Connection con = null;
    PrepareStatement pstmt = null;
    ResultSet rs = null;
    
    try {
    	con = DriverManager.getConnection(
        		"exampleURL:3306",
                "sa",
                "sa");
        pstmt = con.prepareStatement(sql);
        rs = pstmt.executeQuery();
        if (rs.next()){
        	return rs.getString("result");  			
            } else {
            	throw new NoSuchElementException("not found");
            }
        } catch (SQLException e) {
        	throw e;
        } finally {
        	close(con, pstmt, null);
        }
}

private void close(Connection con, Statement stmt, ResultSet rs) {
	//커넥션 닫는 로직..(rs -> stmt -> con 순으로 닫음)
}

import 구문을 볼까요? java.sql로 되어 있습니다.

public interface Connection  extends Wrapper, AutoCloseable {...}

Connection이 어떻게 되어있나 보기위해 들어가보니 인터페이스로 되어있네요.
Java에서는 다형성을 이용해 애플리케이션과 DB 연결에 필요한 내용을 인터페이스로 구현해 놓았습니다.
그리고 각 DB 벤더(MySQL, Oracle, H2 ...)들은 인터페이스의 사양에 맞게 구현체를 Driver(라이브러리)로 만들어 개발자들이 편하게 사용할 수 있던것 이었습니다.

아래 이미지에서는 H2 라이브러리를 확인할 수 있습니다.

여기까지 봤다면 이런 생각이 들겁니다.

🥶 그럼 매번 이렇게 연결 설정을 해줘야하나요? 이때까지 한 번도 이런걸 작성한 적은 없는것 같은데...?

그렇다면 SQLMapper나 ORM 기술을 잘 쓰고 있었던 것 입니다.

지금부터는 대표적인 SQLMapper 기술인 Mybatis에 대해 알아보겠습니다.

Mybatis?

Mybatis는 대표적인 SQLMapper 입니다.
그 전에 위에서 언급한 SQLMapper는 대략적으로 알겠는데 ORM이 뭐지? 하시는 분들을 위해 간단하게 정리해보겠습니다.

SQLMapper : JDBC를 편리하게 사용하기 위한 기술로 위에서 봤던 애플리케이션과 DB 연결을 Mapper가 대신해주기 때문에 반복적인 연결 작업이 필요 없습니다.
개발자는 SQL문에 대해서만 고려하면 됩니다.
대표적인 기술 : JDBCTemplate, Mybatis

ORM : SQL 중심 개발의 문제인 반복적인 작성과 SQL문과 객체지향 프로그래밍의 괴리를 해결하기 위해 등장한것이 ORM 프레임워크 입니다.
개발자는 객체지향 방식을 유지할 수 있고 애플리케이션과 DB사이에 ORM 프레임 워크가 객체와 데이터베이스를 매핑해주는 기술 입니다.
대표적인 기술 : Hibernate, JPA ..

둘 중 뭐가 더 좋을까? 에 대한 고민이 많을 것 입니다.
모두 장단점이 있지만 가장 중요한 것은 두 기술 모두 내부적으로는 JDBC 기술을 사용한다는 것 입니다.
ORM이라고, SQLMapper라고 새로운 방식을 사용해 연결하는 것이 아니라 내부적으로는 여전히 JDBC를 사용해 커넥션을 맺고 SQL문을 보내 결과를 받는 방식을 사용합니다.

참고 : 여기까지는 김영한님 강의 내용과 유사한 흐름 입니다.
DB 연결에 대해 더 자세하게 알고싶다면 김영한 님의 스프링 DB 편 을 참고해 주세요.

지금부터는 대표적인 SQLMapper인 Mybatis가 어떻게 동작하는지 알아보겠습니다.

  1. Mybatis Config : DB 설정에 필요한 구성 요소들 입니다.
    1-1. @MapperScan : 매핑할 인터페이스들의 경로를 지정합니다.
    1-2. Mapping Fiile : 실제 SQL문이 작성된 경로를 지정합니다. 위의 인터페이스와 1:1 매핑되기 때문에 이름 작성에 유의해야 합니다.
    1-3. @ConfigurationProperties : .properties 나 .yml 파일에 있는 설정 값을 자바 클래스에 바인딩 해 사용할 수 있게 해줍니다.

위와 같이 작성한 파일을 실제로 볼까요?

//DB Config example
@Configuration
@MapperScan(basePackages = "flab.just10minutes.member.repository")
public class DatabaseConfig {
	...
    @Bean
    @ConfigurationProperties(prefix="spring.datasource.hikari")
    public HikariConfig hikariConfig() {
        return new HikariConfig();
    }
    @Bean
    public DataSource dataSource() {
        return new HikariDataSource(hikariConfig());
    }
}

위의 코드에서는 @MapperScan으로 DAO 경로와 @ConfigurationProperties으로 application.properties에 있는 DB 커넥션 정보를 입력 받았네요.

  1. mybatis-spring 라이브러리의 SqlSessionFactoryBean은 위에서 생성한 dataSource와 1-2 인 Mapping File(.xml) 에 대한 정보를 입력 받아 SqlSessionFactoryBuilder에 의해 Mybatis의 SqlSessionFactory를 생성합니다.
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        Resource[] arrResource = new PathMatchingResourcePatternResolver().getResources("classpath:mappers/**/*.xml");;
        sqlSessionFactoryBean.setMapperLocations(arrResource);
        sqlSessionFactoryBean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
        return (SqlSessionFactory) sqlSessionFactoryBean.getObject();
    }

위의 코드에서는 "classpath:~"를 통해 매핑할 SQL문에 대한 정보를 입력 받았습니다.
이렇게 SQLMapper를 생성할 정보를 입력받은 sqlSessionFactoryBean 인스턴스는 내부 필드에 입력받은 정보를 가지고 있습니다.

public class SqlSessionFactoryBean ... {
	...
    private Resource[] mapperLocations;
    private DataSource dataSource;
    ...
    private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    ...
    protected SqlSessionFactory buildSqlSessionFactory () {...}
}

코드가 너무 길어 많이 생략했습니다만 인스턴스 필드에 정보를 입력받은 후 buildSqlSessionFactory() 메소드를 통해 SqlSessionFactory 인스턴스를 생성합니다.

😃 후~~ 기네요 이제 다 왔으니 조금만 더 힘내볼까요.

  1. Mybaits-spring 라이브러리의 SqlSessionTemplate는 위에서 생성한 SqlSessionFactory를 입력받아 Mybatis의 SqlSession 인터페이스를 구현한 SqlSessionTemplate을 생성합니다.
    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

이제 설정은 모두 끝냈습니다.🫠
네. 끝이에요.

😱 이래서 끝이라구요?

설정에 대한 내용만 주구장창 설명했지만 이제 어쩌라는건지 궁금하신 분들도 계실겁니다.

다음편에 계속...
<예고>

profile
왜? 다음 어떻게?

0개의 댓글

관련 채용 정보