03M. ๋งํฌ๋ค์ด
03M. ๋งํฌ๋ค์ด ๊ด๋ จ
์ง๋ฌธ์ด๋ ๋ต๋ณ์ ์์ฑํ ๋ ์ผ๋ฐ์ ์ธ ํ ์คํธ ์ธ์ ๊ธ์๋ฅผ ์งํ๊ฒ ํ์ํ๊ฑฐ๋ ๋งํฌ๋ฅผ ์ถ๊ฐํ๊ณ ์ถ์ ์๋ ์๋ค. "๋งํฌ๋ค์ด"์ด๋ผ๋ ๊ธ์ฐ๊ธฐ ๋๊ตฌ๋ฅผ ์ด์ฉํ๋ฉด ์ด๋ฐ ๊ฒ๋ค์ ์ฝ๊ณ ๊ฐ๋จํ๊ฒ ํํํ ์ ์๋ค.
์ด๋ฒ์๋ SBB์ ๋งํฌ๋ค์ด์ ์ ์ฉํด ๋ณด์.
๋งํฌ๋ค์ด์ ์น ์ฌ์ดํธ์์ ์ฌ์ฉํ๋ ๊ธ ์ฐ๊ธฐ ๋๊ตฌ๋ก Github๋ฑ ๋ง์ ์ฌ์ดํธ์์ ์ฌ์ฉํ๋ค.
๋งํฌ๋ค์ด ๋ฌธ๋ฒ
SBB์ ๋งํฌ๋ค์ด์ ์ ์ฉํ๊ธฐ ์ ์ ๋งํฌ๋ค์ด์ ๋ฌธ๋ฒ์ ๋จผ์ ์์๋ณด์.
๋ฆฌ์คํธ
๋ชฉ๋ก์ ํ์ํ๊ธฐ ์ํด ๋ค์์ฒ๋ผ ์์ฑํ๋ค.
* ์๋ฐ
* ์คํ๋ง๋ถํธ
* ์๊ณ ๋ฆฌ์ฆ
์ ๋ฌธ์์ด์ ๋งํฌ๋ค์ด ํด์๊ธฐ๊ฐ HTML๋ก ๋ณํํ๋ฉด ์ค์ ํ๋ฉด์์๋ ๋ค์๊ณผ ๊ฐ์ด ๋ณด์ธ๋ค.
<ul>
<li>์๋ฐ</li><li>์คํ๋ง๋ถํธ</li><li>์๊ณ ๋ฆฌ์ฆ</li>
</ul>
๋งํฌ๋ค์ด ํด์๊ธฐ๋ ์กฐ๊ธ ํ์ ์ค์นํ๊ณ ์ค์ตํ ๊ฒ์ด๋ ์ฐ์ ์ ๋งํฌ๋ค์ด ๋ฌธ๋ฒ์ ์ตํ๋ณด์.
์์๊ฐ ์๋ ๋ชฉ๋ก์ ํ์ํ๋ ค๋ฉด ๋ค์์ฒ๋ผ ์์ฑํ๋ค.
1. ํ๋
2. ๋
3. ์
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
<ol>
<li>ํ๋</li><li>๋</li><li>์
</li>
</ol>
๊ฐ์กฐ
์์ฑํ ๊ธ์๋ฅผ ๊ฐ์กฐ ํ์ํ๋ ค๋ฉด ๊ฐ์กฐํ ํ ์คํธ ์์ชฝ์ **๋ฅผ ๋ฃ์ด ๊ฐ์ผ๋ค.
์คํ๋ง๋ถํธ๋ **์๋ฐ**๋ก ๋ง๋ค์ด์ง ์น ํ๋ ์์ํฌ์ด๋ค.
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
์คํ๋ง๋ถํธ๋ <em>์๋ฐ</em>๋ก ๋ง๋ค์ด์ง ์น ํ๋ ์์ํฌ์ด๋ค.
๋งํฌ
HTML ๋งํฌ๋ ๋ค์์ฒ๋ผ [๋งํฌ๋ช
](๋งํฌ์ฃผ์)
๊ท์น์ ์ ์ฉํ์ฌ ์์ฑํ๋ค.
์คํ๋ง ํํ์ด์ง๋ [https://spring.io](https://spring.io) ์
๋๋ค.
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
์คํ๋ง ํํ์ด์ง๋ <a href="https://spring.io">https://spring.io</a> ์
๋๋ค.
์์ค์ฝ๋
์์ค์ฝ๋๋ ๋ฐฑ์ฟผํธ ` 3๊ฐ๋ฅผ ์ฐ์ด์ด ๋ถ์ฌ ์์๋๋ก ๊ฐ์ธ๋ฉด ์์ฑํ ์ ์๋ค.
๋ฐฑ์ฟผํธ๋ ๋ฐฑํฑ์ด๋ผ๊ณ ๋ ํ๋ค.
\`\`\`
package com.mysite.sbb;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
@GetMapping("/hello")
@ResponseBody
public String hello() {
return "Hello Spring Boot Board";
}
}
\`\`\`
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
package com.mysite.sbb;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
@GetMapping("/hello")
@ResponseBody
public String hello() {
return "Hello Spring Boot Board";
}
}
์ธ์ฉ
์ธ์ฉ์ ํ์ํ๋ ค๋ฉด ๋ค์์ฒ๋ผ >
๋ฅผ ๋ฌธ์ฅ ๋งจ ์์ ์
๋ ฅํ๊ณ 1์นธ ๋์ด์ฐ๊ธฐ๋ฅผ ํ ๋ค์ ์ธ์ฉ๊ตฌ๋ฅผ ์
๋ ฅํ๋ค.
> ๋งํฌ๋ค์ด์ Github์์ ์ฌ์ฉํ๋ ๊ธ์ฐ๊ธฐ ๋๊ตฌ์ด๋ค.
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
<blockquote>
<p>๋งํฌ๋ค์ด์ Github์์ ์ฌ์ฉํ๋ ๊ธ์ฐ๊ธฐ ๋๊ตฌ์ด๋ค.</p>
</blockquote>
๋งํฌ๋ค์ด์ ๋ณด๋ค ์์ธํ ์ฌ์ฉ๋ฐฉ๋ฒ์ ๋ค์ ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์.
๋งํฌ๋ค์ด ๋ฌธ๋ฒ ๊ณต์ ๋ฌธ์: www.markdownguide.org/getting-started
๋งํฌ๋ค์ด ์ค์น
SBB์ ๋งํฌ๋ค์ด ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ ค๋ฉด ๋งํฌ๋ค์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํด์ผ ํ๋ค. ๋ค์์ฒ๋ผ build.gradle ํ์ผ์ ์์ ํ์ฌ ๋งํฌ๋ค์ด์ ์ค์นํ์.
ํ์ผ๋ช :
/sbb/
build.gradle
// (... ์๋ต ...)
dependencies {
// (... ์๋ต ...)
implementation 'org.commonmark:commonmark:0.21.0'
}
// (... ์๋ต ...)
.["Refresh Gradle Project"]
๋ฅผ ์คํํ์ฌ ์ต์ ๋ฒ์ ์ธ 0.21.0 ๋ฒ์ ์ commonmark
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํ์.
๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น ํ ๋ก์ปฌ์๋ฒ ์ฌ์์๋ ์์ง๋ง์.
build.gradle ํ์ผ์์ commonmark์ ๋ฒ์ ์ ๋ณด๊ฐ ํ์ํ ์ด์
์ง๊ธ๊น์ง build.gradle
ํ์ผ์ ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ฑ๋กํ ๋ ๋ฒ์ ์ ๋ช
์ํ์ง ์์๋ค. ํ์ง๋ง commonmark๋ ์์ ๊ฐ์ด 0.21.0 ์ด๋ผ๋ ๋ฒ์ ์ ์ง์ ํด ์ฃผ์ด์ผ๋ง ํ๋ค. ์ด ์ฐจ์ด๋ ์คํ๋ง๋ถํธ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ด๋ฆฌ ๋ฐฉ์๋๋ฌธ์ด๋ค. ์คํ๋ง๋ถํธ๊ฐ ๋ด๋ถ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํฌํจ๋๋ฉด ๋ฒ์ ์ ๋ณด๊ฐ ํ์์๊ณ ํฌํจ๋์ง ์์ผ๋ฉด ๋ฒ์ ์ ๋ณด๊ฐ ํ์ํ๋ค. ์ฆ, commonmark๋ ์คํ๋ง๋ถํธ๊ฐ ๋ด๋ถ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋๋ค.
์คํ๋ง๋ถํธ๊ฐ ๊ด๋ฆฌํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ฒฝ์ฐ ๋ฒ์ ์ ๋ณด๋ฅผ ๋ช ์ํ์ง ์์ผ๋ฉด ์คํ๋ง๋ถํธ๊ฐ ๊ฐ์ฅ ๊ถํฉ์ด ์ ๋ง๋ ๋ฒ์ ์ผ๋ก ์๋ ์ ํํ๋ค. ๋ฐ๋ผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ํธํ์ฑ์ ์๊ฐํ๋ค๋ฉด ๋ฒ์ ์ ๋ณด๋ ๋ฐ๋ก ์ ๋ ฅํ์ง ์๋ ํธ์ด ์ข๋ค.
๋งํฌ๋ค์ด ์ปดํฌ๋ํธ
์ด์ ์ง๋ฌธ์ด๋ ๋ต๋ณ์ "๋ด์ฉ"์ ๋งํฌ๋ค์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ์ฉํด์ผ ํ๋ค. ์ปจํธ๋กค๋ฌ์์ ์ง๋ฌธ์ด๋ ๋ต๋ณ์ ์กฐํํ ํ์ ๋งํฌ๋ค์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ์ฉํ๋ฉด ๋ณํ๋ HTML์ ์ป์ ์ ์๋ค. ํ์ง๋ง ์ฌ๊ธฐ์๋ ๊ทธ๋ณด๋ค๋ ์ข ๋ ๋ฒ์ฉ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ ๋งํฌ๋ค์ด ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๊ณ ํ์๋ฆฌํ ํ ํ๋ฆฟ์์ ์์ฑํ ๋งํฌ๋ค์ด ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ณด์.
๋ค์์ฒ๋ผ CommonUtil
์ปดํฌ๋ํธ๋ฅผ ์์ฑํ์.
ํ์ผ๋ช :
/sbb/src/main/java/com/mysite/sbb/
CommonUtil.java
package com.mysite.sbb;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.springframework.stereotype.Component;
@Component
public class CommonUtil {
public String markdown(String markdown) {
Parser parser = Parser.builder().build();
Node document = parser.parse(markdown);
HtmlRenderer renderer = HtmlRenderer.builder().build();
return renderer.render(document);
}
}
@Component
์ ๋ํ
์ด์
์ ์ฌ์ฉํ์ฌ CommonUtil
ํด๋์ค๋ฅผ ์์ฑํ๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ด์ CommonUtil
ํด๋์ค๋ ์คํ๋ง๋ถํธ์ ์ํด ๊ด๋ฆฌ๋๋ ๋น(bean
, ์๋ฐ๊ฐ์ฒด)์ผ๋ก ๋ฑ๋ก๋๋ค.
์ด๋ ๊ฒ ๋น(bean)์ผ๋ก ๋ฑ๋ก๋ ์ปดํฌ๋ํธ๋ ํ ํ๋ฆฟ์์ ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋ค.
CommonUtil
ํด๋์ค์๋ markdown
๋ฉ์๋๋ฅผ ์์ฑํ๋ค. markdown
๋ฉ์๋๋ ๋งํฌ๋ค์ด ํ
์คํธ๋ฅผ HTML ๋ฌธ์๋ก ๋ณํํ์ฌ ๋ฆฌํดํ๋ค. ์ฆ, ๋งํฌ๋ค์ด ๋ฌธ๋ฒ์ด ์ ์ฉ๋ ์ผ๋ฐ ํ
์คํธ๋ฅผ ๋ณํ๋(์์ค์ฝ๋, ๊ธฐ์ธ์ด๊ธฐ, ๊ตต๊ฒ, ๋งํฌ ๋ฑ) HTML๋ก ๋ฆฌํดํ๋ค.
์ฐธ๊ณ -
commonmark/commonmark-java
ํ ํ๋ฆฟ์ ๋งํฌ๋ค์ด ์ ์ฉ
์ด์ ์ง๋ฌธ ์์ธ ํ ํ๋ฆฟ์ ๋งํฌ๋ค์ด์ ์ ์ฉํด ๋ณด์.
ํ์ผ๋ช :
/sbb/src/main/resources/templates/
question_detail.html
<!-- (... ์๋ต ...) -->
<!-- ์ง๋ฌธ -->
<h2 class="border-bottom py-2" th:text="${question.subject}"></h2>
<div class="card my-3">
<div class="card-body">
<div class="card-text" th:utext="${@commonUtil.markdown(question.content)}"></div>
<div class="d-flex justify-content-end">
<!-- (... ์๋ต ...) -->
<!-- ๋ต๋ณ ๋ฐ๋ณต ์์ -->
<div class="card my-3" th:each="answer : ${question.answerList}">
<a th:id="|answer_${answer.id}|"></a>
<div class="card-body">
<div class="card-text" th:utext="${@commonUtil.markdown(answer.content)}"></div>
<div class="d-flex justify-content-end">
<!-- (... ์๋ต ...) -->
์ค ๋ฐ๊ฟ์ ํ์ํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๊ธฐ์กด์ style="white-space: pre-line;"
์คํ์ผ์ ์ญ์ ํ๊ณ ${@commonUtil.markdown(question.content)}
์ ๊ฐ์ด ๋งํฌ๋ค์ด ์ปดํฌ๋ํธ๋ฅผ ์ ์ฉํ๋ค. ์ด ๋ th:text
๊ฐ ์๋ th:utext
๋ฅผ ์ฌ์ฉํ ๋ถ๋ถ์ ์ฃผ์ํ์. ๋ง์ฝ th:utext
๋์ th:text
๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ HTML์ ํ๊ทธ๋ค์ด ์ด์ค์ผ์ดํ(escape)์ฒ๋ฆฌ๋์ด ํ๊ทธ๋ค์ด ๊ทธ๋๋ก ํ๋ฉด์ ๋ณด์ธ๋ค. ๋งํฌ๋ค์ด์ผ๋ก ๋ณํ๋ HTML ๋ฌธ์๋ฅผ ์ ๋๋ก ํ์ํ๋ ค๋ฉด ์ด์ค์ผ์ดํ ์ฒ๋ฆฌ๋ฅผ ํ์ง ์๊ณ ์ถ๋ ฅํ๋ th:utext
๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
๋งํฌ๋ค์ด ํ์ธ
์ด์ ์ง๋ฌธ ๋๋ ๋ต๋ณ์ ๋งํฌ๋ค์ด ๋ฌธ๋ฒ์ผ๋ก ์์ฑํ๋ฉด ๋ธ๋ผ์ฐ์ ์์ ์ด๋ป๊ฒ ๋ณด์ด๋์ง ํ์ธํด ๋ณด์.
๋ค์ ๋ด์ฉ์ผ๋ก ๊ธ์ ์์ฑํด ๋ณด์.
**๋งํฌ๋ค์ด ๋ฌธ๋ฒ์ผ๋ก ์์ฑํด ๋ด
๋๋ค.**
* ๋ฆฌ์คํธ1
* ๋ฆฌ์คํธ2
* ๋ฆฌ์คํธ3
ํ์ด์ฌ ํํ์ด์ง๋ [http://www.python.org](http://www.python.org) ์
๋๋ค.
โป ์ฐธ๊ณ : ๋งํฌ๋ค์ด ์๋ํฐ
๋งํฌ๋ค์ด ๋ฌธ๋ฒ์ ๋ชฐ๋ผ๋ simplemde์ ๊ฐ์ ๋งํฌ๋ค์ด UI ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋งํฌ๋ค์ด์ ๋ณด๋ค ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๋ค