이번 글은 데브코스 Spring Boot REST API 실습 11강 내용을 정리한 글이다.
11강에서는 댓글 삭제 API를 구현하면서,
왜 JPA에서 @Transactional이 없으면 삭제가 DB에 반영되지 않는지를 직접 체험한다.
또한 orphanRemoval = true 옵션이
어떤 방식으로 실제 DELETE SQL까지 이어지는지도 함께 정리한다.
11강의 목표는 다음과 같다.
@Transactional이 없을 때 삭제 실패 원인 이해@GetMapping("/{id}/delete")
public String delete(
@PathVariable int postId,
@PathVariable int id
) {
Post post = postService.findById(postId).get();
PostComment postComment = post.findCommentById(id).get();
postService.deleteComment(post, postComment);
return "%d번 댓글이 삭제되었습니다.".formatted(id);
}
코드만 보면:
👉 정상적으로 삭제될 것처럼 보인다.
하지만 실제로는 DB에서 삭제가 일어나지 않았다.
핵심 원인은 단 하나다.
트랜잭션(@Transactional)이 없었다.
@OneToMany(
mappedBy = "post",
fetch = LAZY,
cascade = {PERSIST, REMOVE},
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
그리고 댓글 삭제는 다음 메서드로 처리된다.
public boolean deleteComment(PostComment postComment) {
if (postComment == null) return false;
return comments.remove(postComment);
}
여기서 중요한 포인트는:
comments.remove()는 자바 컬렉션에서 제거orphanRemoval = true 설정 덕분에JPA는 다음과 같은 방식으로 동작한다.
comments.remove())즉,
❌ 메서드 호출 순간에 DELETE SQL 실행
⭕ 트랜잭션 종료 시점(commit)에 SQL 실행
👉 그래서 컬렉션에서는 삭제된 것처럼 보이지만,
👉 DB에는 그대로 남아 있는 상태가 된다.
@GetMapping("/{id}/delete")
@Transactional
public String delete(
@PathVariable int postId,
@PathVariable int id
) {
Post post = postService.findById(postId).get();
PostComment postComment = post.findCommentById(id).get();
postService.deleteComment(post, postComment);
return "%d번 댓글이 삭제되었습니다.".formatted(id);
}
이제 흐름은 다음과 같다.
@Transactional 시작
↓
comments.remove(postComment)
↓
JPA 변경 감지
↓
@Transactional 종료 (commit)
↓
flush 발생
↓
DELETE SQL 실행
👉 DB에서도 댓글이 정상적으로 삭제된다.
트랜잭션 종료 시점에 JPA는 다음과 같은 SQL을 실행한다.
DELETE FROM post_comment
WHERE id = ?
이 과정에서:
repository.delete()를 직접 호출하지 않아도orphanRemoval = true 설정 덕분에11강에서는 조회 API들에도 다음과 같이 설정했다.
@Transactional(readOnly = true)
이 설정의 의미는 다음과 같다.
즉, 관례적으로:
@Transactional(readOnly = true)@Transactional이 패턴을 많이 사용한다.
orphanRemoval = true는 고아 엔티티를 DELETE 대상으로 만든다@Transactional이 필요하다readOnly = true로 의도를 표현한다11강은 댓글 삭제 API를 통해
JPA에서 트랜잭션이 왜 필수인지를 직접 체험하는 강의였다.