슬기로운 개발생활

Spring Boot JPA 게시판 댓글 작성자만 수정, 삭제 가능하게 하기

by coco3o
반응형

이전 포스팅에 이어서 댓글 수정, 삭제는 댓글 작성자만 가능하게 구현한 내용을 포스팅 하겠다.

 

Spring Boot JPA 게시판 댓글기능 구현 - 댓글 수정 및 삭제

지난 포스팅에 이어 댓글 수정 및 삭제 기능을 구현하도록 하겠다. Spring Boot JPA 게시판 댓글기능 구현하기 - 댓글 작성 및 조회 게시판에서 댓글은 없어선 안될 중요한 부분이라고 생각한다. 그

dev-coco.tistory.com

필자는 이번 파트를 구현하면서 상당한 고역을 겪었다. 일단 구현내용부터보고 마저 얘기하도록 하자.


1. Controller

PostsIndexController

@RequiredArgsConstructor
@Controller
public class PostsIndexController {
    private final PostsService postsService;
    
    ...
    
    /* 글 상세보기 */
    @GetMapping("/posts/read/{id}")
    public String read(@PathVariable Long id, @LoginUser UserSessionDto user, Model model) {
        PostsResponseDto dto = postsService.findById(id);
        List<CommentResponseDto> comments = dto.getComments();

        /* 댓글 리스트 */
        if (comments != null && !comments.isEmpty()) {
            model.addAttribute("comments", comments);
        }
        /* 사용자 관련 */
        if (user != null) {
            model.addAttribute("user", user);

            /* 게시글 작성자 본인인지 확인 */
            if (dto.getUserId().equals(user.getId())) {
                model.addAttribute("writer", true);
            }
            /* 댓글 작성자 본인인지 확인 */
            for (int i = 0; i < comments.size(); i++) {
                //댓글 작성자 id와 현재 사용자 id를 비교해 true/false 판단
                boolean isWriter = comments.get(i).getUserId().equals(user.getId());
                log.info("isWriter? : " + isWriter);
                model.addAttribute("isWriter",isWriter);
            }
        }
        postsService.updateView(id); // views ++
        model.addAttribute("posts", dto);
        return "posts/posts-read";
    }
}

2. Mustache

comment/list.mustache

{{! Comments }}
<div class="card">
    <div class="card-header bi bi-chat-dots"> {{#comments.size}}{{comments.size}}{{/comments.size}} Comments</div>
    {{! 댓글내용 부분 }}
    <ul class="list-group-flush">
        {{#comments}}
            <li id="comments-{{id}}" class="list-group-item">
                <span>
                    <span style="font-size: small">{{nickname}}</span>
                    <span style="font-size: xx-small">{{createdDate}}</span>
                </span>
                {{#isWriter}}
                    <a type="button" data-toggle="collapse" data-target=".multi-collapse-{{id}}"
                       class="bi bi-pencil-square"></a> {{! 댓글 수정 버튼 }}
                    <a type="button" onclick="main.commentDelete({{postsId}},{{id}},{{userId}},{{user.id}})"
                       class="bi bi-x-square"></a> {{! 댓글 삭제 버튼 }}
                {{/isWriter}}

                {{! 댓글 내용 보기 }}
                <p class="collapse multi-collapse-{{id}} show">{{comment}}</p>

                {{! 댓글 내용 수정 }}
                <form class="collapse multi-collapse-{{id}}">
                    <input type="hidden" id="id" value="{{id}}">
                    <input type="hidden" id="postsId" value="{{postsId}}">
                    <input type="hidden" id="writerUserId" value="{{userId}}">
                    <input type="hidden" id="sessionUserId" value="{{#user}}{{user.id}}{{/user}}">
                    <div class="form-group">
                        <textarea class="form-control" id="comment-content" rows="3">{{comment}}</textarea>
                    </div>
                    <button type="button" id="btn-comment-update" class="btn btn-outline-primary bi bi-pencil-square"> 수정</button>
                </form>
            </li>
        {{/comments}}
    </ul>
</div>

수정폼과 삭제버튼에 댓글작성자id 번호와 현재 사용자(세션)id 번호를 받아 넘겨줬다.


3. app.js

    /** 댓글 수정 */
    commentUpdate : function (form) {
        const data = {
            id: form.querySelector('#id').value,
            postsId: form.querySelector('#postsId').value,
            comment: form.querySelector('#comment-content').value,
            writerUserId: form.querySelector('#writerUserId').value,
            sessionUserId: form.querySelector('#sessionUserId').value
        }
        console.log("commentWriterID : " + data.writerUserId);
        console.log("sessionUserID : " + data.sessionUserId);

        if (data.writerUserId !== data.sessionUserId) {
            alert("본인이 작성한 댓글만 수정 가능합니다.");
            return false;
        }

        if (!data.comment || data.comment.trim() === "") {
            alert("공백 또는 입력하지 않은 부분이 있습니다.");
            return false;
        }
        const con_check = confirm("수정하시겠습니까?");
        if (con_check === true) {
            $.ajax({
                type: 'PUT',
                url: '/api/posts/' + data.postsId + '/comments/' + data.id,
                dataType: 'JSON',
                contentType: 'application/json; charset=utf-8',
                data: JSON.stringify(data)
            }).done(function () {
                window.location.reload();
            }).fail(function (error) {
                alert(JSON.stringify(error));
            });
        }
    },

    /** 댓글 삭제 */
    commentDelete : function (postsId, commentId, commentWriterId, sessionUserId) {

        // 본인이 작성한 글인지 확인
        if (commentWriterId !== sessionUserId) {
            alert("본인이 작성한 댓글만 삭제 가능합니다.");
        } else {
            const con_check = confirm("삭제하시겠습니까?");

            if (con_check === true) {
                $.ajax({
                    type: 'DELETE',
                    url: '/api/posts/' + postsId + '/comments/' + commentId,
                    dataType: 'JSON',
                }).done(function () {
                    alert('댓글이 삭제되었습니다.');
                    window.location.reload();
                }).fail(function (error) {
                    alert(JSON.stringify(error));
                });
            }
        }
    }

댓글작성자id와 현재사용자id를 비교해 작성자가 아니면 댓글 수정 및 삭제하지 못하도록 후처리를 해주었다.


4. 결과 확인

다른 사람의 댓글 수정/삭제버튼 안보임
자신의 댓글 수정/삭제버튼 보임

여기까지는 문제가 없지만, 다음 그림을 보자.

다른 사용자의 댓글까지 수정/삭제 버튼이 보인다.

mustache는 단순히 화면에 데이터를 렌더링 하는 엔진이다.

Logic-less하고 true/false 여부만 판단하며, 항상 최종값만 넘겨받기 때문에, 부분적으로 true/false를 줄 방법은 없었다.

그래서 댓글란에 자신의 댓글이 존재하면 다른 사용자의 댓글이 있어도 true를 리턴해 전체 댓글에 버튼이 보이는 것이였다.

thymeleaf였으면 if문으로 간단히 할 수 있을텐데

부분적으로 버튼을 보여줄 다른 방법이 없을까 몇 날 며칠을 고민해봤으나 결국 찾지 못했고, 자바스크립트로 후처리를 해줬다. 

프로젝트를 완성하고 thymeleaf로 조금씩 바꾸면서 완성도를 더 높여야겠다.

반응형

블로그의 정보

슬기로운 개발생활

coco3o

활동하기