# 댓글 등록하기
## 미션
---
게시글에 댓글을 작성하고,

저장된 레코드를 확인하시오.

## 개념
---
#### ⭐️ 진행 흐름
사용자가 댓글을 작성한다. 이를 JS에서 객체(JSON)로 만들고, Ajax로 전송. 이를 스프링 서버의 컨트롤러가 DTO로 변환하여 받는다. 컨트롤러는 데이터 저장 업무를 리파지터리에게 위임한다. 이 때, DTO가 Entity로 변환되고, Entity는 리파지터리에 의해 DB에 저장된다. 그 결과, 하나의 댓글 레코드가 만들어 진다.

## 튜토리얼
---
#### ⭐️ 뷰 페이지
1) 댓글 입력 창 만들기: "comments/_comments.mustache"
```
<div class="card" id="comments">
<div class="card-body">
<form>
<div class="form-group">
<label>댓글 작성</label>
<textarea class="form-control" id="comment-content" rows="3"></textarea>
</div>
<input type="hidden" id="comment-author" value="익명">
<button type="button" class="btn btn-primary" id="comment-create-btn">제출</button>
</form>
</div>
</div>
<!-- ajax 통신을 위한 JS 추가 -->
<Script src="/js/app/comment.js"></script>
```
2) 댓글 입력 창 추가: "articles/show.mustache"
```
...
<table class="table table-hover">
...
</table>
<!-- 댓글 페이지 -->
{{>comments/_comments}}
<a href="/articles" class="btn btn-success btn-block">목록으로</a>
<!-- ArticleJS for Ajax -->
<Script src="/js/app/article.js"></script>
{{>layouts/footer}}
```
#### ⭐️ JS 파일
3) 생성: "js/app/comment.js"
```
// 데이터 전송 객체 생성!
var comment = {
// 이벤트 등록
init: function() {
var _this = this;
// 생성 버튼 클릭 시!
const createBtn = document.querySelector('#comment-create-btn');
// 이벤트 감시 시, 수행할 메소드 연결!
createBtn.addEventListener('click', function(){
_this.create();
});
},
// 댓글 등록
create: function() {
// 데이터
var data = {
author: document.querySelector('#comment-author').value,
content: document.querySelector('#comment-content').value,
};
// url에서 article의 id를 추출!
var split = location.pathname.split('/');
var articleId = split[split.length - 1];
// Ajax 통신
// - https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
// - https://t.ly/Vrrz
fetch('/api/comments/' + articleId, { // 요청을 보냄
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
}
}).then(function(response) { // 응답 처리
if (response.ok) { // 성공
alert('댓글이 등록되었습니다.');
window.location.reload();
} else { // 실패
alert('댓글 등록 실패..!');
}
});
}
};
// 객체 초기화!
comment.init();
```
#### ⭐️ API 컨트롤러
4) 생성: "api/CommentApiController"
```
@Slf4j
@RequiredArgsConstructor
@RestController
public class CommentApiController {
private final CommentRepository commentRepository;
@PostMapping("/api/comments/{articleId}")
public Long create(@PathVariable Long articleId,
@RequestBody CommentForm form) {
log.info("form: " + form.toString());
Comment saved = commentRepository.save(form.toEntity());
log.info("saved: " + saved.toString());
return saved.getId();
}
}
```
#### ⭐️ 리파지터리 인터페이스
5) 생성: "repository/CommentRepository"
```
public interface CommentRepository extends CrudRepository<Comment, Long> {
}
```
#### ⭐️ DTO
6) 생성: "dto/CommentForm"
```
@Data
public class CommentForm {
private Long id;
private String author;
private String content;
public Comment toEntity() {
return Comment.builder()
.id(id)
.author(author)
.content(content)
.build();
}
}
```
#### ⭐️ 엔티티 클래스
7) 기존 코드 확인: "entity/Comment"
```
@Getter
@ToString
@Builder
@NoArgsConstructor // 디폴트 생성자 넣어 줌!
@AllArgsConstructor // 모든 필드 포함 생성자 자동 기입
@Entity
public class Comment extends BaseTime {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 20, nullable = false)
private String author;
@Column(columnDefinition = "TEXT", nullable = false)
private String content;
}
```
#### ⭐️ 확인하기
8) 댓글 작성

9) DB 레코드 확인

## 훈련하기
---
- 튜터리얼 중 댓글 생성 시 수행되는 SQL 쿼리를 분석하고, 이를 설명하시오.
## 면접 준비
---
- 입력한 댓글이 DB에 저장되기 까지의 과정?
- 입력 댓글이 어떤 article에서 작성 되었는지, DB 레코드에서 확인 가능한가?