728x90
저번에 작성한 댓글 기능 구현 코드를 REST API 규칙에 맞게 수정하도록한다.
* 이전 댓글 구현 글
https://black-mint.tistory.com/35
[Spring Boot] Ajax(비동기) 통신으로 댓글 구현 (+ Jquery 사용법)
게시판 댓글을 구현하는 도중 비동기 호출에 대해 알게 됐고, 이를 이용하려면 Ajax를 활용해야 한다는 정보를 얻었다. 비동기란? 비동기의 반대인 동기적 통신의 경우 절차적으로 일을 차례로
black-mint.tistory.com
1. REST(Representational State Transfer) API 란?
- 네트워크 아키텍처 원리의 모음
- 네트워크 아키텍처 : 자원을 정의하고 자원에 대한 주소를 지정하는 방법 전반을 의미
- 예를 들어 학생
2. REST API 설계
- URI는 정보의 자원을 표현
- 자원에 대한 행위로 HTTP Method(GET, POST, PUT, PATCH, DELETE)로 표현
GET | 데이터를 조회 (게시글 조회) | GET /boards/1 게시글 중 1번 게시글을 조회 |
POST | 데이터를 등록 (게시글 작성) | POST /boards 게시글 등록 |
PATCH | 데이터를 일부 수정 (게시글 수정) | PATCH / boards/1 게시글 중 1번 게시글을 수정 |
PUT | 데이터를 전체적으로 수정 | PUT /boards/1 게시글 중 1번 게시글을 수정 |
DELETE | 데이터를 삭제 | DELETE /boards/1 게시글 중 1번 게시글을 삭제 |
3. REST API 규칙
- 소문자로 작성하고 밑줄(_) 대신 하이픈(-)을 사용
- 동사가 아닌 명사로 작성
- 슬래시 구분자(/)는 계층 관계를 나타낼 때 사용하고 URI 마지막에 쓰지 않는다.
- URI에 파일 확장자는 작성하지 않는다.
이 외 규칙이 많지만 이러한 2~3번 규칙을 잘 지켜서 만든 API를 RESTful API라고 한다.
4. 컨트롤러
@RequestMapping("/comments")
@RestController
public class CommentController {
@Autowired
private CommentService commentService;
// 댓글 조회
@GetMapping("/{boardId}")
public List<Comment> getCommentList(@PathVariable(value = "boardId") Long boardId) throws Exception {
List<Comment> comments = commentService.getCommentList(boardId);
return comments;
}
// 댓글 작성
@PostMapping("/{boardId}")
public void commentWrite(@PathVariable(value = "boardId") Long boardId,
@RequestBody Comment comment,
Principal principal) throws Exception {
String username = principal.getName();
commentService.write(boardId, comment.getContent(), username);
}
// 댓글 수정
@PatchMapping("/{commentId}")
public void updateComment(@PathVariable(value = "commentId") Long commentId,
@RequestBody Comment comment) throws Exception {
commentService.update(commentId, comment.getContent());
}
// 댓글 삭제
@DeleteMapping("/{commentId}")
public void deleteComment(@PathVariable(value = "commentId") Long commentId) throws Exception {
commentService.delete(commentId);
}
- @RestController : 클래스 레벨에 선언하면 이전에 각 매핑마다 @ResponseBody 선언 했던 것을 하지 않아도 된다.
- @ResponseBody : 해당 어노테이션이 선언된 매핑은 HTTP의 BODY에 자바 객체를 직접 반환한다.
- @RequestBody : View에서 받아오는 JSON데이터를 파싱해준다. (변환할 데이터를 매핑 가능하도록 필드명 맞춰줘야함) 단, Content-Type이 multipart/form-data로 전달받을 때는 오류를 일으킨다. (주로 파일, 이미지를 전달받을 때)
- @PathVariable : REST방식에서 주로 사용하며, @RequestParam과 유사. URI에 전달받을 변수를 지정
5. Ajax 통신 스크립트 코드
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script th:inline="javascript">
$(document).ready(function () {
getComments()
})
function getComments() {
var loginUsername = [[${ loginUser }]]
var boardId = $('input[name=boardId]').val()
var url = '/comments/' + boardId
$.ajax({
type: 'GET',
url: url,
success: function (response) {
var a = ''
var size = 0
$.each(response, function (key, value) {
size = size + 1;
a += '<hr /><div>'
a += '<input type="hidden" id="commentId" name="commentId" value="' + value.id + '">'
a += '<span id="writer" style="font-weight: bold;">' + value.writer + '</span>'
if (value.writer == loginUsername) {
a += '<ul name="commentChange" class="justify-content-end" style="display: inline;">'
a += '<li name="commentUpdate" type="button" style="display: inline; opacity: 0.7; font-size: small; margin-right: 5px" onclick="updateCommentForm(' + value.id + ')">수정</li>'
a += '<li name="commentDelete" type="button" style="display: inline; opacity: 0.7; font-size: small;" onclick="deleteComment(' + value.id + ')">삭제</li></ul>'
}
a += '<pre id="' + value.id + '" name="comment' + value.id + '" style="margin-bottom: 5px; font-size: large;">' + value.content + '</pre>'
a += '<p name="createDate' + value.id + '" style="margin-bottom: 5px; opacity: 0.5; font-size: small;">' + moment(value.createDate).format("YYYY-MM-DD HH:mm") + '</p></div>'
});
$("#count").html(size)
$("#comment").html(a)
},
error: function (response) {
console.log("getComments error : " + response)
},
complete: function () { }
})
}
function insertComment() {
var boardId = $('input[name=boardId]').val()
var content = document.getElementById("content").value
var param = {"content": content}
var url = '/comments/' + boardId
if (isEmpty(content) == true) {
alert('댓글을 입력해주세요.')
return false;
} else {
$.ajax({
contentType: 'application/json',
type: 'POST',
url: url,
data: JSON.stringify(param),
success: function (response) {
getComments()
},
error: function (response) {
console.log("insertComment error : " + response)
},
})
}
}
function updateCommentForm(id) {
var commentId = id
var content = document.getElementById(id).innerText
$('ul[name=commentChange]').hide()
$('pre[name=comment' + commentId + ']').contents().unwrap().wrap('<textarea id="newComment" class="form-control mt-2" name="updateContent" rows="4"></textarea>');
$('p[name=createDate' + commentId + ']').contents().unwrap().wrap('<input name="update" type="button" class="me-2 mt-2 btn btn-primary" value="수정하기" onclick="updateComment(' + commentId + ')">');
$('input[name=update]').after("<button class=\"me-2 mt-2 btn btn-primary\" onclick=\"getComments()\">취소</button>")
}
function updateComment(id) {
var commentId = id
var content = document.getElementById("newComment").value
var param = {"content": content}
var url = '/comments/' + commentId
if (isEmpty(content) == true) {
alert('댓글을 입력해주세요.')
return false;
} else {
$.ajax({
contentType: 'application/json',
type: 'PATCH',
url: url,
data: JSON.stringify(param),
success: function (response) {
getComments()
},
error: function (response) {
console.log("updateComment error : " + response)
},
complete: function () { }
})
}
}
function deleteComment(id) {
var commentId = id
var url = '/comments/' + commentId
if (confirm("정말 삭제하시겠습니까?")) {
$.ajax({
type: 'DELETE',
url: url,
success: function (response) {
getComments()
},
error: function (response) {
console.log("deleteComment error : " + response)
},
complete: function () { }
})
} else {
return;
}
}
function isEmpty(strIn) {
if (strIn === undefined) {
return true;
}
else if (strIn == null) {
return true;
}
else if (strIn == "") {
return true;
}
else {
return false;
}
}
</script>
- 이전 글과 바뀐 부분
- Json으로 서버에 데이터를 보내주기 위해 contentType을 json으로 설정
- url을 REST API 규칙에 맞춰 작성
- data: json.stringify( ) : ajax 통신의 데이터 전달부분을 미리 만들어둔 json형식의 자바스크립트 변수를 서버로 전달
- type을 REST API 규칙에 맞춰 작성
- 날짜 포맷을 변경하기 위해 moment라이브러리 사용
- https://black-mint.tistory.com/51
[JavaScript] 날짜 포맷 변경 라이브러리
서버에서 Json 형태로 프론트로 넘어오면 날짜 형식이 다음과 같이 변경돼서 날아온다. "createDate": "Jan 5, 2022, 4:25:48 PM" 원하는 날짜 형식으로 바꿔 보여주고 싶을 때 사용할 라이브러리 https://m
black-mint.tistory.com
* REST 관련 참고
https://congsong.tistory.com/30?category=749196
'Web > SpringBoot' 카테고리의 다른 글
[Spring Boot] Mybatis insert, update 시 PK값 얻기 (0) | 2022.01.09 |
---|---|
[Spring Boot] ajax 리스트 값 서버로 보내기 (휴지통 복원, 삭제) (0) | 2022.01.06 |
[Spring Boot] 쿠키를 이용한 조회수 구현 (0) | 2022.01.03 |
[Spring Boot] JavaMailSender로 메일 보내기 (0) | 2022.01.03 |
[Spring Boot] Ajax(비동기) 통신으로 댓글 구현 (+ Jquery 사용법) (0) | 2022.01.02 |