woowacourse-teams/2020-saebyeok

대댓글 백엔드 구성하고 프론트엔드와 연결하기

hwanghe159 opened this issue · 0 comments

목적

대댓글을 게시할 수 있고, 표시되어야 한다.

체크리스트

  • 대댓글 인수테스트 작성하기
  • 대댓글 도메인 구성하기
  • 대댓글 관련 기능 구현하기
  • 프론트엔드로부터 오는 대댓글 게시 요청과 백엔드 연결하기
  • 프론트엔드로 보내는 대댓글 정보를 프론트에서 표시하기

주의 사항

관련 이슈

일정

대댓글 기능 백엔드 구현 과정

  • 처음에 했던 생각 : Comment 엔티티와 거의 유사한 Recomment 엔티티를 만들어서 따로 관리하자.

  • 하지만 Comment와 Recomment를 분리하면 다음과 같은 문제가 있었음

    • 한 게시글에 대한 댓글수를 받아오고자 할때 Comment 개수, Recomment 개수 따로 구해서 더해줘야 하는 문제 (큰 문제는 아니지만 복잡함)
    • Comment에 대한 like처럼 Recomment에 대한 like도 따로 만들어야 하나? -> 귀찮음
    • 나중에 회원이 받은 모든 Comment수, like수를 가져올때도 Comment에서 정보 가져오고, Recomment에서 또 정보 가져오고 합쳐야 함
    • 무엇보다도 Comment와 Recomment는 굉장히 유사함. 중복이 심한게 마음에 안들었음
  • 그래서 Comment에 parent를 추가해서 해결함

    • @Entity
      public class Comment {
          
          (..중략..)
      
          @ManyToOne
          private Comment parent;
          
          (..중략..)
          
      }
    • parent가 null이면 댓글, null이 아니면 대댓글

    • 대댓글과 댓글은 다대일이므로 @ManyToOne

    • 와 Comment 안에 Comment필드를 넣어서 연결하는게 되네? 신기하다 라고 생각했던 이유

      • 아직 엔티티 클래스를 테이블에 연관지어서 생각하는 게 남아있어서 신기하다고 느꼈던 것 같음
      • 테이블에 연관지어서 생각하면 뭔가 재귀적이어서 안될 것 같지만 객체라고 생각하면 자연스러움
      • 테이블을 생각하지 않고 개발하기 위해 생긴 JPA의 진가를 느낄 수 있었음
  • 이렇게 구현했을 때의 문제

    • 예) 댓글 A,B,C를 달고, 대댓글 D,E는 B에, 대댓글 F는 A에 달았을 경우,

    • 즉, 
      
      댓글 A
      └> 댓글 F
      댓글 B
      └> 댓글 D
      └> 댓글 E
      댓글 C
      
    • 댓글을 단 시간은 A -> B -> C -> D -> E -> F 지만 A -> F -> B -> D -> E -> C 순으로 정렬해서 Response DTO에 넣어줘야 한다.

  • 정렬하기 위해 다음과 같은 방법을 사용함.

    • @Entity
      public class Comment implements Comparable<Comment> {
          
          (..중략..)
      
          @Override
          public int compareTo(Comment other) {
              Comment parentOfThis = (this.parent == null ? this : this.parent);
              Comment parentOfOther = (other.parent == null ? other : other.parent);
              if (parentOfThis != parentOfOther) {//다른 그룹인경우(AF끼리, BDE끼리, C끼리 같은 그룹)
                  return parentOfThis.createdDate.compareTo(parentOfOther.createdDate);
              }
              return this.createdDate.compareTo(other.createdDate);//같은 그룹인경우
          }
      }

      Comparable<Comment>를 구현하고, compareTo()를 오버라이드함.

    • 그럼 comments.stream().sorted()... 같이 사용하면 정렬됨!

  • 이제 정렬은 됐고, 댓글인지, 대댓글인지 판단해서 프론트에서 다르게 보여줘야 하니까

    •         <v-col
                v-for="comment in article.comments"
                :key="comment.id"
                cols="12"
                class="justify-center pt-0 pb-0"
              >
                <div v-if="comment.hasNoParent">
                  <comment :comment="comment" />
                </div>
                <div v-else>
                  <recomment :comment="comment" />
                </div>
              </v-col>
    • v-if, v-else로 다르게 보여줌

    • comment.hasNoParent으로 댓글인지, 대댓글인지 여부를 판단함. 이름이 쫌 이상하긴 하네요;;ㅎㅎ