(7) 답변 등록하기

답변 페이지 만들기


시작하기 전에

개요 : 질문과 답변을 할 수 있는 게시판 서비스를 스프링부트를 통해 만들어 본다.

학습사이트 : https://wikidocs.net/book/7601

예제 코드 : https://github.com/pahkey/sbb


질문 상세 화면에서 답변을 입력하기 위한 버튼을 생성하고, 이 버튼을 누르면 답변이 저장되도록 구현해보자


답변 등록 버튼 만들기


  • 질문 상세 테이블에 답변 등록 버튼 추가
  • question_detail.html 수정

      <!-- 경로 : sbb/src/main/resources/templates/question_detail.html -->
      <h1 th:text="${question.subject}"></h1>
      <div th:text="${question.content}"></div>
        
      <!-- 답변 등록 from태그 : post방식 -->
      <form th:action="@{|/answer/create/${question.id}|}" method="post">
          <textarea name="content" id="content" rows="15"></textarea>
          <input type="submit" value="답변등록">
      </form>
    

    1

    • 답변등록 버튼을 누르면 /answer/create/<질문id> url 호출
    • 아직 만들지 않았으므로 오류


답변 컨트롤러 만들기

  • AnswerController.java 만들기

      // 경로 : sbb/src/main/java/com/mysite/sbb/answer/AnswerController.java
      package com.mysite.sbb.answer;
        
      import com.mysite.sbb.question.Question;
      import com.mysite.sbb.question.QuestionService;
      import lombok.RequiredArgsConstructor;
      import org.springframework.stereotype.Controller;
      import org.springframework.ui.Model;
      import org.springframework.web.bind.annotation.PathVariable;
      import org.springframework.web.bind.annotation.PostMapping;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestParam;
        
      @RequestMapping("/answer") // URL 프리픽스 : 메서드 단위에서 (/answer) 생략 가능
      @RequiredArgsConstructor
      @Controller
      public class AnswerController {
        
          private final QuestionService questionService;
        
          // post요청만 받아들일 경우에 사용하는 에너테이션
          @PostMapping("/create/{id}") // (value=) 생략가능
          public String createAnswer(Model model, @PathVariable("id") Integer id,
          		@RequestParam String content) {
              Question question = this.questionService.getQuestion(id);
              // TODO: 답변을 저장하는 코드 예정
              return String.format("redirect:/question/detail/%s", id);
          }
      }
    
    • @RequestParam : 답변으로 입력한 내용을 넘겨주기 위해 추가
    • 템플릿의 form태그에 textarea의 name 속성명이 content이기 때문에 여기서도 변수명은 content로 사용해주어야 함
    • TODO: 아직 안한일을 적어두는 용도로, 지우고 그냥 주석으로 달아도 되긴 한다


답변 저장하기

답변을 저장하려면 엔티티 객체를 핸들링 해주는 서비스가 필요


  • AnswerService.java 만들기

      // 경로 : sbb/src/main/java/com/mysite/sbb/answer/AnswerService.java
      package com.mysite.sbb.answer;
        
      import com.mysite.sbb.question.Question;
      import lombok.RequiredArgsConstructor;
      import org.springframework.stereotype.Service;
        
      import java.time.LocalDateTime;
        
      @RequiredArgsConstructor
      @Service
      public class AnswerService {
          private final AnswerRepository answerRepository;
        
          // 답변 생성 메서드
          // form 태그로부터 받은 question과 content를 사용하여 객체를 생성하여 저장
          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);
          }
      }
    


  • AnswerController.java 수정
    • 서비스에서 작성한 create 메서드 사용
      // 경로 : sbb/src/main/java/com/mysite/sbb/answer/AnswerController.java
      package com.mysite.sbb.answer;
        
      import org.springframework.stereotype.Controller;
      import org.springframework.ui.Model;
      import org.springframework.web.bind.annotation.PathVariable;
      import org.springframework.web.bind.annotation.PostMapping;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestParam;
        
      import com.mysite.sbb.question.Question;
      import com.mysite.sbb.question.QuestionService;
        
      import lombok.RequiredArgsConstructor;
        
      @RequestMapping("/answer") // URL 프리픽스
      @RequiredArgsConstructor
      @Controller
      public class AnswerController {
        
          private final QuestionService questionService;
            
          // 변수 지정
          private final AnswerService answerService;
        
          // post요청만 받아들일 경우에 사용하는 에너테이션
          @PostMapping("/create/{id}") // (value=) 생략가능
          public String createAnswer(Model model, @PathVariable("id") Integer id,
          		@RequestParam String content) {
              Question question = this.questionService.getQuestion(id);
                
              // 답변저장
              this.answerService.create(question, content);
              return String.format("redirect:/question/detail/%s", id);
          }
      }
    
    • 이전에 TODO자리에 create 메서드를 호출하는 코드 작성


질문 상세 페이지에 답변 표시하기

답변을 저장하는 메서드는 잘 동작하지만, 템플릿에 표시하는 기능은 아직 추가하지 않았으므로 detail 템플릿 수정 필요


  • question_detail.html 수정

      <!-- 경로 : sbb/src/main/resources/templates/question_detail.html -->
      <h1 th:text="${question.subject}"></h1>
      <div th:text="${question.content}"></div>
        
      <!-- 답변을 확인할 수 있는 영역 추가 -->
      <h5 th:text="|${#lists.size(question.answerList)}개의 답변이 있습니다.|"></h5>
      <div>
          <ul>
              <li th:each="answer : ${question.answerList}" th:text="${answer.content}"></li>
          </ul>
      </div>
        
      <!-- 답변 등록 from태그 : post방식 -->
      <form th:action="@{|/answer/create/${question.id}|}" method="post">
          <textarea name="content" id="content" rows="15"></textarea>
          <input type="submit" value="답변등록">
      </form>
    
    • ${#lists.size(question.answerList) : 질문에 달린 답변의 갯수를 의미
    • 답변이 여러개일수도 있으므로 목록태그인 li 엘리먼트로 작성


저장된 답변 확인

2

답변이 웹에 잘 표시된다.

Leave a comment