[SpringBoot] JPA란?

나른한 개발자·2026년 1월 13일

f-lab

목록 보기
24/44

ORM (Object-Relational Mapping)

ORM은 애플리케이션 클래스와 RDB의 테이블을 매핑한다는 뜻이며 기술적으로는 애플리케이션 테이블을 RDB 테이블에 자동으로 영속화해주는 것이다.

장점

  • SQL문이 아닌 Method를 통해 DB를 조작할 수 있어, 개발자는 객체 모델을 이용하여 비즈니스 로직을 구성하는데만 집중할 수 있음. (내부적으로는 쿼리를 생성하여 DB를 조작함. 하지만 개발자가 이를 신경 쓰지 않아도됨)
  • Query와 같이 필요한 선언문, 할당 등의 부수적인 코드가 줄어들어, 각종 객체에 대한 코드를 별도로 작성하여 코드의 가독성을 높임
  • 객체지향적인 코드 작성이 가능하다. 오직 객체지향적 접근만 고려하면 되기때문에 생산성 증가
  • 매핑하는 정보가 Class로 명시 되었기 때문에 ERD를 보는 의존도를 낮출 수 있고 유지보수 및 리팩토링에 유리
  • 예를 들어 기존 방식에서 MySQL 데이터베이스를 사용하다가 PostgreSQL로 변환한다고 가정해보면, 새로 쿼리를 짜야하는 경우가 생김. 이런 경우에 ORM을 사용한다면 쿼리를 수정할 필요가 없음

단점

  • 프로젝트의 규모가 크고 복잡하여 설계가 잘못된 경우, 속도 저하 및 일관성을 무너뜨리는 문제점이 생길 수 있음
  • 복잡하고 무거운 Query는 속도를 위해 별도의 튜닝이 필요하기 때문에 결국 SQL문을 써야할 수도 있음
  • 학습비용이 비쌈

JPA (Java Persistence API)

JPA는 자바 진영에서 ORM 기술 표준으로 사용되는 인터페이스 모임이다. JPA를 구현한 대표적인 구현체는 Hibernate이다.

  • Java 진영에서 ORM(Object-Relational Mapping) 기술 표준으로 사용하는 인터페이스 모음
  • 자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스
  • 인터페이스이기 때문에 Hibernate, OpenJPA 등이 JPA를 구현함
  • 애플리케이션과 JDBC 사이에서 동작

JPA 사용 이유

1. 생산성
SQL을 직접 작성하고 JDBC API하는 반복적인 일은 JPA 대신 처리해준다. CRUD용 SQL이나 DDL문을 자동으로 생성해준다. 따라서 객체 설계 중심으로 작업을 할 수 있다.

2. 유지보수
SQL을 직접 다루면 엔티티에 필드를 하나만 추가해도 관련 등록, 수정, 조회 SQL과 결과를 맵핑하기 위한 JDBC API 코드를 모두 변경해야한다. 반면 JPA를 사용하면 이런 과정을 대신 처리해주므로 필드를 추가/삭제해도 수정해야할 코드가 줄어든다.

3. 패러다임의 불일치 해결
JPA는 상속, 연관관계, 객체 그래프 탐색, 비교하기와 같은 패러다임의 불일치 문제를 해결해준다.

예를 들어 아래와 같이 연관관계가 설계되어있다고 해보자.

자바 객체에서 회원이 소속된 팀을 조회할때는 아래와 같이 참조를 사용해서 연관 찾으면 되는데, 이것을 객체 그래프 탐색이라고 한다.

Team team = member.getTeam();

객체 그래프를 탐색하는 코드는 다음과 같을 것이다.

member.getOrder().getOrderTeam()....

자유롭게 참조를 사용하여 객체 그래프를 탐색할 수 있다. 반면 SQL로는 이렇게 표현할 것이다

SELECT M.*, T.*
	FROM MEMBER M
    JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID

예를 들어 MemberDAO에서 member 객체를 조회할 때 이런 SQL을 생성하여 회원과 팀에 대한 데이터만 조회했다면 member.getTeam()은 성공하지만 객체 그래프는 데이터가 없으므로 null이라 탐색할 수 없을 것이다.

