본문 바로가기
프로그래밍이야기/JPA

[JPA] JPA와 Mybatis 비교

by 사랑꾼이야 2022. 1. 23.
반응형

개발자로서 일을 시작하면서 Mybatis의 사용은 거의 80 ~ 90%였습니다. 왜냐하면 어느 프로젝트에서든지 쉽게 접할 수 있었습니다. 그러다보니 어느 프로젝트를 진행하든 Mybatis라는 프레임워크를 만났기 때문에 어렵지 않게 진행할 수 있어서 사실 반가웠습니다. 그래서 JPA는 미지의 영역이었습니다. 그리고 시간이 흘러서 프로젝트를 새롭게 진행하면서 JPA를 접하게 되었습니다. 그때까지만 해도 JPA를 이렇게 알고 있었습니다.

Database의 제약없이 변경되도 사용할 수 있다는 것

그러다 이러한 생각이 들었습니다. 단순히 위 기능때문에 그 많은 서비스 기업에서 JPA를 사용하는 것일까? 그리고 나는 개발자로서 Java의 기능을 맞게 사용하고 있는것인가? 라는 생각이 들었고 좋은 기회로 우아한 테크캠프를 듣게 되었고 제대로된 개발자의 길을 걷기 위해서 공부한 내용을 정리하였습니다.

아래 내용은 자바 ORM 표준 JPA 프로그래밍의 책을 읽고 정리하였습니다.

Mybatis

마이바티스의 개념은 공식 홈페이지의 잘 설명되어 있습니다.

mybatis 공식 홈페이지 참고

마이바티스는 개발자가 지정한 SQL, 저장프로시저 그리고 몇가지 고급 매핑을 지원하는 퍼시스턴스 프레임워크이다. 마이바티스는 JDBC로 처리하는 상당부분의 코드와 파라미터 설정및 결과 매핑을 대신해준다. 마이바티스는 데이터베이스 레코드에 원시타입과 Map 인터페이스 그리고 자바 POJO 를 설정해서 매핑하기 위해 XML과 애노테이션을 사용할 수 있다.

Mybatis를 보통 SQL 매퍼라 합니다. 개발자가 작성한 SQL과 매핑할 객체만 지정해준다면 JDBC API 사용과 응답 결과를 객체로 매핑하는 일은 SQL 매퍼가 담당하게 됩니다. 이 부분만 놓고 본다면 사실 매우 편리하다고 생각합니다. 하지만 결국엔 개발자가 SQL 쿼리를 직접 생성하여야 합니다.

개발자가 SQL 쿼리를 직접 작성하게 되면 새로운 개발을 진행할 때, 가장 기본적인 CRUD 기능을 반복적으로 만들어야 합니다. 또한 필드가 추가되는 요구사항이 생겼을 시, 단순한 필드 하나 추가지만 DAO의 CRUD 메소드와 쿼리 대부분을 변경해야 합니다. 즉, SQL에 의존적인 개발을 할 수 밖에 없습니다.

좀 더 자세하게 알아보도록 하겠습니다.

반복, 반복 그리고 반복

책을 관리하는 애플리케이션을 만든다고 가정하겠습니다. 기본적인 기능인 책을 등록하고, 조회하고, 책의 정보를 수정하고 삭제하는 기능이 필요합니다. 먼저 책을 관리하는 테이블을 설계를 합니다. 그리고 다음 기능을 개발합니다.

조회 기능

  1. 먼저 책의 대한 객체를 만들어야 합니다.
  2. 책의 대한 DAO(데이터 접근 객체)를 만들어야 합니다.
  3. DAO의 find 메소드를 만들어야 합니다.
  4. find 메소드의 맞는 SQL를 작성해야 합니다.
  5. JDBC API를 사용해서 SQL을 실행합니다.
  6. 실행하여 나온 결과를 책의 대한 객체와 매핑시켜야 됩니다.

등록 기능

  1. DAO의 save 메소드를 만들어야 합니다.
  2. save 메소드의 맞는 SQL를 작성해야 합니다.
  3. JDBC API를 사용해서 SQL을 실행합니다.
  4. 실행하여 나온 결과를 책의 대한 객체와 매핑시켜야 합니다.

수정과 삭제 기능도 비슷한 과정을 겪으면서 만들게 됩니다.

