[Web] 최종프로젝트(4) 프론트단 무한댓글 구현

hyewon jeong·2023년 2월 20일
0

web

목록 보기
6/24
post-thumbnail

🎈 현 블로그는 벡엔드 입장에서 이가 없이 잇몸으로 구현한 포론트라는~ 점 ! ㅎㅎ!!! 명시합니다.

개발 진행에 따른 기록 작성(★★★★★)

1. 엔티티 재 설계

https://velog.io/@wonizizi99/TIL-23.02.17
2.17 댓글 보여주기 구현을 했으나 자세히 보니 부모댓글도 한칸씩 밀려 들어가는 것을 볼수 있었다.

📌 댓글 보여주기

1차시도


결과: ....부모댓글은 나오지만 대댓글 구현이 쉽지 않다. ㅠㅠ 값을 불러오는데서 for문 안에서만 문제가 생기는 건 뭔지..

2차시도

결과: 자바스크립트에서 depth를 만들어 들여쓰기 구현등, 재귀함수 사용하여 1차 구현 >.<ㅎ

3차시도

원인 : 2차시도의 문제점은 부모댓글도 함께 들여쓰기가 되어 자식댓글처럼 보였다.
결과 : 부모댓글은 첫줄에 있고 , 자식댓글만 한칸씩 들여쓰기를 하여 계층구조 구현
해결 방법 : 서버쪽에서 댓글의 depth를 구현하여 깊이만큼 들여쓰기를 하여 계층구조를 표현 할 수 있었다.
서비스 로직이 comment 댓글 엔티티 하나로 대댓글 구현하여
재귀함수로 댓글을 보여주는 형식이 적용 되었다.
재귀로 사용할 수 있었던것 대댓글이 몇백개 달리지는 않을것을 예상하여 적용할 수 있었다.

알게 된점 : 벡엔드만 할때는 뎁스없이도 계층구조로 볼수 있었지만 , 프론트를 위한 값도 벡엔드에서 구현해야 한다는 것을 알수 있었다.

댓글 보여주기 부분 코드

//------------------------ 댓글 보여주기 ------------------------

function showComment(commentList, depth) {
                if (commentList.length === 0) {
                    return; //탈출조건 
                }

                for (let index = 0; index < commentList.length; index++) {
                    const singleComment = commentList[index];
                    const depth = singleComment['depth']

                    let temp_html = makeCommentHtml(singleComment,depth)
                    $('#commentShow').append(temp_html)
                    showComment(singleComment['children'], depth);
                }

            }
function makeCommentHtml(singleComment,depth) {
    var space = ""
    var point = ""
    if(depth>=2){
        point ="ㄴ "
    }
    for (let i = 1; i < depth; i++) {
            space = space + "&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp"
        }
    var nickName = singleComment['nickName']
    return `<div class="d-flex">                       
                        <div class="ms-3">
                            <div class="fw-bold">${space}${point}작성자:${singleComment['nickName']}</div>
                            <div class="text-black-50">${space}${singleComment['comments']}</div> 
                            <p class="text-black-50">${space}${singleComment['createdDate']}
                                <button name="creatRe" id="reply_${singleComment['id']}" >답글</button>
                                <button name="editComment" id ="edit_${singleComment['id']}">수정</button>
                                <button name="delComment" id ="comment_${singleComment['id']}">삭제</button>
                                
                                    
                                <span style="display: none ;" id="toggleEdit_${singleComment['id']}">
                                <textarea id="editCommentContent_${singleComment['id']}"></textarea> 
                                <button name="saveEdit" id="commentEdit_${singleComment['id']}">댓글수정</button>
                                    </span>

                                <span style="display: none ;" id="toggleRe_${singleComment['id']}">
                                <textarea id="replyCommentContent_${singleComment['id']}"></textarea> 
                                <button name="saveRe" id="commentSave_${singleComment['id']}">답글작성</button>
                                    </span>
                                    <div class="d-flex mt-4">
                                    <div class="ms-3" id='commentReply_${singleComment['id']}'>
                                                            
                                    </div>
                            </p>
                        </div>
                    </div>`
    }

