본문 바로가기
오늘의 배움(TIL)/트러블슈팅

[Trouble Shooting] 댓글, 게시글 관계 검증 문제 해결

by _silver 2024. 11. 24.

나의 첫 번째 [BugFixHub] 팀 프로젝트를 진행했다.
BugFixHub는 "Stack Overflow"를 모티브 하여 개발 정보를 공유하고 질문과 답변을 할 수 있는 저장소이다.
 
[GitHub 링크]

[BugFixHub] ERD DIAGRAM

우리는 각 파트들을 나누어 개발을 진행 했고, 그중 나는 Friend, Comment Like 파트를 맡게 되었다.
개발을 진행하면서 Comment Like 부분에서 문제가 발생되어 관련 내용을 Trouble Shooting을 진행하려고 한다.


 
▶ Postman API 호출 리스트

요청 URL 구분 요청사항 API 호출 결과 상태 코드
/posts/postId/comments/commentId/like 댓글
좋아요
좋아요 완료 댓글 좋아요ID, UserId, CommentId 반환 201, CREATED
이미 전송된 요청 이미 좋아요를 남긴 댓글입니다. 400, BAD REQUEST
댓글이 존재하지 않은 경우 댓글을 찾을 수 없습니다. 404, NOT FOUND
댓글과 게시글의 관계 오류 댓글ID와 게시글ID의 관계가 유효하지 않습니다. 400, BAD REQUEST
댓글
좋아요 취소
좋아요 취소  -
204 NO CONTENT
좋아요를 안한 경우 좋아요를 남기지 않은 댓글입니다. 400, BAD REQUEST

 

1. 배경

 1) 문제 상황:

  ① Comment Like(댓글 좋아요) 코드 구현 후 Postman으로 API 호출 결과를 확인하던 중,
게시글이 존재하지 않음에도 불구하고, 댓글에 좋아요를 누를 때 "이미 좋아요를 남긴 댓글입니다"라는 잘못된 오류 메시지가 반환됨.
  ② 이를 해결하기 위해 댓글과 게시글의 관계를 검증하는 "validateCommentAndPostRelation" 메서드를 추가했으나,
추가적인 문제 발생.
       -> 댓글이 존재하지 않는 경우에도 "게시글 ID와 댓글 ID의 관계가 유효하지 않습니다. " 오류 메시지가 우선적으로 표시됨.
 
▶ 수정 전 로직

// 게시글과 댓글 관계 검증 로직 추가

private void validateCommentAndPostRelation(Long commentId, Long postId) {
    if (!commentRepository.existsByIdAndPostId(commentId, postId)) {
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "게시글 ID와 댓글 ID의 관계가 유효하지 않습니다.");
    }
}
// 댓글 좋아요
@Override
@Transactional
public CommentLikeResDto likeComment(Long commentId, Long postId, Long userId) {
    // 게시글과 댓글 관계 검증
    validateCommentAndPostRelation(commentId, postId);


    Comment comment = commentRepository.findByIdAndDeletedFalse(commentId)
            .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "댓글을 찾을 수 없습니다."));

    
    if (comment.getUser().getId().equals(userId)) {
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "본인 댓글에는 좋아요를 남길 수 없습니다");
    }


    if (commentLikeRepository.existsByCommentIdAndUserId(commentId, userId)) {
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "이미 좋아요를 남긴 댓글입니다.");
    }


    User user = userRepository.findById(userId)
            .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "사용자를 찾을 수 없습니다."));



    CommentLike commentLike = new CommentLike(user, comment);
    commentLikeRepository.save(commentLike);

    return new CommentLikeResDto(commentLike);

}

 

2) 원인 분석

위 댓글 좋아요 로직에서 댓글 여부를 확인하기도 전에 게시글과 댓글 관계를 검증하는 "validateCommentAndPostRelation" 메서드가 먼저 실행되면서, 댓글이 삭제되거나 존재하지 않아도 메서드의 흐름을 종료하고 예외를 호출자에게 반환됨.

더보기

※ throw new 방식의 예외 처리

- 호출되는 즉시 현재 실행 중인 메서드의 흐름을 종료하고 예외를 호출자에게 보여준다.

- 예외를 발생시키는 메서드가 실행 순서보다 앞에 있다면, 이후의 중요한 검증 로직은 실행되지 않는다.

 
- Postman 호출 예시:
/posts/11/comments/commentId/like

 


2. 절정

위와 같은 문제를 해결하기 위해 게시글에 댓글 존재 여부를 확인 후, 게시글과 댓글간의 관계를 검증할 수 있도록 순서를 조정했다.
 


3. 결과

- 댓글 존재를 먼저 확인하여, 댓글과 게시글 관계검증은 댓글이 유효한 경우에만 실행될 수 있도록 순서 변경

 
▶ 수정 후 로직

// 게시글과 댓글 관계 검증(추가)
private void validateCommentAndPostRelation(Long commentId, Long postId) {
    if (!commentRepository.existsByIdAndPostId(commentId, postId)) {
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "게시글 ID와 댓글 ID의 관계가 유효하지 않습니다.");
    }
}


// 댓글 좋아요
@Override
@Transactional
public CommentLikeResDto likeComment(Long commentId, Long postId, Long userId) {


    1. 댓글 존재 여부 확인
    Comment comment = commentRepository.findByIdAndDeletedFalse(commentId)
            .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "댓글을 찾을 수 없습니다."));

    2. 게시글과 댓글 관계 검증
    validateCommentAndPostRelation(commentId, postId);

    if (comment.getUser().getId().equals(userId)) {
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "본인 댓글에는 좋아요를 남길 수 없습니다");
    }


    if (commentLikeRepository.existsByCommentIdAndUserId(commentId, userId)) {
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "이미 좋아요를 남긴 댓글입니다.");
    }
    .
    .
    .
    .
    .

 
위와 같이 코드 수정 후 IntelliJ 재 실행했고 Postman을 호출했다.
검증 순서를 조정한 후 정상적으로 호출되는 것을 확인했다.
 
1. 댓글을 찾을 수 없는 경우

 
2. 생성되지 않은 게시글에 댓글 좋아요를 누르는 경우