이번 글에서는 댓글 CRUD기능 중 수정(U)과 삭제(D)에 관한 글을 써보려고 합니다.
부족해도 이해하고 봐주세요... :)
1. html에 수정 버튼 만들기
<div class="reply-content">
<h5><span th:text="${reply.member.name}"></span> :
<span th:text="${reply.content}"></span><br>
<span th:text="${#dates.format(reply.reply_date, 'yyyy-MM-dd HH:mm')}"></span></h5>
<button type="button" th:data-reply-seq="${reply.replySeq}" th:data-reply-member-id="${reply.member.id}"
th:data-login-user-id="${loginUser.id}" class="detail-replyedit-btn"
onclick="replyEdit(this)">댓글수정</button><br>
<button type="button" th:attr="data-reply-seq=${reply.replySeq}"
class="detail-replylike-btn" onclick="replyLike(this)">좋아요</button>
<span>좋아요 수 : <span th:text="${reply.likes}"></span></span>
<button type="button" th:data-reply-seq="${reply.replySeq}" th:data-reply-member-id="${reply.member.id}"
th:data-login-user-id="${loginUser.id}" class="detail-replydelete-btn"
onclick="replyDelete(this)">댓글삭제</button>
<!-- th:attr은 속성 이름과 값을 동적으로 설정할 수 있게 한다. (JavaScript와 상호작용할 때 유용) -->
</div>
<button type="button" th:data-reply-seq="${reply.replySeq}" th:data-reply-member-id="${reply.member.id}"
th:data-login-user-id="${loginUser.id}" class="detail-replyedit-btn"
onclick="replyEdit(this)">댓글수정</button><br>
- data-reply-seq 속성은 각 댓글의 고유 식별자인 replySeq 값을 담습니다.
- data-reply-member-id 속성은 댓글 작성자의 ID를 담습니다.
- data-login-user-id 속성은 현재 로그인한 사용자 ID를 담습니다.
- onclick 속성은 버튼이 클릭되었을 때 실행할 JavaScript 함수(replyEdit)를 지정합니다.
- replyEdit(this)에서 this는 현재 클릭된 버튼 요소를 가리키며, replyEdit 함수에서 data-reply-seq, data-reply-member-id, data-login-user-id를 이용할 수 있게 해줍니다.
2. 버튼 클릭 시 호출할 함수 작성 (JavaScript)
// 댓글 수정
function replyEdit(buttonElement) {
// 댓글 작성자 id와 현재 로그인한 사용자 id 가져오기
var replySeq = $(buttonElement).attr("data-reply-seq"); // 댓글 seq
var replyMemberId = $(buttonElement).attr("data-reply-member-id"); // 댓글 작성자 ID
var loginUserId = $(buttonElement).attr("data-login-user-id"); // 로그인한 사용자 ID
// 댓글 작성자와 로그인한 사용자가 일치하는지 확인
if(replyMemberId === loginUserId) {
swal.fire({
title: '댓글 수정',
input: 'text',
inputLabel: '수정할 댓글을 입력하세요.',
inputPlaceholder: '댓글 내용을 입력해 주세요.',
showCancelButton: true,
confirmButtonText: '수정하기',
cancelButtonText: '취소',
inputValidator: (value) => {
if(!value) {
return '수정할 댓글 내용을 입력해야 합니다.';
}
}
}).then((result) => {
if(result.isConfirmed) {
var updatedReply = result.value;
$.ajax({
url: '/update-reply', // controller 요청 url
type: 'PUT',
contentType: 'application/json',
data: JSON.stringify({
replySeq: replySeq,
content: updatedReply
}),
success: function(response) {
swal.fire({
title: '수정 완료',
text: '댓글을 성공적으로 수정하였습니다.',
icon: 'success',
confirmButtonText: '확인'
}).then(() => {
location.reload();
});
},
error: function(xhr, status, error) {
swal.fire({
title: '수정 실패',
text: '서버에서 오류가 발생했습니다. 다시 시도해 주세요.',
icon: 'error',
confirmButtonText: '확인'
});
}
});
}
});
} else { // 댓글 작성자와 수정버튼을 누른 사용자가 다를경우
swal.fire({
title: '수정 불가',
text: '댓글 작성자만 수정이 가능합니다.',
icon: 'warning',
confirmButtonText: '확인'
});
}
}
- buttonElement에서 댓글 시퀀스(replySeq), 댓글 작성자 ID(replyMemberId), 로그인한 사용자 ID(loginUserId)를 data 속성에서 가져옵니다.
- if(replyMemberId === loginUserId) { : 댓글 작성자 ID와 로그인 사용자 ID가 일치하면 댓글 수정 기능을 제공하고, 일치하지 않으면 수정이 불가능하다는 알림을 표시합니다.
- SweetAlert2를 사용하여 댓글을 수정할 수 있는 입력 창을 표시하고, inputValidator: (value) => { 로 입력값이 없을 경우 return '수정할 댓글 내용을 입력해야 합니다.'; 경고 메시지를 띄웁니다.
- 수정된 댓글 내용을 서버로 전송하기 위해 PUT 요청을 사용하여 /update-reply URL에 AJAX로 데이터를 전송합니다.
- 성공 시 SweetAlert2로 수정 완료 메시지를 띄우고, 페이지를 새로 고칩니다.
- 실패 시 에러 메시지를 표시합니다.
3. Controller 구현
// 댓글 수정 처리
@PutMapping("/update-reply")
public ResponseEntity<String> updateReply(@RequestBody Map<String, Object> request) {
try {
// 요청받은 데이터 추출
int replySeq = Integer.parseInt(request.get("replySeq").toString());
String updatedReply = request.get("content").toString();
replyService.updateReply(replySeq, updatedReply);
return ResponseEntity.ok("댓글이 성공적으로 수정되었습니다.");
} catch(Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).
body("댓글 수정에 실패했습니다. 다시 시도해 주세요.");
}
}
- @PutMapping은 HTTP PUT 요청을 처리하는 메서드임을 나타냅니다. PUT 요청은 주로 리소스를 업데이트하는 데 사용됩니다.
- @RequestBody Map<String, Object> request : Map<String, Object>로 받는 이유는, 클라이언트가 JSON 형식으로 데이터를 보내며, replySeq와 content를 포함한 다양한 데이터를 전송할 수 있기 때문입니다. 각 데이터 항목은 String 타입의 키와 Object 타입의 값으로 매핑됩니다.
- Integer.parseInt(request.get("replySeq").toString()) : Map에서 replySeq 값을 가져오고, 이를 Integer.parseInt()로 정수로 변환합니다.
- request.get("content").toString() : Map에서 content 값을 가져옵니다. 이 값은 수정할 댓글의 새 내용입니다.
+ Service 메서드
@Override
@Transactional
public void updateReply(int replySeq, String content) {
Optional<Reply> beforeReply = replyRepo.findById(replySeq);
if (beforeReply.isPresent()) {
Reply reply = beforeReply.get();
reply.setContent(content); // 댓글 내용 수정
replyRepo.save(reply); // 수정된 댓글 저장
} else {
throw new IllegalArgumentException("잘못된 댓글 번호: " + replySeq); // 댓글이 없으면 예외 발생
}
}
+++ 날짜도 수정하려면 reply.setReply_date(new Date()) 를 추가 하시면 됩니다.
테스트
'SpringBoot 프로젝트' 카테고리의 다른 글
Spring Boot - 댓글 좋아요 기능 구현하기 (2) | 2024.11.23 |
---|---|
Spring Boot - 댓글 CRUD기능 구현하기 (3) (0) | 2024.11.22 |
Spring Boot - 댓글 CRUD기능 구현하기 (1) (2) | 2024.11.21 |
Spring Boot - 이미지 업로드 및 삭제 (0) | 2024.11.21 |
Spring Boot - 리뷰 CRUD기능 구현하기 (4) (0) | 2024.11.19 |