FireDrago
[bobzip] Ajax 비동기 요청을 통한 댓글 수정 본문
댓글 수정 (클라이언트)
댓글 수정로직이 가장 어려웠다. 크게 두가지 문제가 있었다.
1. 페이지네이션이 적용된 상태에서 어떻게 수정폼을 띄워야 할까?
2. 댓글 수정후, 전체 댓글을 다시 로드하면, 수정한 댓글이 있는 페이지를 표시해주는 것이 복잡하다.

댓글은 자바스크립트에의해 동적으로 추가된다.
처음에는 '수정' 버튼을 눌렀을때, 댓글 내용이 <input> 태그로 변경하도록 만드려고 했다.
원본 댓글 아래에 수정 폼을 삽입하는 방식이 더 편리하다고 생각하여,
수정 버튼을 누르면 원본 댓글 밑에 수정 폼이 나타나도록 만들었다.
function editComment(commentId, currentText) {
// 기존 폼이 있으면 제거
$('#edit-form').remove();
const editFormHtml = `
<form id="edit-form" class="mt-3">
<textarea id="edit-comment-text" class="form-control mb-2">${currentText}</textarea>
<button type="button" class="btn btn-primary" onclick="submitEdit(${commentId})">수정하기</button>
<button type="button" class="btn btn-secondary" onclick="cancelEdit()">닫기</button>
</form>
`;
// 댓글 아래에 수정 폼 추가
$(`#comment-${commentId}`).append(editFormHtml);
}
1. 기존 수정폼이 있는경우, 폼을 먼저 제거한다.
2. 폼 HTML 태그를 만든뒤, 수정폼을 추가해준다.
3. 수정폼이 submitEdit() 메서드를 통해 수정요청을 서버로 전달한다.
function submitEdit(commentId) {
const updatedText = $('#edit-comment-text').val();
$.ajax({
url: `/reply/edit/${commentId}`,
method: "POST",
contentType: "application/x-www-form-urlencoded",
data: {
comment: updatedText
},
success: function(response) {
// 댓글 내용을 업데이트
$(`#comment-${commentId} #comment-text`).text(updatedText);
// 수정 폼 제거
$('#edit-form').remove();
},
error: function(xhr) {
if (xhr.status == 401) {
alert(xhr.responseText);
} else {
alert("댓글 수정중 문제가 발생했습니다.")
}
}
});
}
댓글 작성과 조회에서 본 AJAX 요청이므로 어렵지 않았다.
한 가지 다른 점은 댓글 수정이 성공한 경우 서버에 댓글 조회 요청을 다시 보내지 않는다.
수정된 댓글의 텍스트 HTML 내용만 수정하는 것이 더 편리하다고 생각했다.
어차피 댓글 내용은 서버 측에서 수정할 것이므로 클라이언트 화면만 조작했다.
댓글 수정 (서버 코드)
@PostMapping("/edit/{commentId}")
public ResponseEntity<String> editReply(
@PathVariable("commentId") Long commentId, @ModelAttribute("comment") String comment, HttpSession session) {
Member loginMember = (Member) session.getAttribute(LoginConst.LOGIN);
try {
replyService.editReply(commentId, comment, loginMember);
return ResponseEntity.ok("댓글 수정 완료");
} catch (UnauthorizedAccessException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(e.getMessage());
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("댓글 수정 중 오류가 발생했습니다.");
}
}
컨트롤러단에서 리팩토링을 거쳤다.
댓글 작성, 댓글 조회시 DB 쿼리마다 여러번의 커밋이 발생했다.
컨트롤러에서 각각의 독립된 서비스 객체의 트랜잭션 로직을 요청했기 때문이었다.
컨트롤러에서 서비스에 호출하는 메서드를 최대한 줄이고,
커밋이 발생하는 작업은 서비스에서 한번에 처리하도록 리팩토링했다.
@Transactional
public void editReply(Long commentId, String comment, Member loginMember) throws UnauthorizedAccessException {
Reply reply = replyRepository.findById(commentId)
.orElseThrow(() -> new IllegalArgumentException("댓글을 찾을 수 없습니다."));
if (loginMember == null || !reply.getMember().equals(loginMember)) {
throw new UnauthorizedAccessException("댓글 수정");
}
reply.update(comment);
}
서비스단에서는,
1. 수정 요청된 댓글을 찾는다.
2. 댓글 작성자와 현재 로그인된 유저가 동일한지 검사하여 UnauthorizedAccessException 예외를 발생시킨다.
3. Reply 엔티티에 수정로직을 호출하여 업데이트 실시한다.
@Entity
@Getter
public class Reply extends BaseEntity {
@Id
@GeneratedValue
@Column(name = "reply_id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "recipe_id")
private Recipe recipe;
@Column(length = 400)
private String comment;
public Reply() {}
@Builder
public Reply(Member member, Recipe recipe, String comment) {
this.member = member;
this.recipe = recipe;
this.comment = comment;
}
public void update(String comment) {
this.comment = comment;
}
}
'프로젝트' 카테고리의 다른 글
| [bobzip] nginx Request Entity Too Large 오류 (0) | 2024.08.02 |
|---|---|
| [bobzip] QueryDsl 활용하여 냉장고 재료로 레시피 검색하기 (0) | 2024.07.11 |
| [bobzip] Ajax 비동기 요청을 통한 댓글 작성 (0) | 2024.07.03 |
| [bobzip] AJAX 비동기 요청을 통한 댓글 조회 (0) | 2024.07.02 |
| [bobzip] 다중 MultipartFile 이미지를 포함한 엔티티 수정하기 (0) | 2024.06.24 |