국비

[ 53일차 8~14 ] 수업 정리 - Spring boot

코딩하는냥이 2025. 7. 2. 16:24
반응형

오늘은 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 프로젝트에서 질문 목록 출력, 질문 상세 조회, 댓글(답변) 등록까지 전체 흐름을 학습하였습니다. 이와 함께 사용자 정의 예외 처리까지 함께 적용함으로써 실전 웹 애플리케이션의 기초 구조를 갖췄습니다.