기록방
16장 : 웹 페이지에서 댓글 목록 보기 본문
길벗 IT도서에서 주관하는 코딩 자율학습단 8기 : Spring Boot 파트에 참여한 기록입니다 [ 목록 ]
16.1 댓글 보기의 개요
- 특정 게시글의 상세 페이지(show)에서 아래에 댓글 목록(comments)이 보이게 됨
- 기존 댓글을 보여주는 영역(list)와 새 댓글을 입력하는 영역(new)로 나뉨
- 두 댓글 영역은 별도의 뷰 페이지를 만들어 게시글 상세 페이지 아래에 삽입하는 형태로 구현
16.2 댓글 뷰 페이지 삽입하기
{{>layouts/header}}
<table class="table">
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Title</th>
<th scope="col">Content</th>
</tr>
</thead>
<tbody>
{{#article}}
<tr>
<th>{{id}}</th>
<td>{{title}}</td>
<td>{{content}}</td>
</tr>
{{/article}}
</tbody>
</table>
<a href="/articles/{{article.id}}/edit" class="btn btn-primary">Edit</a>
<a href="/articles/{{article.id}}/delete" class="btn btn-danger">Delete</a>
<a href="/articles">Go to Articles List</a>
{{>comments/_comments}} <!--상세 페이지에 댓글 뷰 파일 삽입-->
{{>layouts/footer}}
- show.mustache에 댓글 목록 뷰 추가
<div>
<!--댓글 목록 보기-->
{{>comments/_list}}
<!--새 댓글 작성하기-->
{{>comments/_new}}
</div>
coments/_comments.mustache
는 댓글 목록과 새 댓글 작성 뷰로 이루어짐
<div id="comments-list">
{{#commentDtos}}
<div class="card m-2" id="comments-{{id}}">
<div class="card-header">
{{nickname}}
</div>
<div class="card-body">
{{body}}
</div>
</div>
{{/commentDtos}}
</div>
_list.mustache
16.3 댓글 목록 가져오기
@Controller
@Slf4j
public class ArticleController {
@Autowired
private ArticleRepository articleRepository;
@Autowired
private CommentService commentService;
@GetMapping("/articles/{id}") // 데이터 조회 요청 접수 - PathVariable
public String show(@PathVariable Long id, Model model) { // 매개 변수로 id 받아오기
log.info("id = " + id); // id를 잘 받았는지 확인하는 로그 찍기
// 1. id를 조회해 데이터 가져오기
Article articleEntity = articleRepository.findById(id).orElse(null);
// Optional<Article> articleEntity = articleRepository.findById(id);
List<CommentDto> commentDtos = commentService.comments(id);
// 2. 모델에 데이터 등록하기
model.addAttribute("article", articleEntity);
model.addAttribute("commentDtos", commentDtos);
// 3. 조회한 데이터를 사용자에게 보여 주기 위한 뷰 페이지 만들고 반환하기
return "articles/show";
}
}
ArticleController
수정 : 댓글 목록(commentsDtos)을 model에 넣어줌
🚀 1분 퀴즈
- 뷰 페이지에서 사용할 변수는 모델에 등록해야 사용할 수 있다. ( O )
- 머스테치 문법 {{#data}} - {{/data}} 에서 data 값이 없는 경우, 내부 영역은 보이지 않는다. ( O )
- 머스테치 문법 {{#data}} - {{/data}} 에서 data 값이 있는 경우, 내부 영역은 한 번만 출력 된다. ( X )
- 부트스트랩은 웹 페이지 개발을 위한 다양한 도구를 제공한다. ( O )
✅ 셀프 체크
- 다음은 2022 카타르 월드컵의 그룹 H에 편성된 나라의 목록입니다.
- Portygal, Ghana, Uruguay, Korea Republic
- 이를 상세 페이지에서 보기 위한 코드는 다음과 같습니다.
{{>layouts/header}}
<h1>{{groupname}}</h1>
{ol}
{{#teamDtoList}}
<li><img src="{{imageUrl}}"><span>{{name}}</span></li>
{{/teamDtoList}}
{/ol}
{{>layouts/footer}}
- groups/show.mustache가 정상적으로 동작하도록 다음 컨트롤러 코드를 완성하세요.
(동작에 필요한 엔티티, 리포지토리, 서비스, DTO는 모두 올바르게 동작한다고 가정합니다)
package com.example.firstproject.controller;
import com.example.firstproject.dto.CommentDto;
import com.example.firstproject.entity.Article;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.ui.Model;
import java.util.List;
@Controller
@Slf4j
public class GroupController {
@Autowired
private GroupService groupService;
@Autowired
private TeamService teamService;
@GetMapping("/groups/{id}") // 데이터 조회 요청 접수 - PathVariable
public String show(@PathVariable Long groupId, Model model) { // 매개 변수로 id 받아오기
// 1. id를 조회해 데이터 가져오기
GroupDto groupDto = groupService.getGroup(groupId);
List<TeamDto> teamDtos = teamService.getTeamsOnGroup(groupId);
// 2. 모델에 데이터 등록하기
model.addAttribute("groupname", groupDto.getName());
model.addAttribute("teamDtoList", teamDtos);
// 3. 조회한 데이터를 사용자에게 보여 주기 위한 뷰 페이지 만들고 반환하기
return "groups/show";
}
}
🏓 더 알아볼 내용
1. PUT과 PATCH의 차이
책에서는 업데이트할 때 PATCH
메서드를 사용하는데요. PATCH
말고도 PUT
이라는 메서드도 존재합니다. 두 메서드 모두 업데이트 시에 사용되는 메서드이죠. 하지만 좀 더살펴보면 두 메서드는 규약부터 다른 것을 알 수 있습니다.
1) PUT
RFC 문서에 따르면 PUT
메서드는 요청한 URI의 payload로 자원을 대체하는 메서드 입니다.
저장 혹은 변경을 의미하죠. Upsert(Update + insert)와 일맥상통합니다.
2) PATCH
RFC 문서에 따르면 PATCH
요청은 자원에 대한 부분적인 수정을 적용하기 위한 HTTP
메서드입니다. 예를 들어 User의 정보를 수정하는 PATCH
요청을 보낼 때, User의일부만으로 수정 요청을 해도 기존에 있던 User의 값이 날아가지 않고 정상적으로 수정되는 것을 생각할 수 있습니다.
3) 요약
PUT
은 전체 대체 혹은 삽입, PATCH
는 일부 수정을 하는 역할을 합니다. 하지만 HTTP
메서드는 규약일 뿐 특정 행동을 강제할 수 없습니다. 실제로 코드에서 어떻게 구현하느냐에 따라서 많이 다릅니다.
2. Soft Delete vs Hard Delete
‘댓글 삭제’ 부분에서 다루면 좋을 것 같아 해당 내용을 추가합니다. 책에서는 DB에서 데이터를 직접 삭제 시키죠. 하지만 어떤 데이터는 DB에서 직접 삭제하지 않는 데이터도 존재합니다. User의 경우 대부분의 사이트에서 삭제한 후 2주 후에 진짜로 삭제가 되는 경우가 있죠.
위 두 가지 방법을 각각 Hard Delete, Soft Delete이라고 합니다. Hard Delete는 말 그대로
DB에서 곧바로 삭제하는 것입니다. JpaRespoitory.delete(data)인 것이죠. 반면 Soft Delete는 DB에서 데이터를 바로 삭제하지 않습니다. 애플리케이션에서 삭제되었음을 알려주기만 하는 것이죠. Soft Delete를 하는 대표적인 방식으로 deletedAt 혹은 removedAt 필드를 넣는 방법이 있습니다.
@Getter
@AllArgsConstructor
@NoArgsContstructor
public class User {
private Long id;
private String name;
private Instant deletedAt;
public void delete() {
this.deletedAt = Instant.now();
}
}
이렇게 할 경우, UserService에서 user를 삭제시킬 때 user.delete()를 호출하면 됩니다.
그리고 user를 찾아올 때도 조건을 하나 더 추가해야겠죠!
public interface UserRepository extends JpaRepository<User, Long> {
@Query("select * from users u where u.deletedAt is null")
List<User> findAllUser();
}
데이터를 삭제할 때는 Hard Delete와 Soft Delete 중 어떤 방법을 사용할지 고려해야 합니다.
데이터를 반드시 삭제해야 한다면 Hard Delete. 데이터를 삭제하지 않아도 되고, 이후 사용해야 할 필요하기 있다면 Soft Delete를 사용하는 것이 좋습니다.
'FrameWork > Spring' 카테고리의 다른 글
18장 : 웹 페이지에서 댓글 수정하기 (0) | 2024.07.30 |
---|---|
17장 : 웹 페이지에서 댓글 등록하기 (0) | 2024.07.30 |
15장 : 댓글 컨트롤러와 서비스 만들기 (0) | 2024.07.10 |
14장 : 댓글 엔티티와 리포지토리 만들기 (0) | 2024.07.10 |
13장 : 테스트 코드 작성하기 (0) | 2024.07.09 |