본문 바로가기
프로젝트/트러블 슈팅

[트러블 슈팅] JPA 연관 관계와 테스트 코드 : delete 쿼리가 실행되지 않는 현상 해결

by taetae99 2025. 1. 5.
반응형

목차

     

     


    문제 상황 설명 

     

     

    SpringJPA를 사용한 프로젝트 진행 중에 처음으로 문제에 직면했다. 

     

    게시글과 관련된 Repository와 Service를 작성하고 게시글과 관련된 테스트 코드를 작성 중에

     

    게시글을 삭제하는 부분에서 DELETE 쿼리가 작동하지 않는 문제가 발생했다.

     

    @SpringBootTest
    @Transactional
    class PostServiceTest {
    
        @Autowired
        PostService postService;
        @Autowired
        MemberService memberService;
    
        
    
        @Test
        public void 게시글_삭제() {
            //given
            Member member = createMember("tae", "kino@spring.com", "123456", "kino");
            Post post = createPost(member, "JPA", "JPA에 대한 학습중 입니다.", member.getNickname());
    
            //when
            postService.deletePost(post.getId());
    
            //then
            assertThat(postService.findPostsByMember(member.getId()).size()).isEqualTo(0);
        }
    
    
        private Member createMember(String name, String email, String password, String nickname) {
            Member member = Member.createMember(name, email, password, nickname);
            memberService.join(member);
            return member;
        }
    
        private Post createPost(Member member, String title, String content, String nickname) {
            Post post = Post.createPost(member, title, content, nickname);
            postService.savePost(post);
            return post;
        }
    
    }

     

     

    게시글 삭제의 테스트 코드는 위와 같은 순서로 진행된다. 

    1. 멤버를 생성하고 그 멤버의 정보로 게시글을 생성한다.
    2. postService의 게시글 삭제 로직을 실행한다.
    3. 생성된 게시글은 한 개였고 이를 삭제했으니 findPostByMember로 검색한 결과는 0으로 예상된다.

     

    postservice.deletepost
    PostServece의 deletePost
    repository.delete
    PostRepository의 delete

     

     

     

     


    문제 상황 실행 결과

     

     

    실패 이미지

     

    예상했던 0과는 다르게 실제 값은 1이라고 나온다. 이는 게시글이 제대로 삭제되지 않았다는 것으로 볼 수 있다.

    실제 위의 로그를 확인해 보면 delete 쿼리가 작동하지 않았다.

     

     

     


     

     

    해봤던 시도들

     

     

     

    다양한 블로그를 확인하고 검색하며 문제 원인을 파악하고자 했다. 

     

    검색 결과 예상되는 문제는 두 가지였다. 

    1. 테스트 코드에서의 @Transactional의 사용으로 rollback이 발생한다.
      • @Rollback(value=false)를 사용하여 본다. - 실패
    2. PostRepositort의 delete메서드에서 em.remove에 대한 문제로 EntityManager의 특징을 이해하지 못하였을 것이다.
      • em.remove 이후에 em.flush를 직접 호출해 보았다. - 실패 

     

     


     

    문제 상황 해결

     

     

    해결을 하는데 필요했던 내용은 두 가지였다. 

     

    1. EntityManager에서의 삭제과정에 대한 이해

    삭제 대상 엔티티를 조회하고 EntityManager에 넘겨주면 해당 엔티티를 삭제한다.
    삭제 쿼리를 쓰기 지연 SQL 저장소에 등록한 뒤 트랜잭션을 커밋해서 flush를 호출하면 그제야 DB에 삭제 쿼리를 전달한다.

     

    2. 연관관계 속성에 대한 이해

    내가 작성했던 Post엔티티에 대해 다시 봐보자

    Post와 Member엔티티는 양방향 연관관계를 맺고 있다. 이를 위해 연관관계 메서드를 작성했었다.

    Post엔티티
    연관관계 메서드

     

    Post를 삭제하기 전에 Post와 Member의 연관 관계를 끊지 않으면, Member가 여전히 영속성 컨텍스트에서 관리되기 때문에 JPA는 Post 삭제를 보류한다. 이 경우 delete 쿼리는 쓰기 지연 저장소에 추가되지만, Post 엔티티가 Member와의 연관 관계로 인해 삭제 가능한 상태로 간주되지 않아 실제 쿼리가 실행되지 않는다.

     

     


     

    해결을 하는 방법은 연관관계를 끊어 준 뒤 엔티티를 삭제한다. 

    Post 엔티티에서 연관관계 해제 메서드 작성
    PostRepository에서 연관관계 해제 후 remove

     

    연관관계를 끊어주고 테스트를 진행하면 예상했던 결과대로 delete문이 작동하며 테스트를 통과한다. 

     

     

     

     


     

    해결하는데 도움이 되었던 글:

     

    1. 영속성 컨텍스트와 엔티티 생명주기

    https://doublesprogramming.tistory.com/259

     

    JPA - 영속성 관리

    본 글은 자바 ORM 표준 JPA 프로그래밍를 읽고 개인적으로 학습한 내용 복습하기 위해 작성된 글로 내용상 오류가 있을 수 있습니다. 오류가 있다면 지적 부탁 드리겠습니다. JPA - 영속성 관리 1.

    doublesprogramming.tistory.com

     

    2. 인프런에 작성된 질문 

    https://www.inflearn.com/community/questions/989193/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-jpa-delete-%EC%95%88%EB%90%98%EB%8A%94-%EC%9D%B4%EC%9C%A0%EA%B0%80-%EA%B6%81%EA%B8%88%ED%95%A9%EB%8B%88%EB%8B%A4

     

    스프링 데이터 JPA delete 안되는 이유가 궁금합니다 - 인프런 | 커뮤니티 질문&답변

    누구나 함께하는 인프런 커뮤니티. 모르면 묻고, 해답을 찾아보세요.

    www.inflearn.com

     

    3. 트랜잭션에 대한 정리와 사용에 대한 글

    https://velog.io/@backfox/%EA%B9%80%EC%B6%98%EB%B0%B0%EC%99%80-%EC%95%8C%EC%95%84%EB%B3%B4%EB%8A%94-Transactional-%EC%9D%B4%EB%AA%A8%EC%A0%80%EB%AA%A8-1-%ED%85%8C%EC%8A%A4%ED%8A%B8%EC%BD%94%EB%93%9C

     

    @Transactional 이모저모 1 - 테스트코드와 @Transactional

    이 포스팅 보고 테스트 짰다면 얼마나 좋았을까?

    velog.io

     

    반응형