전체코드

<script>
//-------- 로드실행---------------------------------------- 
$(document).ready(function () {
    var param = document
        .location
        .href
        .split("?");
    console.log(param[1])

    var settings = {
        "url": "http://localhost:8080/api/contact/inquiries/" + param[1],
        "method": "GET",
        "timeout": 0
    };
    //----------------------------------agax --------------------------- 필요변수 여기에 선언
    $
        .ajax(settings)
        .done(function (response) {
            console.log(response);
            let inquiryId = response['id']
            let title = response['title']
            let content = response['content']
            let createdDate = response['createdDate']
            let username = response['username']
            let nickName = response['nickName']



            //------------------------------ 게시글 보여주기 -----------------------------------
            let temp_html = `<div class="container" id= inquiryBox>
                                <table class="table table-hover" width="1000" id="textBox">
                                    <tr>
                                        <td>제목 </td>
                                        <td colspan="4" align="left">${title}</td>
                                        </tr>
                                    <tr align="center">
                                        <td>작성일</td>
                                        <td>${createdDate}</td>
                                        <td>작성자</td>
                                        <td>${nickName}</td>
                                    </tr>
                                    <tr height="300">
                                        <td colspan="5" align="left">${content}</td>
                                    </tr>
                                </table>
                                    <button type="button" class="btn btn-outline-secondary border">
                                        <a href="contactPageIndex-inquiry.html">목록보기</a>
                                    </button>
                                    <button type="button" class="btn btn-outline-secondary border" id="b-edit">
                                        <a href="contactEdit-inquiry.html?${inquiryId}">수정</a>
                                    </button>
                                    <button type="button" class="btn btn-outline-secondary border" name ='b-delete'>
                                        <a href="contactPageIndex-inquiry.html">삭제</a>
                                    </button>
                                    <section class="mb-5">
                                        <div class="card bg-light">
                                            <div class="card-body"  id = "commentShow">
                                                <!-- Comment form-->
                                                <form class="mb-4"><textarea id ="t-commentSave"class="form-control" rows="3" placeholder="댓글을 남겨주세요"></textarea> 
                                                    <button type="button" name='b-commentSave'>댓글등록</button></form>
                                            
                                            </div>
                                        </div>
                                        </section>
                                </div>`

            $('#t-inquiry').append(temp_html)

            showComment(response['comments'], 0)
        //------------------------ 댓글 보여주기 ------------------------

            function showComment(commentList, depth) {
                            if (commentList.length === 0) {
                                return; //탈출조건 
                            }

                            for (let index = 0; index < commentList.length; index++) {
                                const singleComment = commentList[index];
                                const depth = singleComment['depth']

                                let temp_html = makeCommentHtml(singleComment,depth)
                                $('#commentShow').append(temp_html)
                                showComment(singleComment['children'], depth);
                            }

                        }
            function makeCommentHtml(singleComment,depth) {
                var space = ""
                var point = ""
                if(depth>=2){
                    point ="ㄴ "
                }
                for (let i = 1; i < depth; i++) {
                        space = space + "&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp"
                    }
                var nickName = singleComment['nickName']
                return `<div class="d-flex">                       
                                    <div class="ms-3">
                                        <div class="fw-bold">${space}${point}작성자:${singleComment['nickName']}</div>
                                        <div class="text-black-50">${space}${singleComment['comments']}</div> 
                                        <p class="text-black-50">${space}${singleComment['createdDate']}
                                            <button name="creatRe" id="reply_${singleComment['id']}" >답글</button>
                                            <button name="editComment" id ="edit_${singleComment['id']}">수정</button>
                                            <button name="delComment" id ="comment_${singleComment['id']}">삭제</button>
                                            
                                                
                                            <span style="display: none ;" id="toggleEdit_${singleComment['id']}">
                                            <textarea id="editCommentContent_${singleComment['id']}"></textarea> 
                                            <button name="saveEdit" id="commentEdit_${singleComment['id']}">댓글수정</button>
                                                </span>

                                            <span style="display: none ;" id="toggleRe_${singleComment['id']}">
                                            <textarea id="replyCommentContent_${singleComment['id']}"></textarea> 
                                            <button name="saveRe" id="commentSave_${singleComment['id']}">답글작성</button>
                                                </span>
                                                <div class="d-flex mt-4">
                                                <div class="ms-3" id='commentReply_${singleComment['id']}'>
                                                                        
                                                </div>
                                        </p>
                                    </div>
                                </div>`
                }
// ----------------------------------댓글보여주기 끝--------------------------------------------
            });
// ----------------------------------ajax get 끝--------------------------------------------
});

