자바 백엔드 입문 44편. Phase 6.5 JPA 시작. JPA·Hibernate·Spring Data JPA 세 이름이 헷갈리는 이유와 정확한 관계를 자동차 산업 비유로 풀어쓴 학습 노트.
이 글은 자바 백엔드 입문 시리즈 59편 중 44편이에요. Phase 6 Data Access 3편이 끝났고, 이번 44편부터 Phase 6.5 Spring Data JPA 4편으로 들어갑니다. 한국 회사 백엔드의 90%가 JPA 기반이라 이번 4편은 시리즈의 핵심 중 하나. 29편은 그 첫 글로 — 입문자가 가장 헷갈리는 "JPA·Hibernate·Spring Data JPA 세 이름의 차이" 를 풀어요.
세 이름이 헷갈리는 이유
처음 "JPA" 단어를 들으면 — 검색 한 번에 "Hibernate가 JPA의 구현", "Spring Data JPA가 JPA의 래퍼", "EntityManager·SessionFactory·JpaRepository" 같은 단어가 한꺼번에 쏟아져요. 셋이 같은 건가, 다른 건가, 어떤 관계인가 — 처음 보면 정말 막막.
이 글에서는 자동차 산업 비유로 풀어요. JPA = "국제 자동차 안전 표준", Hibernate = "그 표준을 따라 만든 실제 자동차", Spring Data JPA = "자동차에 자동주차·자동긴급제동 같은 편의 기능을 얹은 패키지". 끝까지 따라오시면 세 이름이 한 그림에 들어와요.
ORM이 등장한 배경 — 자바 객체 vs 관계형 DB
ORM(Object-Relational Mapping) 단어부터. 자바 객체와 관계형 DB 사이 "패러다임 불일치" 가 있어요.
| 자바 객체 | 관계형 DB |
|---|---|
| 클래스 + 객체 + 참조 | 테이블 + 행 + 외래 키 |
| 상속·다형성 | 테이블 상속 없음 |
| 객체 그래프 (참조의 참조) | 평면 SQL JOIN |
order.getUser().getName() |
SELECT u.name FROM users u JOIN orders o ON ... |
42편 JdbcTemplate 패턴으로 짜면 — 매번 SQL 짜고 ResultSet에서 객체로 변환하고 객체 참조 직접 연결하는 보일러플레이트가 또 만들어져요. "왜 이걸 자동화 못 하나" 가 1990년대 자바 개발자의 큰 불만이었어요.
ORM = "객체 그래프와 DB 테이블 사이 매핑을 자동 처리" 라는 발상. "내가 자바 객체로 다루면, ORM이 알아서 SQL 짜고 DB 반영".
JPA — 자바의 ORM 표준 규격
JPA(Java Persistence API) 는 "자바 ORM의 표준 규격" 이에요. 2006년 Java EE 5의 일부로 등장했고, 현재는 Jakarta EE 표준(jakarta.persistence.*).
핵심 — JPA는 인터페이스·어노테이션의 집합이지 실제 동작 코드가 아니에요. @Entity·@Table·@Id·EntityManager 같은 표준 정의만 있고, "실제로 어떻게 SQL을 짜고 객체를 만들고 캐싱하는가" 는 구현체가 처리.
비유 — JPA = "국제 자동차 안전 표준(에어백·ABS는 이런 사양을 만족해야 한다)". 표준 자체는 자동차가 아니에요. 자동차 회사들이 그 표준을 따라 자기 자동차를 만들 뿐.
Hibernate — JPA의 실제 구현체
Hibernate 는 자바 ORM의 "실제 동작하는 구현 라이브러리" 예요. 2001년 등장 — JPA보다 5년 앞서. JPA 표준은 사실 Hibernate를 거의 모델로 삼아 만들어졌어요.
JPA 인터페이스를 Hibernate가 구현하고, 실제로 SQL 생성·실행·결과 매핑을 다 처리. JPA 사용자는 "Hibernate가 안에서 도는지" 신경 안 쓰고 표준 JPA만 알면 됩니다.
JPA 구현체는 Hibernate 외에도 EclipseLink·OpenJPA 등이 있는데 — 한국 회사 99%가 Hibernate. Spring Boot 기본도 Hibernate.
비유 — Hibernate = "현대자동차", EclipseLink = "기아", OpenJPA = "GM". 같은 안전 표준(JPA)을 따르지만 실제 운전 경험은 회사마다 미세하게 다를 수 있음.
Spring Data JPA — JPA의 편의 래퍼
Spring Data JPA 는 "JPA(보통 Hibernate)를 Spring에서 더 쉽게 쓰게 해주는 추상화 레이어" 예요. JPA 자체가 아니라 JPA 위에 한 겹 더.
핵심 — JpaRepository 인터페이스 한 줄로 CRUD가 자동 구현돼요.
public interface OrderRepository extends JpaRepository<Order, Long> {
List<Order> findByStatus(String status);
Optional<Order> findByOrderNumber(String orderNumber);
}
이 인터페이스 한 개만 정의하면 — Spring Data JPA가 시작 시점에 자동으로 구현체를 만들어 Bean으로 등록. save()·findById()·findAll()·deleteById() 같은 기본 CRUD + 사용자 정의 메서드 (findByStatus)까지 다 자동.
비유 — Spring Data JPA = "자동차에 자동주차·자동긴급제동 같은 편의 기능을 얹은 패키지". 자동차(Hibernate)는 그대로지만 운전이 훨씬 편해져요.
세 이름 정리 — 한 그림으로
[Spring Data JPA] ← 편의 래퍼 (JpaRepository·메서드 이름 쿼리)
↓ 위에 얹힘
[JPA] ← 자바 ORM 표준 (인터페이스·어노테이션)
↓ 구현
[Hibernate] ← 실제 동작 라이브러리 (SQL 생성·실행)
↓ 사용
[JDBC] ← 자바 표준 DB API
↓
[DataSource] ← 커넥션 풀
↓
[DB (PostgreSQL·MySQL ...)]
위로 갈수록 추상화, 아래로 갈수록 실제 SQL과 DB. 한국 회사 백엔드는 보통 가장 위(Spring Data JPA)에서 코드 짜고, 가끔 복잡한 쿼리에 한 단계 아래(JPA·Hibernate)로 내려가요.
Spring Boot에서 의존성 한 줄
세 라이브러리를 다 합쳐 한 줄 의존성.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'org.postgresql:postgresql'
}
spring-boot-starter-data-jpa 한 줄에 Spring Data JPA + JPA + Hibernate 다 들어 있어요. 별도 설정 안 해도 위 세 가지가 자동 동작 준비.
application.yml — JPA 설정
41편 의 DataSource 설정에 한 블록 추가.
spring:
datasource:
url: jdbc:postgresql://localhost:5432/myshop
username: postgres
password: secret
jpa:
hibernate:
ddl-auto: validate # 운영 표준
show-sql: false # 운영에서는 false (성능)
properties:
hibernate:
format_sql: true # 개발 시 SQL 보기 좋게
default_batch_fetch_size: 100 # N+1 완화
핵심 옵션 — spring.jpa.hibernate.ddl-auto 가 Entity ↔ 실제 DB 테이블 동기화 정책.
| 값 | 의미 | 사용 |
|---|---|---|
none |
아무것도 안 함 | 운영 가능 |
validate |
시작 시 Entity ↔ 테이블 일치 검증만 | 운영 표준 |
update |
자동으로 누락된 컬럼·테이블 추가 | 개발 가능, 운영 위험 |
create |
시작 시 테이블 전부 새로 만들기 | 테스트 전용 |
create-drop |
시작 시 만들고 종료 시 삭제 | 인메모리 테스트 |
운영 표준 = validate 또는 none. update 는 "실수로 컬럼이 자동 추가되어 운영 사고" 위험이라 비권장. 운영 DB 스키마는 Flyway·Liquibase 같은 별도 마이그레이션 도구로 관리.
JPA의 핵심 컨셉 미리보기
30·31·32편에서 깊이 다룰 컨셉을 미리 한 줄씩.
@Entity— "이 클래스를 DB 테이블로 매핑" (30편)JpaRepository— "기본 CRUD 자동 구현" (30·31편)- 메서드 이름 쿼리 —
findByStatus()같이 메서드 이름으로 SQL 자동 생성 (31편) @Query— JPQL 또는 네이티브 SQL 직접 작성 (31편)- 영속성 컨텍스트 — JPA가 "내가 관리하는 객체들" 을 저장하는 1차 캐시 (32편)
- 지연 로딩 — "필요할 때만 DB 조회" 자동 처리 (32편)
이 6개가 박혀 있으면 한국 회사 JPA 코드의 95%가 해석돼요.
JPA vs JdbcTemplate — 언제 무엇을?
42편 JdbcTemplate과 비교가 자주 나와요.
| JdbcTemplate | JPA (Spring Data JPA) | |
|---|---|---|
| 코드 작성 | SQL 직접 + RowMapper | 객체 그래프 + 메서드 이름 |
| 학습 곡선 | 완만 (SQL만 알면 됨) | 가파름 (영속성 컨텍스트·LazyLoading 개념 필요) |
| 쿼리 자유도 | 매우 높음 — SQL 그대로 | 제한적 — 복잡 쿼리는 별도 작업 |
| 유지보수 | SQL 수정 빈번 | 객체 모델 변경 위주 |
| 성능 튜닝 | SQL 단위 제어 쉬움 | JPA 함정 회피 노하우 필요 |
| 한국 회사 사용 | 레거시·통계·복잡 쿼리 | 신규 프로젝트 90%+ |
한국 회사 표준 패턴 = JPA 기본 + 복잡한 쿼리에만 JdbcTemplate 또는 QueryDSL. JPA를 잘 다루는 게 자바 백엔드 채용의 필수 자격.
JPA는 "처음 한 달은 헷갈리고, 두세 번 실수하면서 영속성 컨텍스트와 LazyLoading을 이해하는" 도구예요. 첫 학습에 시간 투자가 필요하지만 — 한 번 잡으면 자바 백엔드 개발 속도가 차원이 달라집니다. 32편 영속성 컨텍스트가 가장 중요한 글이 될 거예요.
한 줄 정리 — JPA = 자바 ORM 표준 (인터페이스·어노테이션). Hibernate = JPA 실제 구현체 (한국 99%). Spring Data JPA = JPA를 더 쉽게 쓰는 편의 래퍼. 한국 회사 백엔드 = Spring Data JPA 90% + JdbcTemplate 보조.
시험 직전 한 번 더 — JPA·Hibernate·Spring Data JPA 입문자가 매번 헷갈리는 것
- JPA = Java Persistence API. 자바 ORM 표준 규격
- 2006년 Java EE 5, 현재 Jakarta EE (
jakarta.persistence.*) - JPA는 인터페이스·어노테이션의 집합 — 실제 동작 X
- Hibernate = JPA의 가장 흔한 구현체. 2001년 등장
- Hibernate가 JPA보다 5년 앞섬 — JPA가 Hibernate 모델로 만들어짐
- 한국 회사 JPA 구현 99% = Hibernate
- 다른 구현체 = EclipseLink·OpenJPA (드물게)
- Spring Data JPA = JPA 위에 얹은 편의 래퍼
- 핵심 =
JpaRepository한 줄로 CRUD 자동 구현 - 메서드 이름 쿼리 =
findByStatus()같은 자동 SQL 생성 - Spring Boot =
spring-boot-starter-data-jpa한 줄에 셋 다 포함 application.yml의spring.jpa.hibernate.ddl-auto= 스키마 동기화 정책- 운영 =
validate또는none표준 create·create-drop= 테스트 전용update= 운영 위험 (자동 컬럼 추가 사고)- 운영 스키마 마이그레이션 = Flyway·Liquibase
- ORM = Object-Relational Mapping. 객체 ↔ DB 매핑 자동화
- ORM 등장 배경 = 객체-관계형 패러다임 불일치
- JPA·Hibernate·Spring Data JPA = 위에서 아래로 추상화 → 구체
- 한국 회사 = JPA 기본 + 복잡 쿼리에만 JdbcTemplate·QueryDSL
시리즈 다른 편 (앞뒤 글 모음)
이전 글:
- 39편 — Spring @Async CompletableFuture 비동기
- 40편 — Spring WebClient RestClient HTTP 클라이언트
- 41편 — JDBC와 DataSource
- 42편 — JdbcTemplate으로 SQL 다루기
- 43편 — @Transactional의 원리
다음 글: