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
)๋ ๊ฒ์ด๋ค.

/answer/create/<์ง๋ฌธid>
URL์ ๋ํ ๋งคํ์ด ์์ผ๋ฏ๋ก ๋ฒํผ์ ๋๋ฅด๋ฉด ๋ค์๊ณผ ๊ฐ์ 404 ํ์ด์ง๊ฐ ๋ํ๋๋ค.์ด ์ค๋ฅ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ๋ต๋ณ ์ปจํธ๋กค๋ฌ๋ฅผ ๋ง๋ค๊ณ ํด๋น 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>
์๋ฆฌ๋จผํธ๋ก ํ์ํ๋ค.

์ถํํ๋ค! ์ด์ ์ฌ๋ฌ๋ถ์ ๋ต๋ณ์ ์ ์ฅํ๊ณ ํ์ธํ ์ ์๊ฒ ๋์๋ค.