요약

문제 1

  1. 인증 게시판과 플로깅 구인 게시판에서 동일하게 사용하는 Comment 도메인이 있음.
  2. 각 게시판과 Comment 사이에 연관관계를 두었기 때문에 Comment 엔티티에 불필요한 컬럼 발생
  3. Comment 엔티티에 Enum 을 두어 어떤 게시판에서 달린 댓글인지 확인 할 수 있도록 함.

문제 2

  1. 인증 게시판과 플로깅 구인 게시판에서 동일하게 사용하는 댓글 도메인이 있음.
  2. 게시판 종류에 따라 댓글 생성 로직이 달라 댓글 조회 로직을 if 분기로 처리
  3. if 분기가 반복적으로 존재하기에 전략 패턴 적용

개요

과거 댓글기능을 넣는 과정에서, 댓글-및-대댓글-구현기 와 같이 구현을 했었다. 이 당시 서로 다른 게시판에서 댓글에 대해 생성, 조회, 삭제 해야했기 때문에 생성 및 조회하는 댓글이 어떤 게시판에 해당하는 댓글인지 확인을 해야했다. 그 해결법으로 무지성 if 문을 통해 각 게시판에 대한 분기를 처리하면서 코드가 지저분해졌다. 그래서 리팩토링 해보았다.

크게 두가지 문제가 있었는데

  1. 댓글을 생성하는 addComment 에서 경우 게시판 종류에 따라서 Comment 정적 팩토리 메서드를 호출해야기 때문에 if 분기가 반복적으로 있었다.
package mokindang.jubging.project_backend.comment.service;

@Service
@RequiredArgsConstructor
public class CommentService {

	  //...
    @Transactional
    public BoardIdResponse addComment(final Long memberId, final BoardType boardType, final Long boardId,
                                      final CommentCreationRequest commentCreationRequest) {
        Member writer = memberService.findByMemberId(memberId);
        LocalDateTime now = LocalDateTime.now();
        **if (boardType == BoardType.RECRUITMENT_BOARD)** {
						//구인 게시글 조회
            RecruitmentBoard board = recruitmentBoardService.findByIdWithOptimisticLock(boardId);
						// 댓글을 생성하고 구인 게시글과 연관관계를 맺는 메서드 호출
            Comment comment = Comment.createOnRecruitmentBoardWith(board, commentCreationRequest.getCommentBody(), writer, now);
            commentRepository.save(comment);
            return new BoardIdResponse(boardId);
        }

        **if (boardType == BoardType.CERTIFICATION_BOARD)** {
						//인증 게시글 조회
            CertificationBoard board = certificationBoardService.findById(boardId);
						//댓글을 생성하고 인증 게시글과 연관관계를 맺는 메서드 호출
            Comment comment = Comment.createOnCertificationBoardWith(board, commentCreationRequest.getCommentBody(), writer, now);
            commentRepository.save(comment);
            return new BoardIdResponse(boardId);
        }
        throw new IllegalArgumentException("존재 하지 않는 게시판에 대한 접근입니다.");
    }
//...
}
  1. 댓글 리스트를 조회하는 selectComments 는 게시판 타입에 따라서 해당하는 Comment 리스트를 불러온다.
package mokindang.jubging.project_backend.comment.service;

@Service
@RequiredArgsConstructor
public class CommentService {

//...
  @Transactional
    public MultiCommentSelectionResponse selectComments(final Long memberId, final BoardType boardType, final Long boardId) {
        if (boardType == BoardType.RECRUITMENT_BOARD) {
            List<Comment> commentsByRecruitmentBoard = commentRepository.findCommentsByRecruitmentBoardId(boardId);
            Member member = memberService.findByMemberId(memberId);
            RecruitmentBoard board = recruitmentBoardService.findByIdWithOptimisticLock(boardId);
						//회원에 대해 게시판에 있는 댓글에 대한 검증 로직이 이루어짐
            boolean writingCommentPermission = board.isSameRegion(member.getRegion());
            boolean isWriterParticipatedIn = board.isParticipatedIn(memberId);
            return new MultiCommentSelectionResponse(convertToRecruitmentBoardCommentSelectionResponse(memberId, commentsByRecruitmentBoard, board, isWriterParticipatedIn),
                    writingCommentPermission);
        }

        if (boardType == BoardType.CERTIFICATION_BOARD) { //검증 없이 조회 가능
            List<Comment> commentsByCertificationBoard = commentRepository.findCommentsByCertificationBoardId(boardId);
            CertificationBoard board = certificationBoardService.findById(boardId);
            return new MultiCommentSelectionResponse(convertToCertificationBoardCommentSelectionResponse2(memberId, commentsByCertificationBoard, board),
                    true);
        }
        throw new IllegalArgumentException("존재 하지 않는 게시판에 대한 접근입니다.");
    }

    private List<CommentSelectionResponse> convertToRecruitmentBoardCommentSelectionResponse(final Long memberId, final List<Comment> commentsByRecruitmentBoard, final RecruitmentBoard board, final boolean isWriterParticipatedIn) {
        return commentsByRecruitmentBoard.stream()
                .map(comment -> new CommentSelectionResponse(comment, memberId, board.isSameWriterId(comment.getWriter().getId()), isWriterParticipatedIn))
                .collect(Collectors.toUnmodifiableList());
    }

    private List<CommentSelectionResponse> convertToCertificationBoardCommentSelectionResponse2(final Long memberId, final List<Comment> commentsByRecruitmentBoard, final CertificationBoard board) {
        return commentsByRecruitmentBoard.stream()
                .map(comment -> new CommentSelectionResponse(comment, memberId, board.isSameWriterId(comment.getWriter().getId()), false))
                .collect(Collectors.toUnmodifiableList());
    }
//...
}