[Tistory] 게시글 상세보기

yuzu sim's avatar
Oct 14, 2024
[Tistory] 게시글 상세보기

1. 화면

notion image
 

2. PostResponse - DetailDTO 생성

// 게시글 상세보기 @Data public static class DetailDTO { private Integer id; private String title; private String content; private Integer userId; private String username; private String createdAt; private Boolean isPostOwner; public DetailDTO(Integer id, String title, String content, Integer userId, String username, LocalDateTime createdAt, Boolean isPostOwner) { this.id = id; this.title = title; this.content = content; this.userId = userId; this.username = username; this.createdAt = createdAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")); } }
 

3. PostJPARepository

// 게시글 상세보기 @Query("select new site.metacoding.blogv3.post.PostResponse$DetailDTO(p.id, p.title, p.content, p.user.id, p.user.username, p.createdAt)" + "from Post p where p.id = :postId") Optional<PostResponse.DetailDTO> findByPostId(Integer postId);
 

4. PostService

public PostResponse.DetailDTO postDetail(Integer postId, User sessionUserId) { PostResponse.DetailDTO postDetail = postJPARepo.findByPostId(postId) .orElseThrow(() -> new RuntimeException("게시글이 존재하지 않습니다.")); System.out.println("postDetail = " + postDetail); Boolean isPostOwner = false; if (sessionUserId != null) { if (sessionUserId.getId() == postDetail.getUserId()) { isPostOwner = true; } } postDetail.setIsPostOwner(isPostOwner); return postDetail; }
 

5. PostController

@GetMapping("/post/detail/{postId}") public String postDetail(@PathVariable Integer postId, HttpServletRequest request) { User user = (User) session.getAttribute("sessionUser"); PostResponse.DetailDTO postDetail = postService.postDetail(postId, user); System.out.println("Post Detail: " + postDetail); request.setAttribute("model", postDetail); return "post/detail"; }
 

6. detail.mustache

{{>/layout/main-header}} <div class="container"> <input id="postId" type="hidden" value="{{model.postId}}"/> <input id="pageOwnerId" type="hidden" value="1"/> <input id="my-loveId" type="hidden" value="1"> <div class="my_post_detail_title"> <h2>{{model.title}}</h2> </div> <hr/> <div class="my_post_detail_content"> {{model.content}} </div> <div class="my_post_info_box d-flex"> <div class="my_post_info"> <i class="fa-solid fa-heart my_fake_like my_mr_sm_1" id="heart-1"></i> by <b>{{model.username}}</b> <span class="my_text_body_sm">날짜</span> <!-- <i class="far fa-heart my_fake_un_like my_mr_sm_1" id="my-heart"></i>--> <!-- by <b>유저네임</b> <span class="my_text_body_sm">날짜</span>--> </div> </div> {{#model.isPostOwner}} <div class="my_mt_md_1"> <a class="btn btn-outline-success" href="#">수정</a> <button id="btn-delete" class="btn btn-outline-danger">삭제</button> </div> {{/model.isPostOwner}} <br/> <!-- <div class="my_livere">--> <!-- &lt;!&ndash; 라이브리 시티 설치 코드 &ndash;&gt;--> <!-- <div id="lv-container" id="city" data-uid="MTAyMC81MTM0MC8yNzgyMQ==">--> <!-- <script type="text/javascript">--> <!-- (function (d, s) {--> <!-- var j, e = d.getElementsByTagName(s)[0];--> <!-- if (typeof LivereTower === 'function') {--> <!-- return;--> <!-- }--> <!-- j = d.createElement(s);--> <!-- j.src = 'https://cdn-city.livere.com/js/embed.dist.js';--> <!-- j.async = true;--> <!-- e.parentNode.insertBefore(j, e);--> <!-- })(document, 'script');--> <!-- </script>--> <!-- <noscript>라이브리 댓글 작성을 위해 JavaScript를 활성화 해주세요</noscript>--> <!-- </div>--> <!-- &lt;!&ndash; 시티 설치 코드 끝 &ndash;&gt;--> <!-- </div>--> </div> {{>/layout/footer}}

7. 오류터짐…

notion image
list.mustache에서 상세보기 넘어갈때 postId 바인딩 왜 안되지???
notion image
 

8. PostService 수정

처음 쿼리 작성했을때 중첩 클래스의 경우 데이터베이스 쿼리에서 적절히 매핑이 안된거 같음
Post 엔티티를 데이터베이스에서 가져와보자..
public PostResponse.DetailDTO postDetail(Integer postId, User sessionUser) { Post post = postJPARepo.findById(postId) .orElseThrow(() -> new Exception404("게시글이 존재하지 않습니다.")); PostResponse.DetailDTO detailDTO = new PostResponse.DetailDTO(post, sessionUser); return detailDTO; }
notion image
public PostResponse.DetailDTO postDetail(Integer postId, User sessionUser) { Post post = postJPARepo.findByIdWithUser(postId) .orElseThrow(() -> new Exception404("게시글이 존재하지 않습니다.")); PostResponse.DetailDTO detailDTO = new PostResponse.DetailDTO(post, sessionUser); return detailDTO; }

9. PostJPARepository 수정

레이지 로딩 터짐 - 조인 패치로 쿼리 수정
// 게시글 상세보기 (조인패치) @Query("SELECT p FROM Post p JOIN FETCH p.user WHERE p.id = :postId") Optional<Post> findByIdWithUser(@Param("postId") Integer postId);
 

10. PostResponse - DetailDTO 수정(코드 가독성 향상)

DTO 합쳐서 응답하자 - 내부클래스로 만듦, 모든걸 DTO로 옮기는 방식
@Data public static class DetailDTO { private Integer postId; private String title; private String content; private Integer userId; private String username; private String createdAt; private Boolean isPostOwner; public DetailDTO(Post post, User sessionUser){ this.postId = post.getId(); this.title = post.getTitle(); this.content = post.getContent(); this.userId = post.getUser().getId(); this.username = post.getUser().getUsername(); this.createdAt = post.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")); // 세션유저 받아서 isPostOwner 만듬 isPostOwner = false; if (sessionUser != null) { if (sessionUser.getId() == post.getUser().getId()) { isPostOwner = true; } } } }

11. 화면확인

notion image
아.. 됐다!!!
 
Share article

Coding_study