다음의 순서는 댓글 기능에 대한 개요이다. 1번부터 5번까지는 백엔드 파트이고, 6번은 프론트엔드 파트이다.
1.댓글에 대한 DB테이블 생성(cno, bno, pcno, comment, commenter, reg_date, up_date)
→ cno는 댓글 번호, bno는 게시물 번호, pcno는 대댓글을 위한 기준 정렬 번호를 각각 의미한다.
2. Mapper XML 작성
3. DAO 작성 및 테스트
4. Service 작성 및 테스트
5. 컨트롤러 작성 및 테스트
6. UI 작성 및 테스트
게시판 CRUD와 같은 흐름의 방식으로 설계하기 때문에 1번~4번까지의 전반적인 내용은 생략하고, 5번 컨트롤러의 차이점을 중심으로 하여 정리하였다.
BoardController(게시판 컨트롤러)와의 설계 차이점
① @PathVariable
쿼리스트링으로 들어가는 값과 Mapping 된 URI의 일부에 들어가는 값 인지를 잘 비교하고, Mapping 된 URI의 일부를 읽어올 때에는 앞에 @PathVariable을 붙여주어야 한다. 아래 예제 코드의 @DeleteMapping("/comments/{cno}") 처럼 URI의 일부에 들어가는 cno 값은 @PathVariable 붙여주어야 함을 볼 수 있다.
@DeleteMapping("/comments/{cno}") // /comments/1?bno=729 <-- 삭제할 댓글 번호
public ResponseEntity<String> remove(@PathVariable Integer cno, Integer bno, HttpSession session) {
String commenter = (String)session.getAttribute("id");
try {
int rowCnt = service.remove(cno, bno, commenter);
② ResponseEntity 객체
댓글 기능을 사용하던 중 에러가 발생하여 요청이 잘 처리되지 않았음에도 응답 헤더는 항상 200번대를 유지한다. 따라서 아래 예제 코드와 같이 요청이 잘 처리됐을 때와 처리되지 않았을 때에 따른 올바른 상태를 지정해주어야 한다. 이때 사용하는 것이 바로 ResponseEntity 객체이다.
try {
int rowCnt = service.remove(cno, bno, commenter);
if(rowCnt != 1)
throw new Exception("Delete Failed");
return new ResponseEntity<>("DEL_OK", HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<>("DEL_ERR", HttpStatus.BAD_REQUEST);
}
③ RestController
메서드마다 일일이 @ResponseBody를 붙여주는 것 대신 클래스 앞에 @RestController 어노테이션을 사용하였다.
※ 간단 Tip) @RestController = @Controller + @ResponseBody
Ajax를 이용한 댓글 및 대댓글 기능 구현
아래 예제 코드는 댓글 기능 중 일부인 댓글 작성에 대한 코드이다. 전체적으로 각 댓글 버튼 UI를 구성하고 적절하게 각 버튼에 대한 클릭 이벤트를 작성해주어 댓글 기능들을 구현해준다.
ㆍtype : 요청 메서드
ㆍurl : 요청 URI
ㆍheaders : 요청 헤더(JSON)
ㆍdataType : 전송받을 데이터의 타입(생략하면 기본값이 JSON이 된다)
ㆍdata : 서버로 전송할 데이터이고, 따라서 직렬화(JSON 문자열로 변환)가 필요하다.
ㆍsuccess : 서버로부터 성공적으로 응답이 오면 호출되는 함수
ㆍerror : 에러가 발생하면 서버로부터 호출되는 함수
$("#sendBtn").click(function(){
$.ajax({
type:'POST', // 요청 메서드
url: '/ch4/send', // 요청 URI
headers : { "content-type": "application/json"}, // 요청 헤더
dataType : 'text', // 전송받을 데이터의 타입
data : JSON.stringify(person), // 서버로 전송할 데이터. stringify()로 직렬화 필요.
success : function(result){
person2 = JSON.parse(result); // 서버로부터 응답이 도착하면 호출될 함수
alert("received="+result); // result는 서버가 전송한 데이터
$("#data").html("name="+person2.name+", age="+person2.age);
},
error : function(){ alert("error") } // 에러가 발생했을 때, 호출될 함수
}); // $.ajax()
댓글 기능을 구현하고 이를 바탕으로 특정 댓글에 대한 답글인 대댓글을 구현한다. 이때, 두 가지 사항을 고려한다.
1. '답글' 버튼을 누르면 대댓글을 작성할 해당 댓글의 바로 밑에 form 태그가 보여지도록 설계
→ .append($(this).parent())를 통해 각 해당 댓글 즉, 부모 댓글(li 태그) 뒤에 붙게 된다. 따라서 대댓글 입력 폼이 해당 댓글의 바로 밑에 보여지게 된다.
2. 댓글 DB테이블의 pcno 칼럼 정보를 통해 작성된 대댓글이 부모 댓글의 바로 밑에 위치하도록 설계
→ ORDER BY pcno asc, cno asc; 구문을 통해서 pcno를 기준으로 댓글 목록이 정렬될 수 있도록 하고, 여러 개의 대댓글이 달릴 수 있으므로 대댓글 또한 cno를 기준으로 정렬해주면 된다.
※ pcno에 부모 댓글 번호(cno) 값을 채워준다면 정렬 기준이 pcno이므로 부모 댓글 밑에 대댓글이 위치하게 되는 것
'[패스트캠퍼스] 스프링의정석 정리 > 게시판 구현 핵심 개념' 카테고리의 다른 글
4. REST API와 Ajax (0) | 2023.05.10 |
---|---|
3. 게시판 검색 기능 (0) | 2023.05.10 |
2. 게시판 CRUD (0) | 2023.05.10 |
1. 게시판 목록 - 페이징 처리 (0) | 2023.05.09 |