• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

다대일 양방향 연관관계를 사용할 경우 질문이 있습니다.

24.02.03 14:16 작성 24.02.03 14:26 수정 조회수 69

0

## 다대일 양방향 연관관계를 사용할 경우 질문이 있습니다
 아래와 같이 Reply 엔티티를 생성할 때 Board엔티티의 List<Reply> replies에 추가를 해주어야 하기 떄문에,
 엔티티 생성시 필요한 엔티티에 대한 select문은 getReferenceById를 사용해서 없앨 수 있었고 Reply엔티티 생성도 할 수 있었다.
````agsl
    @Transactional
    public Reply addReply(Long memberId, Long boardId, String content) {

        Member member = memberRepository.getReferenceById(memberId); //엔티티 생성에 불필요한 select문 없다.
        Board board = boardRepository.getReferenceById(boardId);
        System.out.println("===================");
        Reply reply = Reply.createReply(member, board, content);
        System.out.println("===================");
        return replyRepository.save(reply);
    }
````
 다만 다대일 양방향 연관관계의 경우 댓글을 저장할 때마다, Board에 대한 Select쿼리가 발생한다.
 
````agsl
    public static Reply createReply(Member member, Board board, String content) {
        Reply reply = new Reply();
        reply.member = member;
        reply.board = board;
        reply.content = content;
        reply.likeCount = 0;
        reply.isDeleted = false;
        log.info("board select 발생 넣기 --");
        board.addReply(reply);
        log.info("board select 발생 넣기 --");
        return reply;
    }
````

이렇게 댓글을 저장할 때 마다 board에 대한 select쿼리가 발생하다 보니 다대일 양방향 관계를 하지 말아야 하는 생각이 드는데요..
지금 프로젝트에서는 양방향 연관관계의 장점은 영속성 전이와 orphanremoval을 사용헤서 게시글 삭제시 댓글이 모두 삭제되는 이점을 얻는다는 것이 있습니다.
물론 board삭제할 경우 replyrepository에서 boardId를 통한 댓글 삭제가 가능할 것으로 생각 되는데요.

댓글을 작성할 때마다 Board select쿼리가 나가는 것은 성능상의 이슈로 봐야 할까요?? -> 다대일 단방향 연관관계로 바꾸는게 맞을까요?
아니면 양방향 연관관계의 경우 JPA를 사용하지 않을시 객체지향적 코드를 보장한다는 이야기를 들었는데 Board조회시 조인하여 Reply 컬렉션을 조회할 수 있다는 것이 장점으로 느껴지긴 합니다
(단방향 연관관계일 경우 reply 컬렉션 조회 메서드를 따로 작성해서 해결해야 함.)
어떤 선택을 해야할 지 질문드립니다!!
어떤 선택을 해야 할까요?

아래는 발생 쿼리 로그입니다.
```agsl
===================
2024-02-03T14:15:00.936+09:00  INFO 2612 --- [    Test worker] cos.blog.web.model.entity.Reply          : board select 발생 넣기 --
2024-02-03T14:15:00.937+09:00 DEBUG 2612 --- [    Test worker] org.hibernate.SQL                        : 
    select
        b1_0.board_id,
        b1_0.content,
        b1_0.created_time,
        b1_0.last_modified_time,
        b1_0.member_id,
        b1_0.title 
    from
        board b1_0 
    where
        b1_0.board_id=?
2024-02-03T14:15:00.938+09:00  INFO 2612 --- [    Test worker] p6spy                                    : #1706937300938 | took 0ms | statement | connection 74| url jdbc:h2:tcp://localhost/~/blog
select b1_0.board_id,b1_0.content,b1_0.created_time,b1_0.last_modified_time,b1_0.member_id,b1_0.title from board b1_0 where b1_0.board_id=?
select b1_0.board_id,b1_0.content,b1_0.created_time,b1_0.last_modified_time,b1_0.member_id,b1_0.title from board b1_0 where b1_0.board_id=31;
2024-02-03T14:15:00.939+09:00  INFO 2612 --- [    Test worker] cos.blog.web.model.entity.Reply          : board select 발생 넣기 --
===================
2024-02-03T14:15:00.940+09:00 DEBUG 2612 --- [    Test worker] org.hibernate.SQL                        : 
    insert 
    into
        reply
        (board_id, content, created_time, is_deleted, last_modified_time, like_count, member_id, reply_id) 
    values
        (?, ?, ?, ?, ?, ?, ?, default)
2024-02-03T14:15:00.942+09:00  INFO 2612 --- [    Test worker] p6spy                                    : #1706937300942 | took 0ms | statement | connection 74| url jdbc:h2:tcp://localhost/~/blog
insert into reply (board_id,content,created_time,is_deleted,last_modified_time,like_count,member_id,reply_id) values (?,?,?,?,?,?,?,default)
insert into reply (board_id,content,created_time,is_deleted,last_modified_time,like_count,member_id,reply_id) values (31,'replyreply','2024-02-03T14:15:00.939+0900',false,'2024-02-03T14:15:00.939+0900',0,12,default);
===================
```

답변 1

답변을 작성해보세요.

1

안녕하세요. 이원준님

이 부분은 선택인데요. 최적화를 하려면 다대일 단방향으로 변경해야 합니다.

하지만 일반적으로 이 정도 조회는 다음과 같은 이유로 전체적으로 보면 성능에 크게 문제가 되지는 않습니다.

  1. 이 로직은 댓글이 달릴 때 사용되는데요. 일반적으로 게시물을 보는 사용자가 10이라면 게시물에 답글을 다는 사용자는 1이 안됩니다.

  2. PK를 기준으로 데이터 1건을 DB에서 조회하는 것은 매우 빠릅니다.

감사합니다.