1. 쿼리 작성
더미데이터 추가
insert into reply_tb(comment, board_id, user_id, created_at) values('댓글1', 1, 1, now()); insert into reply_tb(comment, board_id, user_id, created_at) values('댓글2', 4, 1, now()); insert into reply_tb(comment, board_id, user_id, created_at) values('댓글3', 4, 1, now()); insert into reply_tb(comment, board_id, user_id, created_at) values('댓글4', 4, 2, now());
select rt.id, rt.user_id, rt.comment, ut.username from reply_tb rt inner join user_tb ut on rt.user_id = ut.id where rt.board_id = 4 ;
게시글에 작성된 댓글을 표시한다. 화면에는 username 과 comment 만 출력하지만 댓글의 작성자 여부를 확인하기 위해 id 와 userId 도 함께 받아온다.
2. DTO 만들기
댓글 테이블에서 받은 데이터를 boardResponse 에 DTO로 받는다. 댓글을 게시글에 출력해야 하기 때문이다.
package shop.mtcoding.blog.board; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; import lombok.Data; import shop.mtcoding.blog.user.User; import java.util.List; public class BoardResponse { @Data public static class DetailDTO { private Integer id; private String title; private String content; private Integer userId; private String username; @Data public static class ReplyDTO { private Integer id; private Integer userId; private String username; private String comment; public ReplyDTO(Object[] ob,User sessionUser) { this.id = (Integer) ob[0]; this.userId = (Integer) ob[1]; this.comment = (String) ob[2]; this.username = (String) ob[3]; } } }
기존 BoardResponse 는 DB에서 조회된 게시글 테이블을 받는 DTO였다. 여기에 댓글 테이블을 받는 DTO를 합친다.
ReplyDTO를 컬렉션 형태로 받는 이유는 하나의 게시글에 여러 개의 댓글이 표현되어야 하기 때문이다. 컬렉션 형태로 mustache 에 전달하면 반복문의 형태가 된다.
3. 컨트롤러
@GetMapping("/board/{id}") public String detail(@PathVariable int id,HttpServletRequest request) { User sessionUser = (User) session.getAttribute("sessionUser"); // 세션의 id if(sessionUser!=null){ // 세션의 값이 null 이 아니어야 로그인 상태 if(boardUserId==sessionUser.getId()){ 세션 id = 게시글 작성 id 비교 owner = true; // 일치하면 권한 활성 } request.setAttribute("owner",owner); // View 에 전달 } //DB데이터를 DetailDTO에 받음 BoardResponse.DetailDTO boardDTO = boardRepository.findByIdWithUser(id); //DB데이터를 ReplyDTO에 받음 List<BoardResponse.ReplyDTO> replyDTOList = replyRepository.findByBoardId(id,sessionUser); //게시글 데이터를 view 로 가져감 request.setAttribute("board", boardDTO); //댓글 데이터를 view 로 가져감 request.setAttribute("replyList",replyDTOList); return "board/detail"; }
댓글은 게시글에 출력되기 때문에 boardController 의 상세보기 메서드에 작성한다.
레파지토리에 게시판 번호와 세션의 회원ID를 가져간다 세션 회원 ID는 추후에 댓글의 작성자 여부를 확인할 때 사용한다.
4. 레파지토리
public List<BoardResponse.ReplyDTO> findByBoardId(int boardId, User sessionUser) { Query query = em.createNativeQuery("select rt.id, rt.user_id, rt.comment, ut.username from reply_tb rt \n" + "inner join user_tb ut on rt.user_id = ut.id where rt.board_id = ?"); query.setParameter(1,boardId); List<Object[]> obs = query.getResultList(); //DB에서 받은 정보를 ReplyDTO에 로그인한 User 정보와 함께 받는다. return obs.stream().map(ob -> new BoardResponse.ReplyDTO(ob,sessionUser)).toList(); }
게시글 번호로 테이블을 조회한다.
Stream API 를 통해 ReplyDTO 로 받은 테이블 데이터를 오브젝트 배열 형태로 담는다.
5. View
<!-- 댓글아이템 --> {{#replyList}} <div class="list-group-item d-flex justify-content-between align-items-center"> <div class="d-flex"> <div class="px-1 me-1 bg-primary text-white rounded">{{username}}</div> <div>{{comment}}</div> </div> <form action="/reply/1/delete" method="post"> <button class="btn">🗑</button> </form> </div> {{/replyList}}
replyList 는 컬렉션 형태기 때문에 {{#replyList}} {{/replyList}} 는 mustache 에서 반복문 형태가 된다. 따라서 댓글 테이블이 여러개라면 반복문을 돌면서 출력한다.
4번 게시글에 댓글이 정상적으로 출력된다.
게시글이 없는 댓글은 출력되지 않는다.
댓글을 작성하면 리스트에 출력이 된다.
Share article