이렇게 SQL을 직접 다루면 처음 실행하는 SQL에 따라 객체 그래프를 어디까지 탐색할 수 있는지 정해지기 때문에 큰 제약사항이 생긴다. 왜냐하면 비즈니스 로직에 따라 사용하는 객체 그래프가 다른데 언제 끊어질지 모를 객체 그래프를 함부로 탐색할 수 없기 때문이다.

//회원조회 비즈니스 로직
class MemberService{
	...
    public void process() {
    	Member member = memberDAO.find(memberId);
        member.getTeam();//member->team 탐색 가능 여부 알수 없음
        member.getOrder().getDelivery(); // 탐색가능여부 알수없음

member 객체를 조회했지만 연관된 Team, Order, Delivery 방향으로 객체 그래프를 탐색할 수 있을지 없을지는 위 코드만 보고 알수없다. 결국 DAO를 직접 열어서 SQL을 확인해야 어디까지 탐색가능한지를 알 수 있을 것이다.

하지만 JPA를 사용하면 객체 그래프를 얼마든지 탐색 할 수 있다. 바로 지연로딩 때문이다.

class Member{
	private Order order;
    public Order getOrder(){
    	return order;
    }
}

Memeber 클래스에 order를 반환하는 getOrder() 하나만 정의해놓았다. 다음 코드는 지연 로딩을 사용하는 코드다.

// 처음 조회 시점에 SELECT MEMBER SQL
Member member = jpa.find(Member.class, memberId);

Order order = member.getOrder();
order.getOrderDate(); // Order를 사용하는 시점에 SELECT ORDER SQL

Member를 사용할때마다 Order를 함께 사용하면 이렇게 한 테이블씩 조회하는 것보다는 Member를 조회하는 시점에 SQL을 조인해서 Member와 Order를 함께 조회하는 것이 효과적이다.

JPA는 연관된 객체를 즉시 함께 조회할지 아니면 실제 사용되는 시점에 지연하여 조회할지를 간단한 설정으로 정의할 수 있다.

4.성능

JPA는 애플리케이션과 데이터베이스 사이에서 동작한다. 따라서 다양한 성능 최적화 기회를 제공한다. 예를 들어 같은 트랜잭션안에서 같은 회원 데이터를 두번 조회할 때, JDBC API를 사용해서 SELECT SQL로 DB와 두 번 통신 했을 것이다. 하지만 JPA에서는 한번만 SELECT SQL을 전달하고 두 번째는 조회한 회원 객체를 재사용한다.

5. 데이터 접근 추상화와 벤더 독립성
JPA는 애플리케이션과 데이터베이스 사이에 추상화된 데이터 접근 계층을 사용하여 애플리케이션이 특정 데이터베이스 기술에 종속되지 않도록 한다. 데이터베이스를 변경하더라도 JPA에게 다른 데이터 베이스를 사용한다고 알려주기만 하면 된다.

JPA는 자바 진영에서 사용하는 ORM 표준 인터페이스이다. 대표적인 구현체로는 hibernate가 있다. SQL을 직접 사용하고 JDBC를 사용하다보면 반복적인 코드가 발생하게 되는데 JPA는 기본적인 CRUD SQL과 DDL문은 자동으로 생성을 해준다. 그래서 객체 설계 중심으로 작업할수 있다. 또한 SQL을 직접 다루면 필드 하나만 추가가 되어도 관련된 생성/등록/조회 SQL과 맵핑을 하기 위한 JDBC API를 모두 변경해야한다. 하지만 JPA에서는 이 과정을 대신 처리해주기 때문에 수정해야하는 범위가 줄어든다. 또한 애플리케이션과 데이터베이스 사이에서 동작하기 때문에 영속성 컨텍스트를 사용해서 객체의 동일성을 보장하고, 네트워크 비용을 감소하는 등 성능을 최적화할 수 있다.

profile
Start fast to fail fast

0개의 댓글