반응형
오늘은 Spring Boot 기반 Q&A 게시판 구현의 심화 내용으로, 질문 목록과 상세 페이지, 답변 등록, 예외 처리 등을 중심으로 학습했습니다.
📌 주요 학습 내용
📌 QuestionRepository 인터페이스
public interface QuestionRepository extends JpaRepository<Question, Integer> {
Question findBySubject(String subject);
Question findBySubjectAndContent(String subject, String content);
List<Question> findBySubjectLike(String subject);
}
- Spring Data JPA의 메서드 이름 기반 쿼리 기능을 활용하여 다양한 조회 메서드를 정의.
📌 QuestionController
@Controller
@RequiredArgsConstructor
@RequestMapping("/question")
public class QuestionController {
private final QuestionService questionService;
@GetMapping("/list")
public String list(Model model) {
List<Question> questionList = this.questionService.getList();
model.addAttribute("questionList", questionList);
return "question_list";
}
@GetMapping("/detail/{id}")
public String detail(Model model, @PathVariable("id") Integer id) {
Question question = this.questionService.getQuestion(id);
model.addAttribute("question", question);
return "question_detail";
}
}
📌QuestionService
@Service
@RequiredArgsConstructor
public class QuestionService {
private final QuestionRepository questionRepository;
public List<Question> getList() {
return this.questionRepository.findAll();
}
public Question getQuestion(Integer id) {
Optional<Question> question = this.questionRepository.findById(id);
if (question.isPresent()) return question.get();
else throw new DataNotFoundException("해당 게시물을 찾을 수 없습니다.");
}
}
📌 DataNotFoundException
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "객체를 찾을 수 없습니다.")
public class DataNotFoundException extends RuntimeException {
public DataNotFoundException(String message) {
super(message);
}
}
- 게시물이 존재하지 않을 경우 예외를 발생시켜 사용자에게 오류 메시지를 전달.
📌 질문 상세 페이지 (question_detail.html)
<h1 th:text="${question.subject}"></h1>
<hr>
<div th:text="${question.content}"></div>
<h5 th:text="|${#lists.size(question.answerList)}개의 댓글이 있습니다.|"></h5>
<ul>
<li th:each="answer : ${question.answerList}" th:text="${answer.content}"></li>
</ul>
<form th:action="@{|/answer/create/${question.id}|}" method="post">
<textarea rows="3" cols="80" name="content"></textarea>
<input type="submit" value="답글 등록">
</form>
📌 Answer 관련 클래스
📌 AnswerController
@Controller
@RequiredArgsConstructor
@RequestMapping("/answer")
public class AnswerController {
private final QuestionService questionService;
private final AnswerService answerService;
public String createAnswer(Model model, @PathVariable("id") Integer id, @RequestParam("content") String content) {
Question question = this.questionService.getQuestion(id);
this.answerService.create(question, content);
return String.format("redirect:/question/detail/%s", id);
}
}
📌 AnswerService
@Service
@RequiredArgsConstructor
public class AnswerService {
private final AnswerRepository answerRepository;
public void create(Question question, String content) {
Answer answer = new Answer();
answer.setContent(content);
answer.setCreateDate(LocalDateTime.now());
answer.setQuestion(question);
this.answerRepository.save(answer);
}
}
💡 포인트 정리
- JpaRepository는 CRUD 기능뿐 아니라 쿼리 메서드도 지원.
- @ResponseStatus로 사용자 정의 예외 발생 시 HTTP 상태 코드 지정 가능.
- Thymeleaf로 동적 HTML 렌더링 + th:each로 댓글 반복 출력.
- @RequestParam과 @PathVariable을 함께 활용해 RESTful 요청 처리 가능.
📌정리하자면, 53일차에는 Spring Boot 프로젝트에서 질문 목록 출력, 질문 상세 조회, 댓글(답변) 등록까지 전체 흐름을 학습하였습니다. 이와 함께 사용자 정의 예외 처리까지 함께 적용함으로써 실전 웹 애플리케이션의 기초 구조를 갖췄습니다.
'국비' 카테고리의 다른 글
[ 56일차 18~21 ] 수업 정리 - Spring boot (1) | 2025.07.07 |
---|---|
[ 55일차 ] 복습 (0) | 2025.07.04 |
[ 54일차 15~17 ] 수업 정리 - Spring boot (2) | 2025.07.03 |
[ 52일차 ] 병결로 인한 휴식 (0) | 2025.07.02 |
[ 51일차 1~7 ] 수업 정리 - Spring boot (1) | 2025.06.30 |
[ 48~50일차 ] 복습 및 시험 (1) | 2025.06.28 |