JPA EntityManager의 persist()와 merge()

ShaynePark·2025년 10월 25일

SpringBoot

목록 보기
4/4

JPA를 쓰다 보니 entityManager.persist()와 entityManager.merge()가 갑자기 무슨 차이가 있을까? 하는 궁금증이 시작되었어요. 처음 봤을때 “둘 다 저장하는 거 아냐?” 싶었지만, 분명 다른 무언가가 있을 것이라는 생각에 이 둘을 알아보기로 했습니다.

JPA의 EntityManager가 어떻게 엔티티를 다루는지, 그리고 그 핵심이 되는 엔티티 생명주기(비영속 / 영속 / 준영속 / 삭제) 를 함께 정리해보겠습니다.


EntityManager란?

JPA의 핵심은 EntityManager입니다. 엔티티를 데이터베이스와 연결해주는 중간 관리자죠. EntityManager는 다음과 같은 일을 합니다. 엔티티를 DB에 저장하거나 조회, 변경 감지를 통해 수정 사항 자동 반영, 엔티티의 상태 관리(영속, 비영속, 준영속 등)를 합니다.
EntityManager는 단순히 insert/update 명령을 실행하는 도구가 아니라, 엔티티의 생명주기를 전반적으로 관리하는 “엔티티 관리자”입니다.


엔티티의 생명주기 4단계

상태설명예시
비영속 (new/transient)아직 EntityManager가 모르는 상태. DB와 전혀 연결 안 됨주민등록 전
영속 (managed/persistent)EntityManager가 관리 중인 상태. 변경 감지가 일어남주민 등록 완료
준영속 (detached)원래 영속이었지만, 이제 EntityManager가 더 이상 관리하지 않음해외로 나가서 더 이상 정부가 추적 안 함
삭제 (removed)DB에서 삭제될 예정인 상태사망신고 접수

EntityManager가 관리 중이면 "영속",
관리하지 않으면 “비영속” 혹은 “준영속” 상태입니다.


persist() — 새로운 엔티티 등록

persist()는 말 그대로 “새로운 객체를 영속 상태로 전환”시키는 역할이고,
DB에 새 레코드를 INSERT할 때 사용합니다.

val user = User(name = "지훈")
entityManager.persist(user)

위 코드를 실행하면 다음과 같은 상황이 일어납니다.

  • user는 비영속 상태 → 영속 상태로 변경
  • 트랜잭션이 커밋될 때 INSERT 쿼리 실행
  • user는 여전히 같은 객체로 유지됨

여기서 중요한 점은, persist()는 이미 DB에 존재하는 데이터를 업데이트하는 함수가 아닙니다. 항상 새로운 데이터 등록용이에요.


merge() — 준영속 객체의 복귀

merge()는 조금 헷갈릴 수 있습니다. 이 메서드는 준영속(또는 비영속) 엔티티를 다시 영속 상태로 복귀시키는 역할을 합니다. 예를 들어, 트랜잭션이 끝나면 EntityManager는 닫히고 엔티티는 “준영속”이 됩니다. 이 상태에서 객체를 수정해도 DB에는 반영되지 않아요.

// 트랜잭션1
val user = entityManager.find(User::class.java, 1L)
// user는 영속 상태

// 트랜잭션 종료 후 -> 준영속 상태
user.name = "New Name" // DB 반영 안 됨

// 트랜잭션2
val mergedUser = entityManager.merge(user)

이제 merge()가 호출되면

  • DB에서 같은 ID를 가진 엔티티를 새로 조회
  • user의 변경 내용을 복사해서 새로운 영속 엔티티에 반영
  • 반환값(mergedUser)은 영속 상태, 기존 user는 여전히 준영속 상태

merge()는 객체를 그대로 다시 관리하는 게 아니라, 복사본을 새로 관리합니다.
이게 중요한 이유는 기존 객체를 건드려봤자 DB 반영이 안 되기 때문이에요.
merge()의 리턴값을 써야 실제 DB 반영이 됩니다.


persist()와 merge() 차이

항목persist()merge()
목적새 엔티티 등록준영속 엔티티 다시 영속화
새로운 insert?아니오 (update 동작 가능)
객체 동일성그대로 유지새 복사본 리턴
변경 감지이후부터 감지 시작병합된 객체에서 감지
사용 시점신규 등록기존 데이터 수정 재연결

이것 외에 다른건 무엇이 있을까?

EntityManager에는 persist()와 merge() 외에도 두 가지가 더 있습니다.

1. detach(entity)

entityManager.detach(user)
user.name = "Detached" // DB 반영 안 됨

이 객체는 준영속 상태가 되어, 더 이상 변경 감지가 일어나지 않습니다.

2. remove(entity)

엔티티를 삭제 예정 상태로 바꾸고, 트랜잭션 커밋 시 DELETE 쿼리가 실행됩니다.

entityManager.remove(user)

user는 “삭제 예정(removed)” 상태가 되고, 이후 트랜잭션이 끝나면 실제 DB에서도 삭제됩니다.


위의 내용을 다시한번 정리하면

상태의미주요 메서드
비영속EntityManager가 모르는 객체new User()
영속EntityManager가 관리 중persist()
준영속더 이상 관리 안 함detach() / 트랜잭션 종료
삭제삭제 예정 상태remove()
병합준영속 → 영속 복귀merge()

JPA의 EntityManager는 단순한 DB 커넥터가 아니라, 엔티티의 상태를 추적하고 관리하는 컨트롤 타워입니다. persist(), merge(), detach(), remove() 같은 메서드는 단순히 SQL을 실행하는 게 아니라 “엔티티의 생명주기”를 조작하는 도구에 가깝습니다.

이 구조를 이해하면, “언제 DB에 반영되는지?”, “왜 수정했는데 저장이 안 될까?”, “merge는 왜 새 객체를 반환하지?” 같은 의문들이 자연스럽게 풀립니다.
결국 JPA를 잘 다루기 위해서 SQL보다 먼저, 엔티티의 생명주기를 이해하는 게 핵심인 것 같아요.

0개의 댓글