위와 같이 진행하면서 불편함을 느꼈던 부분들은 MyBatis와 jdbcTemplate을 사용하여 웹 애플리케이션을 개발할 때 생성한 DAO와 작성한 SQL의 필드가 맞는지 확인하는 작업을 하였습니다. 이러한 부분은 추가된 요구사항으로 인하여 필드가 추가되었을때도 동일한 문제를 겪을 수 있습니다.

예를 들어, 책의 종류를 나타내는 정보를 추가해달라는 요구사항이 생겼습니다. 테이블의 Type 필드를 추가하였습니다. 그리고 기존에 생성한 DAO에도 필드를 추가하고, SQL에도 추가하여서 Type 이라는 필드가 값이 입력되는지 확인을 하였습니다. 생성 테스트는 완료하여서 기능을 완료하였다고 보고하였습니다. 그 후 화면에서(화면이 있다고 가정하고) Type 필드가 조회되지 않는다고 연락이 왔습니다. 확인을 해보니 책 정보를 조회하는 기능의 SQL의 책 Type 필드를 갖고 오는 쿼리는 수정하지 않았습니다. 실제 이런 일들을 많이 겪었습니다.

패러다임의 불일치

애플리케이션은 발전하면서 그 내부의 복잡성도 점점 커지게 되는데, 지속 가능한 애플리케이션을 개발하는 일은 끊임없이 증가하는 복잡성과의 싸움입니다. 비즈니스 요구사항을 정의한 도메인 모델로 객체로 모델링하면 객체지향 언어가 가진 장점들을 활용할 수 있습니다. 문제는 이렇게 정의한 도메인 모델을 저장할 때 발생하게 됩니다. 애플리케이션은 자바라는 객체지향 언어로 개발하고 데이터는 관계형 데이터베이스에 저장해야 한다면, 패러다임의 불일치 문제를 개발자가 중간에서 해결해야 합니다. 문제는 이런 객체와 관계형 데이터베이스 사이의 패러다임 불일치 문제를 해결하는 데 너무 많은 시간과 코드를 소비하는 데 있습니다.

상속

자바에서는 상속이라는 개념이 존재하지만 데이터베이스에서는 상속이라는 기능은 없습니다.

다음 구현된 객체 모델 코드를 보시면, Item이라는 부모 클래스가 존재하고 각 Album, Movie, Book 객체는 Item을 상속하고 있습니다.

abstract class Item {
    Long id;
    String name;
    int price;
  }

  class Album extends Item {
    String artist;
  }

  class Movie extends Item {
    String director;
    String actor;
  }

  class Book extends Item {
    String author;
    String isbn;
  }

Album 객체를 저장한다고 하면 SQL 2개가 필요합니다.

JDBC API를 사용해서 작성하려면 부모 객체에서 부모 데이터만, 자식 객체에서 자식 데이터만 꺼내서 각각의 INSERT SQL을 작성해야 합니다. 조회하는 것도 쉽지는 않은데, Album을 조회하려면 ITEM과 ALBUM 테이블을 조인해서 조회한 다음 Album 객체를 생성해야 합니다.

JPA와 상속

JPA는 상속과 관련된 패러다임의 불일치 문제를 개발자 대신 해결해줄 수 있습니다. 개발자는 마치 자바 컬렉션에 객체를 저장하듯이 JPA에게 객체를 저장하면 됩니다.

JPA를 사용해서 Item을 상속한 Album 객체를 저장해보면,

jpa.persist(album);

JP는 다음 SQL을 실행해서 객체를 ITEM, ALBUM 두 테이블에 나누어 저장합니다.

INSERT INTO IEM ...
INSERT INTO ALBUM ...

연관관계

자바에서 객체는 참조를 사용해서 다른 객체와 연관관계를 가지고 참조에 접근해서 연관된 객체를 조회합니다.

데이터베이스에서 테이블은 외래 키를 사용해서 다른 테이블과 연관관계를 가지고 조인을 사용해서 연관된 테이블을 조회합니다.

객체를 테이블에 맞추어 모델링

  • 객체를 테이블에 저장하거나 조회할 때는 편리합니다.
  • 하지만 객체는 연관된 객체의 참조를 보관해야 연관된 객체를 찾을 수 있습니다.
  • 좋은 객체 모델링은 기대하기 어렵고 결국 객체지향의 특징을 잃어버리게 됩니다.

객체지향 모델링

  • 객체지향 모델링을 사용하면 객체를 테이블에 저장하거나 조회하기는 쉽기 않습니다.
  • 객체는 외래 키가 필요 없고 단지 참조만 있으면 됩니다.
  • 테이블은 참조가 필요 없고 외래 키만 있으면 됩니다.
  • 중간에 개발자가 변환을 해줘야 합니다.

JPA와 연관관계

JPA는 연관관계와 관련된 패러다임의 불일치 문제를 해결해줍니다.

개발자는 객체 간의 관계를 설정하고 저장하면 됩니다. (상속 관계)

객체 그래프 탐색

SQL을 직접 다루면 처음 실행하는 SQL에 따라 객체 그래프를 어디까지 탐색할 수 있는지 정해집니다.

무엇보다, 객체 그래프를 탐색할 수 있는지 없는지는 SQL을 직접 열어서 확인을 해봐야 합니다. 이것은 SQL에 의존적인 개발을 하게 됩니다. 객체 그래프를 신뢰할 수 없게 됩니다.

JPA와 객체 그래프 탐색

JPA를 사용하면 객체 그래프를 탐색할 수 있습니다. 이 기능은 실제 객체를 사용하는 시점까지 데이터베이스 조회를 미룬다고 해서 지연 로딩이라고 합니다.

비교

데이터베이스는 기본 키의 값으로 각 로우를 구분합니다.

객체는 동일성동등성 비교라는 두 가지 방법이 있습니다.

  • 동일성의 비교는 == 입니다. 객체 인스턴의 주소 값을 비교합니다.
    • member1과 member2는 같은 데이터베이스 로우에서 조회하였지만, 객체 측면에서 볼 때 둘은 다른 인스턴스기 때문에 member1 == member2false 가 됩니다.
    • Member member1 = list.get(0); Member member2 = list.get(0); member1 == member2
    • 객체를 컬렉션에 보관하였다면 동일성 비교에 성공하게 됩니다.
  • String memberId = "100"; Member member1 = membetDAO.getMember(memberId); Member member2 = membetDAO.getMember(memberId); member1 == member2
  • 동등성의 비교는 equals 메소드를 사용해서 객체 내부의 값을 비교합니다.

JPA와 비교

JPA는 같은 트랜잭션일 때 같은 객체가 조회되는 것을 보장합니다. 그러므로 다음 코드에서 member1과 member2는 동일성 비교에 성공합니다.

String memberId = "100";
Member member1 = jpa.find(Member.class, memberId);
Member member2 = jpa.find(Member.class, memberId);

member1 == member2

정리

정리하면 객체 모델과 관계형 데이터베이스 모델은 지향하는 패러다임이 다릅니다. 문제는 이 패러다임의 차이를 극복하기 위해 개발자가 너무 많은 시간과 코드를 소비해야 합나다. 더 어려운 문제는 객체지향 애플리케이션답게 정교한 객체 모델링을 할수록 패러다임의 불일치 문제가 더 커진다는 점입니다. 그리고 이 틈을 메우기 위해 개발자가 소모해야 하는 비용도 점점 커지게 됩니다.

JPA의 개념 및 특징에 대해서 자세하게 알아보도록 하겠습니다.

JPA

개념

자바 진영의 ORM 기술 표준이며, 애플리케이션과 JDBC 사이에 동작합니다.

1.6_JPA.png

특징

  • 생산성
    • 지루하고 반복적인 코드와 CRUD용 SQL을 개발자가 직접 작성하지 않아도 됩니다.
    • DDL 문을 자동으로 생성해주는 기능도 있습니다.
  • 유지보수
    • 필드를 추가하거나 삭제해도 수정해야 할 코드가 줄어듭니다.
    • 객체지향 언어가 가진 장점을 활용해서 유연하고 유지보수하기 좋은 도메인 모델을 편리하게 설계할 수 있습니다.
  • 패러다임의 불일치 해결
    • JPA는 상속, 연관관계, 객체 그래프 탐색, 비교하기와 같은 패러다임의 불일치 문제를 해결해줍니다.
  • 성능
    • 애플리케이션과 데이터베이스 사이에 계층이 하나 더 있으면 최적화 관점에서 시도해 볼 수 있는 것들이 많습니다.
    • 하이버네이트는 SQL 힌트를 넣을 수 있는 기능도 제공합니다.
  • 데이터 접근 추상화와 벤더 독립성
    • JPA를 사용하면 로컬 개발 환경은 H2 데이터베이스, 개발이나 상용 환경은 오라클이나 MySql 데이터베이스를 사용할 수 있습니다.
  • 표준
    • JPA는 자바 진영의 ORM 기술 표준입니다. 표준을 사용하면 다른 구현 기술로 손쉽게 변경할 수 있습니다.
반응형

댓글