[Spring Boot] 17. 웹 페이지에서 댓글 등록하기
- -
17장. 웹 페이지에서 댓글 등록하기
17.1. 댓글 등록의 개요
이번에는 새 댓글을 등록하는 부분을 구현해보자. 댓글 등록 구현을 댓글 생성 뷰(View) 페이지에 댓글 입력 폼을 만드는 것과 [댓글 작성] 버튼을 클릭해 REST API 요청을 보내는 2가지로 나눠서 진행하겠다.
그동안 REST API 요청을 보낼 때 Talend API Tester를 이용했는데, 실제 게시판에서는 해당 웹 페이지에서 바로 요청을 보내므로 자바스크립트 API를 사용해 구현해보자.
· document.querySelector()
- 웹 페이지에서 특정 요소(버튼)을 찾아 반환한다.
· addEventListener()
- 특정 요소에 이벤트(버튼 클릭)가 발생했을 때 특정 동작(댓글 객체 전달)을 수행한다.
· fetch()
- 웹 페이지에서 REST API 요청(POST 요청)을 보낸다.
17.2. 댓글 생성 뷰 페이지 만들기
댓글 생성 뷰 페이지는 card의 body 스타일을 이용해 만들어보자. class 속성을 class="card m-2"로 수정해 여백(margin)을 2만큼 주고, 구분을 위해 id="comments-new" id 속성을 추가한다.
댓글 작성 폼은 form 태그의 Overview 스타일을 이용해 만들어보자. 닉네임 입력 폼은 id="new-comment-nickname" 속성을 받고, 댓글 본문 입력 폼은 id="new-comment-body" 속성을 받는다. 댓글 본문은 닉네임과 달리 내용이 많으므로 <input> 대신 여러 줄을 입력할 수 있는 <textarea></textarea>로 수정한다.
댓글의 게시글에 종속되는 특성 상 부모의 게시글을 가지고 있어야 하므로 부모 게시글의 id를 히든 인풋(hidden input)으로 넣는다. 머스테치 문법으로 {{#article}} ... {{/article}}을 이용해 변수 사용 범위를 지정하고 id="new-comment-id" 속성과 value="{{id}}" 속성을 설정한다.
src > main > resources > templates > comments > _new.mustache
<div class="card m-2" id="comments-new">
<div class="card-body">
<!-- 댓글 작성 폼 -->
<form>
<!-- 닉네임 입력 -->
<div class="mb-3">
<label class="form-label">닉네임</label>
<input type="text" class="form-control"
id="new-comment-nickname">
</div>
<!-- 댓글 본문 입력 -->
<div class="mb-3">
<label class="form-label">댓글 내용</label>
<textarea type="text" class="form-control" rows="3"
id="new-comment-body"></textarea>
</div>
<!-- 히든 인풋 -->
{{#article}}
<input type="hidden" id="new-comment-article-id" value="{{id}}">
{{/article}}
<!-- 전송 버튼 -->
<button type="button" class="btn btn-primary"
id="comment-create-btn">댓글 작성
</button>
</form>
</div>
</div>
17.3. 자바스크립트로 댓글 달기
웹 페이지에서도 자바스크립트를 사용하면 REST API를 호출할 수 있다. 댓글 생성을 위해 _new.mustache 코드 맨 아래에 <script></script> 코드를 추가하고 안쪽에 블록({ })을 잡는다.
17.3.1. 버튼 클릭 이벤트 감지하기
· document.querySelector()
- 웹페이지에서 특정 요소를 선택할 때 사용한다
- 메서드에 id, name, class, HTML 태그 등의 값을 입력하면 해당 속성 값을 가진 대상을 반환한다.
- id 값으로 대상을 찾을 때는 id 값 앞에 #을 붙인다. 이를 아이디 선택자(#id)라고 한다.
// 해당 id값을 가진 요소를 찾아 변수에 저장하기
자료형 변수명 = document.querySelector("#id_값");
[댓글 작성] 버튼 id 값인 comment-create-btn을 #과 함께 querySelector() 메서드로 입력해 상수 타입의 commentCreateBtn 변수에 저장한다.
<button type="button" class="btn btn-primary"
id="comment-create-btn">댓글 작성</button>
<script>
{
// 댓글 생성 버튼 변수화
const commentCreateBtn = document.querySelector("#comment-create-btn");
}
</script>
· document.querySelector()
- 특정 요소에 이벤트(버튼 클릭)가 발생했을 때 특정 동작(댓글 객체 전달)을 수행한다.
// 이벤트가 감지되면 이벤트 처리 함수 실행
요소명.addEventListener("이벤트_타입", 이벤트_처리_함수);
// 댓글 생성 버튼 변수화
const commentCreateBtn = document.querySelector("#comment-create-btn");
// 댓글 클릭 이벤트 감지
commentCreateBtn.addEventListener("click", function () {
console.log("버튼을 클릭했습니다"); // 콘솔에 출력
};
17.3.2. 새 댓글 자바스크립트 객체 생성
자바스크립트에서 객체를 생성하는 방법은 3가지가 있다. 객체 리터럴 방식, 생성자 함수 방식, Object.create() 방식이다. 여기서는 객체를 변수로 선언해 사용하는 객체 리터럴 방식(object literal)을 사용한다.
var object = {
key1 : value1,
key2 : value2,
key3 : value3
}
키 값은 다음과 같이 querySelector() 메서드와 value로 가져온다.
// 해당 id값을 가진 요소를 찾고, 찾은 대상의 value를 가져옴
document.querySelector("#id_값").value
다음은 닉네임, 댓글 본문, 히든 인풋의 부모 게시글 id 값이 들어있는 입력들의 id 속성 값으로 요소를 찾고 value를 가져오는 코드이다.
<!-- 닉네임 입력 -->
<div class="mb-3">
<label class="form-label">닉네임</label>
<input type="text" class="form-control"
id="new-comment-nickname">
</div>
<!-- 댓글 본문 입력 -->
<div class="mb-3">
<label class="form-label">댓글 내용</label>
<textarea type="text" class="form-control" rows="3"
id="new-comment-body"></textarea>
</div>
<!-- 히든 인풋 -->
{{#article}}
<input type="hidden" id="new-comment-article-id" value="{{id}}">
{{/article}}
// 댓글 클릭 이벤트 감지
commentCreateBtn.addEventListener("click", function () {
// 새 댓글 객체 생성
const comment = {
// 새 댓글의 닉네임
nickname: document.querySelector("#new-comment-nickname").value,
// 새 댓글의 본문
body: document.querySelector("#new-comment-body").value,
// 부모 게시글의 id
articleId: document.querySelector("#new-comment-article-id").value
};
17.3.3. 자바스크립트로 REST API 호출하고 응답 처리하기
fetch() 함수는 웹 페이지에서 HTTP 통신을 하는데 사용한다. 즉, fetch() 함수를 통해 웹 페이지에서 GET, POST, PATCH, DELETE 같은 요청을 보내고 응답을 보낼 수 있다. POST 요청을 보낼 때 형식은 다음과 같다.
fetch('API_주소', {
method: "POST", // POST 요청
headers: { // 헤더 정보 : 전송 본문의 데이터 타입(JSON) 정보
"Content-Type": "application/json"
},
body: JSON.stringify(객체) // 객체를 JSON 문자열로 변환해 전송
}).then(response => { // 응답을 받아 처리하는 구문
응답_처리문
});
다음 코드에서 살펴보자. 첫 번째 전달값으로 API 주소를 가지고 있는 URL을 넘기고, 두 번째 전달값으로 요청 메서드, 헤더 정보, 전송 본문을 보낸다. 이때 전송 본문은 JSON 형태로 보내야 하므로 JSON.stringfy() 메서드를 사용해 JSON으로 형태 변환한다. 헤더 정보에는 전송 본문의 데이터 타입이 JSON임의 명시하는 내용이 들어간다.
댓글 작성이 완료되면 응답을 보내기 위해 fetch() 함수의 응답 처리 구문을 구현해보자. 응답 객체의 상태가 ok면 "댓글이 등록됐습니다." 를 아니면 "댓글 등록 실패..!"를 msg 변수에 저장하고 alert() 함수로 출력한다. 댓글 생성 완료 후 메시지까지 출력이 정상적으로 이루어졌으면 window.location.reload() 메서드로 웹 페이지를 새로 고침한다.
// fetch() - 비동기 통신을 위한 API
const url = "/api/articles/" + comment.articleId + "/comments";
fetch(url, {
method: "post", // POST 요청
headers: { // 전송 본문의 데이터 타입(JSON) 정보
"Content-Type": "application/json"
},
body: JSON.stringify(comment) //comment 객체를 JSON 문자열로 변환해 전송
}).then(response => {
// HTTP 응답 코드에 따른 메시지 출력
const msg = (response.ok) ? "댓글이 등록됐습니다." : "댓글 등록 실패..!";
alert(msg);
// 현재페이지 새로고침
window.location.reload();
});
'BackEnd > 스프링부트3 백엔드 개발 입문' 카테고리의 다른 글
[Spring Boot] 19. 웹 페이지에서 댓글 삭제하기 (0) | 2024.02.02 |
---|---|
[Spring Boot] 18. 웹 페이지에서 댓글 수정하기 (0) | 2024.02.01 |
[Spring Boot] 16. 웹 페이지에서 댓글 목록 보기 (0) | 2024.01.30 |
[Spring Boot] 15. 댓글 컨트롤러와 서비스 만들기 (2) (0) | 2024.01.29 |
[Spring Boot] 15. 댓글 컨트롤러와 서비스 만들기 (1) (0) | 2024.01.26 |
소중한 공감 감사합니다