일기 데이터를 수정하고 저장하는 editdiary.html 에 ajax JQuery 함수를 적용시켜볼께.
이미 작성된 일기 데이터를 읽어들여 보여주고, 수정한 후에 “저장” 버튼을 누르면 form 태그의 action URL 로 전송되는 구조였어. 이때의 action URL 은 PUT method 인 /diary/{id} 이고 DiaryController 클래스에 구현되어 있지.
DiaryController.java
@RestController
public class DiaryController {
...
// Update
@PutMapping(value = "/diary/{id}")
public RedirectView UpdateDiary(@PathVariable("id") Integer id, String diary_date, String diary_content) {
System.out.println("id=" + id + ", date=" + diary_date + ", content=" + diary_content);
diaryService.UpdateDiary(id, diary_date, diary_content);
return new RedirectView("/");
}
...
}
이 구조를 “저장” 버튼을 클릭했을 때 ajax 함수를 호출하여 데이터를 저장하는 Rest API 를 호출하고 결과를 받아서 페이지 이동을 하는 구조로 변경해 볼거야. 다시 말해서 DiaryController의 UpdateDiary 함수가 뷰의 이동까지 처리하던 것을 데이터처리만 하는 것으로 변경하고, 뷰 이동은 front-end 쪽으로 넘긴다는 이야기지.
우선 “저장” 버튼을 클릭했을 때 ajax 함수를 호출하기 위해서 onclick 이벤트 함수를 추가해볼께. 그리고 “저장” 버튼의 type 은 submit 에서 button 으로 변경했어. 그리고 자바스크립트에서 일기내용이 작성된 form 을 참고해야 하기 때문에 form 에 id 를 붙여줬지.
editdiary.html
...
<h1>Edit</h1>
<form th:id="editForm" th:action="@{/diary/{id}(id=${diary.id})}" th:method="POST">
<input type="hidden" name="_method" value="PUT" />
<!--<input type="hidden" id="id" name="id" th:value="${diary.id}" />-->
<div class="mb-3">
<label for="diary_date" class="form-label">날짜:</label>
<input type="text" class="form-control" id="diary_date" name="diary_date" th:value="${#temporals.format(diary.diary_date, 'yyyy-MM-dd')}" />
</div>
<div class="mb-3">
<label for="diary_content" class="form-label">내용:</label>
<textarea class="form-control" rows="10" id="diary_content" name="diary_content" th:value="${diary.diary_content}" th:text="${diary.diary_content}"></textarea>
</div>
<input type="button" class="btn btn-primary" value="저장" th:onclick="modifyDiary()" />
</form>
...
팁!! submit Type 의 버튼에 onclick 이벤트에 함수를 설정하는 경우 해당 함수의 로직이 모두 수행된 뒤에 자동으로 submit 기능이 동작을 해. 만약 설정된 함수의 로직에서 submit 하지 말아야 할 상황이 되었을 때 false 를 리턴해서 submit 이 동작하지 않게 하려면 onclick 이벤트에 설정하는 함수 이름 앞에 return 을 붙여주면 돼. <input type="submit" class="btn btn-primary" value="저장" th:onclick="return modifyDiary()" />
modifyDiary 자바스크립트 함수는 jQuery 를 사용해서 다음과 같이 작성했어.
<script src="https://code.jquery.com/jquery-3.6.0.min.js" charset="UTF-8"></script>
<script th:inline="javascript">
function modifyDiary() {
let editForm = $("#editForm");
let formData = new FormData(editForm.get(0));// get Form element
let diary_date = formData.get("diary_date");
let diary_content = formData.get("diary_content");
// 입력값 유효성 확인
if (!diary_date || !diary_content) {
alert("빈값일 수 없습니다.");
return;
}
let diaryId = /*[[${diary.id}]]*/"";
let url = `/diary/${diaryId}`;
let data = editForm.serialize();
console.log("data = " + data);
//////////////////////////////////////////
$.ajax({
url: url,
type: 'PUT',
data: data,
error: function(xhr, status, error) {
alert("error");
},
success: function() {
alert("succeeded");
}
});
}
</script>
자바스크립트 함수를 설명하려면 많은 것을 설명해야 하는데, 여기에서 가장 중요한 것은 DiaryController 클래스의 PUT method 핸들러 함수인 UpdateDiary 를 하나도 고치지 않은 상태에서 데이터가 처리되게 하기 위해서 Form 객체의 serialize() 함수를 이용해서 얻은 데이터를 그대로 전송하게 했다는거야. 즉, 기존에 submit Type 의 버튼을 클릭했을 때와 같은 방식으로 데이터가 전송되게 하는 방법이지. 클라이언트 콘솔에 남긴 로그를 보면 serialize() 함수로 얻은 값이 Form 에 작성한 각 항목의 이름(name)과 값(value)이 & 로 연결된 형태의 값인 것을 확인할 수가 있어.
프로그램을 빌드해서 실행시키면 서버로그와 클라이언트 로그에 각각 Request method ‘PUT’ is not supported 와 405 (Method Not Allowed) 가 남아.
하지만 데이터 업데이트는 성공했지. Spring Boot: study.diary swagger 연동 (API 테스트 목적) 에서 확인했던 결과와 마찬가지인거지.
이제 DiaryController 클래스의 UpdateDiary 함수에서 뷰 이동에 관한 로직을 제거해서 오직 데이터 처리에 관한 로직만 남겨볼께.
@PutMapping(value = "/diary/{id}")
public void UpdateDiary(@PathVariable("id") Integer id, String diary_date, String diary_content) {
System.out.println("id=" + id + ", date=" + diary_date + ", content=" + diary_content);
diaryService.UpdateDiary(id, diary_date, diary_content);
}
이렇게 수정하고 프로그램을 실행시켜보니 데이터 업데이트도 성공하고, 더 이상 Request method ‘PUT’ is not supported 또는 405 (Method Not Allowed) 라는 에러 로그는 보이지 않게 되었어. 하지만, 처음에 의도했던대로 데이터 수정 이후 Home 화면으로의 이동 처리는 안되고 있지. 이제 ajax 함수에 API 호출 결과에 따라 페이지 이동 처리를 위한 코드를 추가해볼께.
$.ajax({
url: url,
type: 'PUT',
data: data,
error: function(xhr, status, error) {
alert("error");
},
success: function() {
alert("succeeded");
window.location.href = '/';
}
});
이제 일기 수정을 하게 되면 데이터 수정은 Rest API 에서, 수정 성공 후 페이지 이동은 Front-End 에서 처리되는 것으로 수정이 완료되었어.
Spring Boot: study.diary swagger 연동 (API 테스트 목적) 에서 swagger UI 에서 테스트시 문제가 되었던 PUT method 에 의한 /diary/{id} API 호출 역시 문제없이 실행되는걸 확인할 수 있게 되었지.