응애개발자
article thumbnail
728x90

들어가기 앞서, MyBatis와 JPA를 사용하여 프로젝트를 만든 경험이 있었다. 확실히 JPA를 사용하면 코드 작성도 편해지고 가독성도 좋았다. 그렇다면 조금 더 자세하게 JPA가 무엇인지, Hibernate가 무엇인지, Spring Data JPA가 무엇인지, ORM이 무엇인지, JPA와 MyBatis의 차이는 무엇인지 자세하게 알아보자.

📌JPA란?

JPA(Java Persistence API)는 자바 진영의 ORM(Object Relational Mapping:객체 관계 매핑)기술 표준으로 사용되는 인터페이스 모음을 말한다. 

 

여기서 중요하게 생각할 점은 JPA는 특정 기능을 하는 라이브러리가 아닌, ORM을 사용하기 위한 인터페이스의 모음이라는 것이다. 그렇다는 것은 JPA는 단순히 명세이기 때문에 구현이 없는것이다. JPA를 정의한 javax.persistence 패키지의 대부분은 interface, enum, Exception, 그리고 각종 어노테이션으로 이루어져있다.

 

그 예시로 JPA의 핵심이 되는 EntityManager는 아래와 같이 interface로 정의되어 있다.

package javax.persistence;

import ...

public interface EntityManager {

    public void persist(Object entity);

    public <T> T merge(T entity);

    public void remove(Object entity);

    public <T> T find(Class<T> entityClass, Object primaryKey);

    // More interface methods...
}

그래서 이런 인터페이스를 실제로 구현한 구현체가 필요하고 그것이 Hibernate다.

 

📌Hibernate란?

Hibernate는 JPA라는 명세의 구현체다. 즉 위에서 EntityManager와 같은 인터페이스를 직접 구현한 라이브러리이다. JPA와 Hibernate는 마치 자바에서 interface와 해당 interface를 구현한 class와 같은 관계이다.

위 사진은 JPA와 Hibernate의 상속 및 구현 관계를 나타낸 것이고, JPA의 핵심인 EntityManagerFactory, EntityManager, EntityTransaction을 Hibernate에서 각각 SessionFactory, Session, Transaction으로 상속받고 impl로 구현하고 있음을 확인할 수 있다.

package org.hibernate;

import ...

public interface Session extends SharedSessionContract, EntityManager {

	void flush();

	@Override
	void setFlushMode(FlushModeType flushMode);
    
    //More interface methods...
}

즉 다시 말해 JPA 기술을 사용하기 위해서 반드시 Hibernate를 사용할 필요는 없다. Hibernate가 마음에 안든다면 DataNucleus, EclipseLink등 다른 JPA 구현체를 사용하거나, 본인이 직접 JPA를 구현해서 사용할 수 있다. 하지만 그렇게 사용하지 않는 이유는 단지 Hibernate가 굉장히 성숙한 라이브러리이기 때문에 사용하는 것이다.

 

📌Spring Data JPA란?

그렇다면 우리는 Spring으로 개발하면서 단 한번도 EntityManager를 직접 다뤄본 적이 없다.  (ex. em.merge(), em.find()같은 메서드) 아마 DB와 접근하기 위해서 Repository를 정의하여 사용했을 것이다. 이 Repository가 바로 Spring Data JPA의 핵심이다.

 

Spring Data JPA는 Spring에서 제공하는 모듈 중 하나로, 개발자가 JPA를 더 쉽고 편하게 사용할 수 있도록 도와준다. 만약 Spring Data JPA를 사용하지 않는다면 우리가 직접 JPA의 동작 방식으로 데이터를 처리해야 할 것이다. 하지만 우리는 Spring Data JPA를 통해 Repository라는 인터페이스를 제공받음으로써 알아서 관리해준다.

package org.springframework.data.jpa.repository.support;

import ...

public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {

    private final EntityManager entityManager;

 
    @Override
	@Transactional
	@SuppressWarnings("unchecked")
	public void delete(T entity) {

		Assert.notNull(entity, "Entity must not be null");

		if (entityInformation.isNew(entity)) {
			return;
		}

		Class<?> type = ProxyUtils.getUserClass(entity);

		T existing = (T) entityManager.find(type, entityInformation.getId(entity));

		// if the entity to be deleted doesn't exist, delete is a NOOP
		if (existing == null) {
			return;
		}

		entityManager.remove(entityManager.contains(entity) ? entity : entityManager.merge(entity));
	}
    // Other methods...
}

 

📚JPA 정리

즉 JPA는 ORM(Object Relational Mapping:객체 관계 매핑)기술 표준으로 사용되는 인터페이스 모음 Hibernate는 이 JPA 인터페이스를 구체화한 구현체, Spring Data JPA는 JPA를 쓰기 편하게 만들어놓은 모듈이다.

 

그렇다면 이제 ORM이 무엇인지 알아보자.


 

📌ORM(Object Relational Mapping)이란?

