02K. ๋ต๋ณ ๋ฑ๋ก
02K. ๋ต๋ณ ๋ฑ๋ก ๊ด๋ จ
์ ์ ์์ ์ฐ๋ฆฌ๋ ์ง๋ฌธ์ ์กฐํํ๋ ๊ธฐ๋ฅ์ ๋ง๋ค์๋ค. ์ด๋ฒ์๋ ์ง๋ฌธ์ ๋ต๋ณ์ ๋ฑ๋กํ๊ณ ๋ณด์ฌ ์ฃผ๋ ๊ธฐ๋ฅ์ ๋ง๋ค์ด ๋ณด์. ์ง๋ฌธ ์์ธ ํ๋ฉด์ ๋ต๋ณ์ ์ ๋ ฅํ๊ธฐ ์ํ ํ ์คํธ ์ฐฝ(textarea)๊ณผ <๋ต๋ณ๋ฑ๋ก> ๋ฒํผ์ ์์ฑํ๊ณ , ์ด ๋ฒํผ์ ๋๋ฅด๋ฉด ๋ต๋ณ์ด ์ ์ฅ๋๋๋ก ๊ตฌํํด ๋ณด์.
๋ต๋ณ ๋ฑ๋ก ๋ฒํผ ๋ง๋ค๊ธฐ
์ง๋ฌธ ์์ธ ํ
ํ๋ฆฟ์ ๋ต๋ณ ์ ์ฅ์ ์ํ form
, textarea
, input
์๋ฆฌ๋จผํธ๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์ถ๊ฐํ์.
ํ์ผ๋ช :
/sbb/src/main/resources/templates/
question_detail.html
<h1 th:text="${question.subject}"></h1>
<div th:text="${question.content}"></div>
<form th:action="@{|/answer/create/${question.id}|}" method="post">
<textarea name="content" id="content" rows="15"></textarea>
<input type="submit" value="๋ต๋ณ๋ฑ๋ก">
</form>
<๋ต๋ณ๋ฑ๋ก>
๋ฒํผ์ ๋๋ฅด๋ฉด ์ ์ก๋๋ form์ action์ ํ์๋ฆฌํ์ "th:action
" ์์ฑ์ผ๋ก ์์ฑํ๋ค. ์์ ๊ฐ์ด ์ถ๊ฐํ๊ณ ์ง๋ฌธ ์์ธ ํ์ด์ง์ ์ ์ํด ๋ณด์.
์ด์ <๋ต๋ณ๋ฑ๋ก>
๋ฒํผ์ ๋๋ฅด๋ฉด POST ๋ฐฉ์์ผ๋ก /answer/create/<์ง๋ฌธid>
URL์ด ํธ์ถ(submit
)๋ ๊ฒ์ด๋ค.
์ด ์ค๋ฅ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ๋ต๋ณ ์ปจํธ๋กค๋ฌ๋ฅผ ๋ง๋ค๊ณ ํด๋น URL์ ๋ํ ๋งคํ์ ์ฒ๋ฆฌํด์ผ ํ๋ค.
๋ต๋ณ ์ปจํธ๋กค๋ฌ ๋ง๋ค๊ธฐ
์์์ ์ง๋ฌธ ์ปจํธ๋กค๋ฌ๋ฅผ ๋ง๋ค์๋ฏ์ด ๋ต๋ณ ์ปจํธ๋กค๋ฌ๋ฅผ ๋ง๋ค์ด ๋ณด์.
ํ์ผ๋ช :
/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")
@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);
}
}
๋ต๋ณ ์ปจํธ๋กค๋ฌ์ URL ํ๋ฆฌํฝ์ค๋ /answer
๋ก ๊ณ ์ ํ๋ค. ๊ทธ๋ฆฌ๊ณ /answer/create/{id}
์ ๊ฐ์ URL ์์ฒญ์ createAnswer
๋ฉ์๋๊ฐ ํธ์ถ๋๋๋ก @PostMapping
์ผ๋ก ๋งคํํ๋ค. @PostMapping
์ @GetMapping
๊ณผ ๋์ผํ๊ฒ ๋งคํ์ ๋ด๋นํ๋ ์ญํ ์ ํ์ง๋ง POST์์ฒญ๋ง ๋ฐ์๋ค์ผ ๊ฒฝ์ฐ์ ์ฌ์ฉํ๋ค. ๋ง์ฝ ์ URL์ GET๋ฐฉ์์ผ๋ก ์์ฒญํ ๊ฒฝ์ฐ์๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
@PostMapping(value="/create/{id}")
๋์@PostMapping("/create/{id}")
์ฒ๋ผ value๋ ์๋ตํด๋ ๋๋ค.
๊ทธ๋ฆฌ๊ณ createAnswer
๋ฉ์๋์ ๋งค๊ฐ๋ณ์์๋ @RequestParam String content
ํญ๋ชฉ์ด ์ถ๊ฐ๋์๋ค. ์ด ํญ๋ชฉ์ ํ
ํ๋ฆฟ์์ ๋ต๋ณ์ผ๋ก ์
๋ ฅํ ๋ด์ฉ(content
)์ ์ป๊ธฐ ์ํด ์ถ๊ฐ๋์๋ค. ํ
ํ๋ฆฟ์ ๋ต๋ณ ๋ด์ฉ์ ํด๋นํ๋ textarea
์ name
์์ฑ๋ช
์ด content
์ด๊ธฐ ๋๋ฌธ์ ์ฌ๊ธฐ์๋ ๋ณ์๋ช
์ content
๋ก ์ฌ์ฉํด์ผ ํ๋ค. ๋ง์ฝ content
๋์ ๋ค๋ฅธ ์ด๋ฆ์ผ๋ก ์ฌ์ฉํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํ ๊ฒ์ด๋ค.
createAnswer
๋ฉ์๋์ URL ๋งคํ /create/{id}
์์ {id}
๋ ์ง๋ฌธ์ id ์ด๋ฏ๋ก ์ด id ๊ฐ์ผ๋ก ์ง๋ฌธ์ ์กฐํํ๊ณ ์์ ๊ฒฝ์ฐ์๋ 404 ์ค๋ฅ๊ฐ ๋ฐ์ํ ๊ฒ์ด๋ค. ํ์ง๋ง ์์ง ๋ต๋ณ์ ์ ์ฅํ๋ ์ฝ๋๋ฅผ ์์ฑํ์ง ์๊ณ ์ผ๋จ ๋ค์๊ณผ ๊ฐ์ ์ฃผ์์ผ๋ก ๋ต๋ณ์ ์ ์ฅํด์ผ ํจ์ ๋ํ๋ด์๋ค.
// TODO: ๋ต๋ณ์ ์ ์ฅํ๋ค.
๋ต๋ณ ์ ์ฅํ๊ธฐ
์ด์ ๋ต๋ณ์ ์ ์ฅํ๋ ์ฝ๋๋ฅผ ์์ฑํด ๋ณด์. ๋ต๋ณ์ ์ ์ฅํ๋ ค๋ฉด ๋ต๋ณ ์๋น์ค๊ฐ ํ์ํ๋ค. AnswerService
๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ์.
ํ์ผ๋ช :
/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;
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);
}
}
AnswerService
์๋ ๋ต๋ณ ์์ฑ์ ์ํด create
๋ฉ์๋๋ฅผ ์ถ๊ฐํ๋ค. create
๋ฉ์๋๋ ์
๋ ฅ์ผ๋ก ๋ฐ์ question๊ณผ content
๋ฅผ ์ฌ์ฉํ์ฌ Answer
๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ์ ์ฅํ๋ค.
์ด์ ์์ฑํ create
๋ฉ์๋๋ฅผ AnswerController
์์ ์ฌ์ฉํด ๋ณด์.
ํ์ผ๋ช :
/sbb/src/main/java/com/mysite/sbb/answer/
AnswerController.java
(... ์๋ต ...)
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);
return String.format("redirect:/question/detail/%s", id);
}
}
์ฃผ์๋ฌธ์ ์ญ์ ํ๊ณ AnswerService
์ create
๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ๋ต๋ณ์ ์ ์ฅํ ์ ์๊ฒ ํ๋ค.
์ด์ ๋ค์ ์ง๋ฌธ ์์ธ ํ์ด์ง์ ์ ์ํ์ฌ ํ
์คํธ ์ฐฝ์ ์๋ฌด ๊ฐ์ด๋ ์
๋ ฅํ๊ณ <๋ต๋ณ๋ฑ๋ก>
์ ๋๋ฌ ๋ณด์. ๋ต๋ณ์ ์ ์ ์ฅ๋์๋ค.
ํ์ง๋ง ์ฌ์ ํ ํ๋ฉด์๋ ์๋ฌด๋ฐ ๋ณํ๊ฐ ์๋ค. ์ ๊ทธ๋ด๊น?
์๋ํ๋ฉด ์ฐ๋ฆฌ๋ ์์ง ๋ฑ๋กํ ๋ต๋ณ์ ํ ํ๋ฆฟ์ ํ์ํ๋ ๊ธฐ๋ฅ์ ์ถ๊ฐํ์ง ์์๊ธฐ ๋๋ฌธ์ด๋ค.
์ง๋ฌธ ์์ธ ํ์ด์ง์ ๋ต๋ณ ํ์ํ๊ธฐ
์ง๋ฌธ์ ๋ฑ๋ก๋ ๋ต๋ณ์ ์์ธ ํ๋ฉด์ ํ์ํด ๋ณด์. ๋ต๋ณ์ ๋ฑ๋ก๋ ์ง๋ฌธ ๋ฐ์ ๋ณด์ฌ์ผ ํ๋ฏ๋ก ์ง๋ฌธ ์์ธ ํ ํ๋ฆฟ์ ๋ค์์ ์ฝ๋๋ฅผ ์ถ๊ฐํ์.
ํ์ผ๋ช :
/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>
<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)}
๋ ๋ต๋ณ ๊ฐ์๋ฅผ ์๋ฏธํ๋ค. #lists.size(์ดํฐ๋ฌ๋ธ๊ฐ์ฒด)
๋ ํ์๋ฆฌํ๊ฐ ์ ๊ณตํ๋ ์ ํธ๋ฆฌํฐ๋ก ๊ฐ์ฒด์ ๊ธธ์ด๋ฅผ ๋ฐํํ๋ค. ๋ต๋ณ์ question
๊ฐ์ฒด์ answerList
๋ฅผ ์ํํ์ฌ <li>
์๋ฆฌ๋จผํธ๋ก ํ์ํ๋ค.
์ถํํ๋ค! ์ด์ ์ฌ๋ฌ๋ถ์ ๋ต๋ณ์ ์ ์ฅํ๊ณ ํ์ธํ ์ ์๊ฒ ๋์๋ค.