1. 추천 기능 추가하기
- [추천] 버튼을 통해 질문이나 답변을 본 다른 사용자들이 반응을 남길 수 있도록 '추천' 기능을 구현
1) 엔티티에 속성 추가
- 답변을 추천한 사용자(SiteUser)가 DB에 저장될 수 있도록 관련 속성을 질문, 답변 엔티티에 추가
- 하나의 질문에 여러 사람이 추천할 수 있고 한 사람이 여러 개의 질문을 추천할 수 있기 때문에 @ManyToMany 사용
Question.java
package com.example.demo.question;
import java.util.Set;
....
import jakarta.persistence.ManyToMany;
@Getter
@Setter
@Entity
public class Question {
....
@ManyToMany
Set<SiteUser> voter;
}
- @ManyToMany와 함께 Set<SiteUser> voter를 작성해 voter 속성을 다대다 관계로 설정하여 질문 엔티티에 추가
- set 자료형을 쓴 이유는 voter 속성값이 서로 중복되지 않도록 하기 위해서임
Answer.java
package com.example.demo.answer;
import java.util.Set;
...
import jakarta.persistence.ManyToMany; //다대다 관계
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
public class Answer {
...
@ManyToMany
Set<SiteUser>voter;
}
- @ManyToMany를 사용해 다대 관계로 석성을 생성하면 새로운 테이블을 만들어 관련 데이터를 관리
2) 질문 추천 기능 생성
templates/question_detail.html
...
<div class="my-3">
<!-- 추천 버튼 -->
<a href="javascript:void(0);" class="recommend btn btn-sm btn-outline-secondary"
th:data-uri="@{|/question/vote/${question.id}|}">
추천
<span class="badge rounded-pill bg-success" th:text="${#lists.size(question.voter)}"></span>
</a>
...
- lists.size 메서드에 question.voter를 사용하여 추천 수도 함께 보이게 함
- class 속성에 recommend를 적용해 자바스크립트로 data-uri에 정의된 URL이 호출되도록 함
(@{|/question/vote/${question.id}|}이 호출됨)
- [추천] 버튼을 눌렀을 때 메시지가 적힌 팝업 창을 통해 추천을 진행
question_detail.html
...
const recommend_elements = document.getElementByClassName("recommend");
Array.from(recomment_elements).forEach(function(element){
element.addEventListener('click', function(){
if(confirm("정말로 추천하시겠습니까?")){
location.href = this.dataset.uri;
};
});
});
..
QuestionService.java
@RequiredArgsConstructor
@Service
public class QuestionService {
...
//추천인 저장
public void vote(Question question, SiteUser siteUser) {
question.getVoter().add(siteUser);
this.questionRepository.save(question);
}
}
- 로그인한 사용자를 질문 엔티티에 추천인으로 저장하기 위해 vote 메서드 추가
QuestionController.java
@RequestMapping("/question")
@RequiredArgsConstructor
@Controller
public class QuestionController{
...
//질문 추천
@PreAuthorize("isAuthenticated()")
@GetMapping("/vote/{id}")
public String questionVote(Principal principal, @PathVariable("id") Integer id)
{
Question question = this.questionService.getQuestion(id);
SiteUser siteUser = this.userService.getUser(principal.getName());
this.questionService.vote(question,siteUser);
return String.format("redirect:/question/detail/%s", id);
}
}
- GET 방식으로 호출되는 @{|/question/vote/${question.id}|} URL을 처리하기 위해 questionVote 메서드 추가
- 로그인한 사람만 사용할 수 있도록 @PreAuthorize("isAuthenticated()") 적용
- QuestionService의 vote 메서드를 호출하여 사용자(SiteUser)를 추천인(voter)으로 저장
3) 답변 추천 기능 생성하기
templates/question_detail.html
- 답변의 추천 수를 표시하고, 답변을 추천할 수 있는 버튼 생성
...
<div class="my-3">
<a href="javascript:void(0);" class="recommend btn btn-sm btn-outline-secondary"
th:data-uri="@{|/answer/vote/${answer.id}|}">
추천
<span class="badge rounded-pill bg-success" th:text="${#lists.size(answer.voter)}"></span>
</a>
...
AnswerService.java
- 답변을 추천한 사람을 저장하는 vote 메서드 추가
@RequiredArgsConstructor
@Service
public class AnswerService {
...
//추천인 저장
public void vote(Answer answer, SiteUser siteUser) {
answer.getVoter().add(siteUser);
this.answerRepository.save(answer);
}
}
AnswerContorller.java
- GET 방식으로 호출되는 @{|/answer/vote/${answer.id}|} URL을 처리하기 위해 answerVote 메서드 추가
- 로그인한 사람만 가능해야 하므로 @PreAuthorize("isAuthenticated()")를 적용
- AnswerService의 vote 메서드를 호출하여 추천인을 저장
@RequestMapping("/answer")
@RequiredArgsConstructor
@Controller
public class AnswerController {
...
//추천
@PreAuthorize("isAuthenticated()")
@GetMapping("/vote/{id}")
public String answerVote(Principal principal, @PathVariable("id") Integer id)
{
Answer answer = this.answerService.getAnswer(id);
SiteUser siteUser = this.userService.getUser(principal.getName());
this.answerService.vote(answer, siteUser);
return String.format("redirect:/question/detail/%s", answer.getQuestion().getId());
}
}
2. 앵커 기능 추가하기
- 현재 답변을 작성하거나 수정하면 페이지 상단으로 스크롤이 이동해서 자신이 작성한 답변을 확인하려면 다시 스크롤을 내려서 확인해야 함
- HTML에는 URL 호출 시 원하는 위치로 이동해 주는 앵커(anchor) 태그 <a> 태그가 있는데, 이를 활용하면 답변 등록, 답변 수정, 답변 추천 시 앵커 태그를 이용하여 원하는 위치로 이동할 수 있음
- <a> 태그를 이용하여 다른 웹 페이지로 이동하거나 동일한 페이지 내에서 특정 위치로 스크롤하도록 만들 수 있음
1) 답변 앵커 추가하기
templates/question_detail.html
- 답변 작성, 수정 시에 이동해야 할 앵커 태그 추가
- 앵커 태그의 id 속성은 유일한 값이어야 하므로 답변의 id값을 사용
리다이렉트 수정
- 기존 URL 리다이렉트 코드
return String.format("redirect:/question/detail/%s", answer.getQuestion().getId());
- 리다이렉트되는 질문 상세 페이지 URL에 #answer_%s 삽입
- 답변 등록, 수정, 추천 부분에 추가
return String.format("redirect:/question/detail/%s#answer_%s",
answer.getQuestion().getId(), answer.getId());
2) 답변 서비스 수정하기
- 답변 컨트롤러에서 답변이 등록된 위치로 이동하려면 반드시 답변 객체 (Answer 객체)가 필요
AnswerService.java
...
public Answer create(Question question, String content, SiteUser author) {
Answer answer = new Answer();
answer.setContent(content);
answer.setCreateDate(LocalDateTime.now());
answer.setQuestion(question);
answer.setAuthor(author);
this.answerRepository.save(answer);
return answer;
}
...
3) 답변 컨트롤러 수정하기
AnswerController.java
'SpringBoot' 카테고리의 다른 글
[스프링부트 3 백엔드 개발자 되기] ch 0. 개발환경 구축하기 (0) | 2024.07.10 |
---|---|
[Do it] 3장 스프링 부트 고급 기능 익히기(6) (0) | 2024.01.25 |
[Do it] 3장 스프링 부트 고급 기능 익히기(4) (1) | 2024.01.24 |
[Do it] 3장 스프링 부트 고급 기능 익히기(3) (1) | 2024.01.23 |
[Do it] 3장 스프링 부트 고급 기능 익히기(2) (0) | 2024.01.23 |