[데브코스] Spring Boot REST API 실습 (12강) - orphanRemoval, 더티 체킹, 그리고 영속성 컨텍스트의 역할

zuno·2025년 12월 21일

이번 글은 데브코스 Spring Boot REST API 실습 12강 내용을 정리한 글이다.
12강은 새로운 기능을 구현하는 강의라기보다는,
댓글 삭제 API가 왜 동작했고, 왜 동작하지 않았는지
JPA 내부 동작 관점에서 정리하는 강의였다.

핵심 키워드는 다음 세 가지다.

  • orphanRemoval = true
  • 더티 체킹(Dirty Checking)
  • 영속성 컨텍스트(Persistence Context)

1️⃣ 12강의 핵심 질문

11강에서 댓글 삭제 API를 구현하면서 다음과 같은 현상을 경험했다.

  • orphanRemoval = true 설정이 있음
  • 댓글을 리스트에서 제거함
  • 하지만 @Transactional이 없을 때는 DB에서 삭제가 안 됨

이 강의의 핵심 질문은 바로 이것이다.

왜 orphanRemoval = true인데도
트랜잭션이 없으면 실제 DB 삭제가 일어나지 않을까?


2️⃣ orphanRemoval = true 다시 정리

@OneToMany(
    mappedBy = "post",
    orphanRemoval = true
)
private List<PostComment> comments;

orphanRemoval = true의 의미는 다음과 같다.

부모 엔티티(Post)의 컬렉션에서
자식 엔티티(PostComment)가 제거되어
더 이상 어떤 부모에도 속하지 않게 되면
해당 자식 엔티티를 DB에서도 DELETE 처리한다.

즉,

post.getComments().remove(comment);

post.getComments() -> 리스트
리스트.remove(댓글)

이 한 줄은
조건만 맞으면 DB DELETE까지 이어질 수 있는 코드다.


3️⃣ 더티 체킹(Dirty Checking)이란?

더티 체킹은 JPA의 핵심 메커니즘이다.

JPA가 영속 상태의 엔티티 변경사항을 감지하여
트랜잭션 종료 시점에
자동으로 데이터베이스에 반영하는 기능

중요한 점은 다음 두 가지다.

  • JPA는 변경 순간에 SQL을 실행하지 않는다
  • 변경 내용은 트랜잭션이 끝날 때 한 번에 반영된다

4️⃣ 영속성 컨텍스트란?

한 문장 정의

영속성 컨텍스트는
JPA가 엔티티를 관리하는 공간이며,
더티 체킹이 일어나는 장소다.

조금 더 풀면:

  • DB에서 조회한 엔티티를 보관하는 1차 캐시
  • 엔티티의 최초 상태를 기억
  • 이후 변경 사항과 비교
  • 트랜잭션 종료 시점에 변경을 DB에 반영

👉 더티 체킹은 영속성 컨텍스트 없이는 동작할 수 없다.


5️⃣ 영속성 컨텍스트는 언제 생성되고 사라질까?

Spring + JPA 환경에서 가장 일반적인 흐름은 다음과 같다.

@Transactional 시작
→ 영속성 컨텍스트 생성
→ 엔티티 조회 / 수정 / 삭제
→ 트랜잭션 종료 (commit 또는 rollback)
→ flush
→ 영속성 컨텍스트 종료

즉,

트랜잭션 시작 = 영속성 컨텍스트 생성
트랜잭션 종료 = 영속성 컨텍스트 종료


6️⃣ 댓글 삭제 코드의 실제 동작 흐름

코드

@Transactional
post.getComments().remove(comment);

내부 동작 순서

1️⃣ 트랜잭션 시작
→ 영속성 컨텍스트 생성

2️⃣ post 조회
→ Post 엔티티가 영속성 컨텍스트에 등록

3️⃣ getComments() 호출
→ 필요 시 댓글 SELECT 쿼리 실행
→ 댓글 엔티티들도 영속 상태가 됨

4️⃣ comments.remove(comment)
→ 자바 컬렉션에서 제거
→ JPA가 변경 사항을 기억만 함

5️⃣ 트랜잭션 종료(commit)
→ 더티 체킹 수행
→ orphanRemoval = true 확인
→ DELETE SQL 생성 및 실행

DELETE FROM post_comment WHERE id = ?

6️⃣ 영속성 컨텍스트 종료


7️⃣ @Transactional이 없으면 왜 실패할까?

트랜잭션이 없으면 다음 문제가 발생한다.

  • 영속성 컨텍스트가 없거나 매우 짧게 유지됨
  • 더티 체킹이 정상적으로 동작하지 않음
  • 커밋 시점이 없어서 SQL이 실행되지 않음

즉 흐름은 다음과 같다.

comments.remove(comment)
→ 변경 발생
→ ❌ 트랜잭션 없음
→ ❌ 커밋 없음
→ ❌ DELETE SQL 실행 안 됨

그래서 컬렉션에서는 삭제된 것처럼 보이지만,
DB에는 그대로 남아 있는 현상이 발생한다.


8️⃣ 12강의 핵심 메시지

12강이 전달하려는 메시지는 명확하다.

  • orphanRemoval은 더티 체킹에 의존한다
  • 더티 체킹은 영속성 컨텍스트 안에서만 동작한다
  • 영속성 컨텍스트는 트랜잭션과 함께 생기고 사라진다
  • 따라서 변경 작업에는 반드시 @Transactional이 필요하다

🔚 12강 정리

  • orphanRemoval = true는 컬렉션 제거를 DELETE로 연결한다
  • 더티 체킹은 JPA 변경 감지의 핵심 메커니즘이다
  • 더티 체킹은 트랜잭션 내부에서만 동작한다
  • 영속성 컨텍스트는 트랜잭션과 생명주기를 함께한다
  • @Transactional이 없으면 실제 DB 반영이 이루어지지 않는다

💡 한 줄 요약

12강은 댓글 삭제를 통해
orphanRemoval, 더티 체킹, 영속성 컨텍스트가
왜 트랜잭션과 함께 이해되어야 하는지
를 정리하는 강의였다.

0개의 댓글