// ----------------------------------로드시 실행되는부분 끝-------------------------------------------

📌 해당 버튼클릭시 댓글쓰기


// ----------------[해당버튼 클릭시 댓글쓰기]---------------

$('#t-inquiry').on("click", "button[name='b-commentSave']", function () {
    var param = document.location.href.split("?");
    var settings = {
        "url": "http://localhost:8080/api/comments/inquiry/" + param[1],
        "method": "POST",
        "timeout": 0,
        "headers": {
            "Authorization": localStorage.getItem('accessToken'),
            "Content-Type": "application/json"
        },
        "data": JSON.stringify({
            "comments": $('#t-commentSave').val(),

        }),
    };
    $.ajax(settings).done(function (response) {
        console.log(response);
        alert(response)
        window.location.reload()
    });
})

📌 해당 버튼 클릭시 댓글삭제

// -----[해당 버튼 클릭시 댓글삭제]-----------

$('#t-inquiry').on("click", "button[name='delComment']", function(){
    var id_by_name = $(this).attr('id')
    console.log(id_by_name)
    var commentId = id_by_name.split("_")[1]
    console.log(commentId)
    var settings = {
    "url": "http://localhost:8080/api/comments/"+commentId+"/inquiry",
    "method": "DELETE",
    "timeout": 0,
    "headers": {
        "Authorization": localStorage.getItem('accessToken')
    },
};

$.ajax(settings).done(function (response) {
    console.log(response);
    alert(response)
    window.location.reload();

}).fail(function(response){
    console.log(response.responseJSON);
    if(response.responseJSON.statusCode === 403){
        alert(response.responseJSON.message)
    }
});
})

📌 해당 버튼 클릭시 답글 수정 창 열림 및 수정 요청

// -----[해당 버튼 클릭시 답글 수정 창 나옴]-------------------

$('#t-inquiry').on("click", "button[name='editComment']", function(){
var id_by_name = $(this).attr('id')
var commentId =id_by_name.split("_")[1]
$("#toggleEdit_"+commentId).toggle();
})
// ---------------------------------------------------------

// -----[해당 버튼 클릭시 댓글수정 요청]----------------------
$('#t-inquiry').on("click", "button[name='saveEdit']", function(){    
    var id_by_name = $(this).attr('id')
    var commentId = id_by_name.split("_")[1]
    var settings = {
"url": "http://localhost:8080/api/comments/"+commentId+"/inquiry",
"method": "PUT",
"timeout": 0,
"headers": {
"Authorization": localStorage.getItem('accessToken'),
"Content-Type": "application/json"
},
"data": JSON.stringify({
"comments": $('#editCommentContent_'+commentId).val()
}),
};

$.ajax(settings).done(function (response) {
console.log(response);
alert(response)
window.location.reload();
}).fail(function(response){
console.log(response.responseJSON);
if(response.responseJSON.statusCode === 403){
alert(response.responseJSON.message)
window.location.reload();
}
if(response.responseJSON.statusCode === 404){
    alert("다른 유저의 댓글은 수정할 수 없습니다.")
    window.location.reload();
}
});
})

