게시글 상세 페이지에서 댓글 목록을 함께 볼 수 있도록 해두었다.
그 댓글 목록에서 댓글을 수정하고 삭제하는 기능을 추가하겠다.
bootStrp이 제공하는 modal 형식을 사용하였다.
수정 버튼을 클릭 시 수정을 위한 폼이 나오도록..
https://getbootstrap.com/docs/5.1/components/modal/
해당 링크에서 코드를 복사하여 붙여넣기한 후에 코드를 수정하여 완성했다.
<!-- Button trigger modal -->
<button type="button"
class="btn btn-sm btn-outline-primary"
data-bs-toggle="modal"
data-bs-target="#comment-edit-modal"
data-bs-id="{{id}}"
data-bs-nickname="{{nickname}}"
data-bs-body="{{body}}"
data-bs-article-id="{{articleId}}">
수정
</button>
<!-- Modal -->
<div class="modal fade" id="comment-edit-modal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">댓글 수정</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form>
<!-- 닉네임 입력 -->
<div class="mb-3">
<label class="form-label">닉네임</label>
<input type="text" class="form-control form-control-sm" id="edit-comment-nickname">
</div>
<!-- 댓글 본문 입력 -->
<div class="mb-3">
<label class="form-label">댓글 내용</label>
<textarea type="text" class="form-control form-control-sm" rows="3" id="edit-comment-body"></textarea>
</div>
<!-- 히든 인풋 -->
<input type="hidden" id="edit-comment-id">
<input type="hidden" id="edit-comment-article-id">
<!-- 전송 버튼 -->
<button type="button" class="btn btn-outline-primary btn-sm" id="comment-update-btn">댓글 수정 완료</button>
</form>
</div>
</div>
</div>
</div>
"#comment-edit-modal"인 버튼 id값으로 값을 가져왔다.
<!--모달 이벤트 처리-->
<script>
//모달 요소 선택
const commentEditModal = document.querySelector("#comment-edit-modal");
//모달 이벤트 감지
commentEditModal.addEventListener("show.bs.modal",function(event) {
//트리거 버튼 선택
const triggerBtn = event.relatedTarget;
//데이터 가져오기
const id = triggerBtn.getAttribute("data-bs-id");
const nickname = triggerBtn.getAttribute("data-bs-nickname");
const body = triggerBtn.getAttribute("data-bs-body");
const articleId = triggerBtn.getAttribute("data-bs-article-id");
//데이터 반영
document.querySelector("#edit-comment-nickname").value = nickname;
document.querySelector("#edit-comment-body").value = body;
document.querySelector("#edit-comment-id").value = id;
document.querySelector("#edit-comment-article-id").value = articleId;
});
{
//수정완료 버튼 을 누르면 rest API를 호출하여 데이터를 수정
const commentUpdateBtn = document.querySelector("#comment-update-btn");
//클릭 이벤트 감지 및 처리
commentUpdateBtn.addEventListener("click", function() {
//수정 댓글 객체 생성
const comment = {
id: document.querySelector("#edit-comment-id").value,
nickname: document.querySelector("#edit-comment-nickname").value,
body: document.querySelector("#edit-comment-body").value,
article_id: document.querySelector("#edit-comment-article-id").value
}
//수정 REST api 호출 - fetch( )를 사용해서..
const url = "/api/comments/"+comment.id;
fetch(url, {
method: "PATCH", //팻치 요청
body: JSON.stringify(comment), //수정된 댓글 객체를 json으로 전달
headers: {
//바디에 담긴건 제이슨이야! 를 알려줌.
"Content-Type": "application/json"
}
} ).then(response => {
//http 응답 코드에 따른 메시지 출력
const msg = (response.ok) ? "댓글 수정 완료 ! " : "댓글 수정 실패 ..";
alert(msg);
//현재 페이지 새로고침
window.location.reload();
});
});
}
</script>
<button type="button"
class="btn btn-sm btn-outline-danger comment-delete-btn"
data-comment-id="{{id}}">
삭제
</button>
document.querySelector 는 제일 먼저 발견되는 것만 찾아낸다.
All 추가..
document.querySelectorAll은 여러개의 버튼이여도 다 찾아낸다.
수정버튼과 다르게 삭제버튼은 id값이 아닌 class값으로 가져왔다. ".comment-delete-btn"
<!-- 댓글 삭제 -->
<script>
//삭제 버튼 선택
const commentDeleteBtns = document.querySelectorAll(".comment-delete-btn");
//각 삭제 버튼의 이벤트 처리
commentDeleteBtns.forEach(btn => {
btn.addEventListener("click", (event) => {
//이벤트 발생 요소를 선택 - 몇번째 댓글의 삭제인지..
//클릭 이벤트가 발생된 버튼을 가져오기
const commentDeleteBtn = event.target;
//삭제 댓글 id 가져오기
const commentId = commentDeleteBtn.getAttribute("data-comment-id");
//삭제 api 호출 및 처리
const url = `/api/comments/${commentId}`; //백틱
fetch(url, {
method: "DELETE"
} ).then(response => {
if(!response.ok){
alert("댓글 삭제 실패");
return;
}
//삭제 성공시.. 화면에서 댓글 지우기
const target = document.querySelector(`#comments-${commentId}`);
target.remove();
});
});
});
</script>
btn.addEventListener("click", function() {
function을 아래처럼 변경해도 동일하다.
btn.addEventListener("click", (event) => {
지금까지 h2 DB를 사용했는데, h2는 메모리에서 동작하므로 서버 실행 시 마다 데이터가 초기화되곤 했었다.
이제 외부 DB인 postgre SQL을 연동해서 서버가 꺼져도 데이터가 유지되도록 해보겠다.
build.gradle
runtimeOnly 'org.postgresql:postgresql'
application.properties
spring.datasource.url=jdbc:postgresql://localhost:5432/firstproject_db
spring.datasource.username= 비밀~~
spring.datasource.password= 비밀~~
spring.datasource.data=classpath:/data.sql
spring.datasource.initialization-mode=always
spring.jpa.hibernate.ddl-auto=create-drop
postgre의 기본 주소와 만들어둔 디비를 설정해준다.
사용자명
비밀번호
데이터를 초기화해줄 코드 정보
always 해주면 서버 실행 시 코드 정보인 data.sql을 항상 수행
create-drop 서버가 켜질때 테이블과 데이터를 생성하고 서버가 꺼질때 모두 삭제한다.
기존과 동일하게 서버를 껐다 키면 데이터가 data.sql로 초기화된다.
이제는 서버가 꺼져도 데이터를 유지하기 위해서 아래처럼 변경해준다.
spring.datasource.initialization-mode=never
spring.jpa.hibernate.ddl-auto=update
always => never
create-drop =>update