ORM이란 객체와 DB테이블을 Mapping 시켜 RDB 테이블을 객체지향적으로 사용하게 해주는 기술을 말한다. RDB 테이블은 객체지향적 특성(상속, 다형성) 등이 없어서 Java와 같은 객체지향적 언어로 접근하는 것이 어렵다. 이때 ORM 기술인 JPA를 사용한다면 보다 객체지향적으로 RDB를 사용할 수 있다. 

 

JPA등장 이전에는 MyBatis라는 SQL Mapper 기술을 이용하였는데 MyBatis는 Java 클래스 코드와 직접 작성한 SQL 코드를 Mapping 시켜주어야만 했다. 하지만 JPA와 같은 ORM 기술은 객체가 DB에 연결되기 때문에, SQL을 직접 작성하지 않고 표준 인터페이스 기반으로 처리한다는 점에서 차이가 있다.

 

📚SQL Mapper, ORM정리

SQL Mapper

Object와 SQL의 필드를 매핑하여 데이터를 객체화 하는 기술

  • 객체와 테이블 간의 관계를 매핑하는 것이 아님
  • SQL문을 직접 작성하는 방법
  • DBMS에 종속적인 문제
  • EX) JdbcTemplate, MyBatis

ORM

Object와 DB테이블을 매핑하여 데이터를 객체화하는 기술

  • 개발자가 반복적인 SQL을 직접 작성하지 않음
  • DBMS에 종속적이지 않음
  • 복잡한 쿼리의 경우 JPQL을 사용하거나 SQL Mapper을 혼용하여 사용 가능

 

📚MyBatis, JPA정리

JPA : ORM(Object Relational Mapping) 기술

  • 자바 ORM의 기술 표준
  • 대표적인 오픈소스로 Hibernate
  • CRUD 메소드 기본 제공
  • 쿼리를 만들지 않아도 됨
  • 1차 캐싱, 쓰기지연, 변경감지, 지연로딩 제공
  • MyBatis는 쿼리가 수정되어 데이터 정보가 바뀌면 그에 사용 되고 있던 DTO와 함께 수정해주어야 하는 반면에, JPA 는 객체만 바꾸면 된다.
  • 즉, 객체 중심으로 개발 가능
  • but 복잡한 쿼리는 해결이 어려움

MyBatis : Object Mapping 기술

  • 자바에서 SQL Mapper를 지원해주는 프레임워크
  • SQL문을 이용하여 RDB에 접근, 데이터를 객체화 시켜줌
  • SQL 직접 작성하여 쿼리 수행 결과를 객체와 매핑
  • 쿼리문을 xml로 분리 가능
  • 복잡한 쿼리문 작성 가능
  • 하지만 객체와 쿼리문 모두 관리해야 하고, CRUD 메소드를 직접 다 구현해야함.

MyBatis

MyBatis 예시

DTO
public class UserDTO {
    private int id;
    private String name;
    private String email; // 새로운 필드 추가 시

    // getters and setters
}

XML Mapper
<!-- 기존 쿼리 -->
<select id="selectUser" resultType="UserDTO">
  SELECT id, name FROM users WHERE id = #{id}
</select>

<!-- 새로운 필드(email)을 추가한 경우, 쿼리도 수정해야 함 -->
<select id="selectUser" resultType="UserDTO">
  SELECT id, name, email FROM users WHERE id = #{id}
</select>

 

JPA

@Entity
public class User {
    @Id
    private int id;

    private String name;

    private String email; // 새로운 필드 추가

    // getters and setters
}

 

 

❓그렇다면 왜 MyBatis보다 JPA를 사용해야 할까?

다음과 같은 장점을 누릴 수 있기 때문이다.

  1. 엔티티에 맞는 테이블 생성 + DB 생성이 편리하다.
  2. 객체 지향 중심의 개발이 가능하다.
  3. 기본적인 CRUD를 자동화 할 수 있다.
  4. 복잡한 쿼리는 QueryDSL을 사용해 처리할 수 있다.

 

엔티티에 맞는 테이블 생성 + DB 생성이 편리하다.

jpa는 설정에 따라 매핑된 객체를 바탕으로 테이블을 자동으로 만들어준다.

 

객체 지향 중심의 개발이 가능하다.

우리는 JPA를 이용하면 더욱 객체지향적으로 개발할 수 있다. 그리고 이러한 방향은 Java에 더욱 잘 맞는다.

 

기본적인 CRUD를 자동화 할 수 있다.

JPA는 테이블과 객체를 매핑시키는 기술이므로 기본적인 CRUD 가 제공이된다. MyBatis를 사용한다면 이러한 쿼리들을 모두 작성해야 하는 것에 반해 JPA를 사용하면 생산성을 높일 수 있다.

 

복잡한 쿼리는 QueryDSL을 사용해 처리할 수 있다.

실제로 JPA를 이용하다 보면 동적 쿼리를 처리하기가 어렵다. 하지만 이럴때 MyBatis를 이용하기보다 QueryDSL을 사용하면 이러한 문제도 해결할 수 있다.

 

이러한 장점 뿐만 아니라 영속성 컨텍스트에 대한 이점도 있는데 이것은 다음 시간에 알아보자.

profile

응애개발자

@Eungae-D

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!