📌 해당 버튼 클릭시 답글적는창 열림 및 해당 버튼 클릭시 답글DB로 보냄

// -----[해당 버튼 클릭시 답글적는창 나옴]-------------------


$('#t-inquiry').on("click", "button[name='creatRe']", function(){
    var id_by_name = $(this).attr('id')
    console.log(id_by_name)
    var commentId =id_by_name.split("_")[1]
    console.log("★"+commentId)                                    
    $("#toggleRe_"+commentId).toggle();

})
// ---------------------------------------------------------

// -----[해당 버튼 클릭시 답글DB로 보냄]-------------------todo : 답글보여지는 위치에서 에러남 
$('#t-inquiry').on("click", "button[name='saveRe']", function(){
    var param = document.location.href.split("?");
    console.log(param[1])

    var id_by_name = $(this).attr('id')
    console.log(id_by_name)
    var commentId = id_by_name.split("_")[1]
    console.log("☆"+commentId)
    var settings = {
"url": "http://localhost:8080/api/comments/inquiry/"+param[1],
"method": "POST",
"timeout": 0,
"headers": {
    "Authorization": localStorage.getItem('accessToken'),
    "Content-Type": "application/json"
},
"data": JSON.stringify({
    "comments": $('#replyCommentContent_'+commentId).val(),
    "parentId": commentId
}),
};

$.ajax(settings).done(function (response) {
console.log(response);
alert(response)
window.location.reload();
}).fail(function(response){
console.log(response.responseJSON);
if(response.responseJSON.statusCode === 403){
    alert(response.responseJSON.message)
}
});
})

벡엔드단 로직

commentService 댓글 저장로직
에서 뎁스와 parentId가 정해진다.
그럼으로 부모댓글과 자식댓글로 나뉘어 지고, 부모댓글은 자식댓글들을 가지게 된다.
commentService

  @Override
  public void saveInquiryComment(Long inquiryId,
      CreateContactCommentRequest createContactCommentRequest,
      String username) {
    String nickName = userService.nickNameFindByUsername(username);
    if (!inquiryRepository.existsById(inquiryId)) {
      throw new CustomException(ExceptionStatus.BOARD_NOT_EXIST);
    } else {
      /**부모댓글이 있는 경우 - 대댓글 등록. 즉 자식 댓글이 됨 */
      ContactComment parent = null;

      if (createContactCommentRequest.getParentId() != null) {
        parent = contactCommentRepository.findById(createContactCommentRequest.getParentId())
            .orElseThrow(
                () -> new CustomException(ExceptionStatus.COMMENT_NOT_EXIST)
            );
        /** 부모 댓글과 자식 댓글의 게시글 아이디가 같은지 확인*/
        if (!parent.getInquiryId().equals(inquiryId)) {
          throw new CustomException(ExceptionStatus.WRONG_POST_ID);
        }
        int depth = parent.getDepth();
        ContactComment contactComment = createContactCommentRequest.toEntity(inquiryId, username,
            nickName, parent,depth);
        // ContactComment contactComment = new ContactComment(comments,inquiryId,username,parent);
        depth = contactComment.getDepth()+1;
        contactComment.getParent().setId(createContactCommentRequest.getParentId());
        contactComment.setDepth(depth);
        contactCommentRepository.save(contactComment);

        /**부모댓글이 없는 경우 - 댓글 등록*/
      } else {
        int depth = 1;
        //   ContactComment contactComment = new ContactComment(comments,inquiryId,username,parent);
        ContactComment contactComment = createContactCommentRequest.toEntity(inquiryId, username,
           nickName, parent, depth);
        contactCommentRepository.save(contactComment);
      }
    }
  }
profile
개발자꿈나무

0개의 댓글