본문 바로가기

Spring

[Spring]Spring 시작해보기(9) - 답글 달기 form 생성 및 출력

 detail 페이지까지 생성했는데, 댓글을 달 수 있는 곳도 있어야 하지 않을까?

 

그러기 위해 Answer을 등록할 수 있는 form을 생성해 출력시키도록 해보자.

 

1. 답변 등록 Form 생성

question_detail.html을 수정하여 form을 생성할 수 있도록 하자.

<form> 태그안에는 <textarea>태그를 넣어 답변을 넣어줄 수 있도록 하고, <input> 태그에는 전송할 수 있는 submit을 넣는다.

 

여기서 form에는 현재 question_id를 가져와 해당 id에 대한 answer을 생성할 수 있도록 한다.

<form>태그 안에서는 action을 동작할 URL을 사용한다.(여기서 question_id를 가져온다.)

<form th:action="@{|/answer/create/${question.id}|}" method="post">
    <textarea name="content" id="content" rows="15"></textarea>
    <input type="submit" value="답변등록">
</form>

결과는

textarea로 잘 나온다.

 

2. 답변 생성 컨트롤러 생성 및 URL 매핑 처리

textarea처럼 많은 내용을 파라미터로 불러올 수 없기 때문에 POST 방식으로 불러올 수 있도록 하였고, controller에서 POST를 받아야 하기 때문에 PostMapping을 사용하였다.

 

<form>에서 얻은 값을 사용하기 위해 @RequestParam 어노테이션을 사용하고, <form>내의 태그 중 name에 적은 속성명과 같게 적어야 한다.

@RequestMapping("/answer")
@RequiredArgsConstructor
@Controller
public class AnswerController {

    private final QuestionService questionService;

    @PostMapping("/create/{id}")
    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);
    }
}

 

 

3. 답변 저장하기

이제 답변을 저장하기 위해 Service를 통해 Repository로 이동시켜 실행할 수 있도록 한다.

설정자를 통해 Answer 엔티티의 컬럼의 값들을 모두 입력하여 Repository를 통해 save 시켜준다.

@RequiredArgsConstructor
@Service
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);
    }
}

Service를 만들었다면, Controller도 수정해주어야 한다.

@RequestMapping("/answer")
@RequiredArgsConstructor
@Controller
public class AnswerController {

    private final QuestionService questionService;
    private final AnswerService answerService;

    @PostMapping("/create/{id}")
    public String createAnswer(Model model, @PathVariable("id") Integer id, @RequestParam String content) {
        Question question = this.questionService.getQuestion(id);
        this.answerService.create(question, content);
        // TODO: 답변을 저장한다.
        return String.format("redirect:/question/detail/%s", id);
    }
}

 

 

4. detail에 답변 출력

form으로 Answer 엔티티에 저장된 내용을 출력하도록 해보자.

<h1 th:text="|제목 : ${question.subject}|"></h1>
<div th:text="|날짜 : ${#temporals.format(question.createDate, 'yy-MM-dd')}|"></div>
<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}, 시간 : ${#temporals.format(answer.createDate, 'yy-MM-dd')}|"></li>
    </ul>
</div>

<form th:action="@{|/answer/create/${question.id}|}" method="post">
    <textarea name="content"rows="15" required></textarea>
    <input type="submit" value="답변등록">
</form>

여기서 나온 $(#lists.size(question.answerList)}는 타임리프가 제공하는 유틸리티이다. 객체의 길이를 반환하여 Answer의 총 갯수를 출력한다. required를 사용해 textarea가 비어 있으면 submit되지 않도록 했다.

 

추가적으로 만든 날짜를 출력시키기 위해 createDate를 넣었다.

하지만 날짜이 너무 길게 나와 format을 시켜주었는데, 이 때 #temporals.format(createDate, formatting)을 사용하면 된다.