Go/Blockchain
[Nomad Coin] Explorer - #5.3 Using Partials
Gopythor
2022. 7. 18. 00:02
728x90
반응형
#5.3 Using Partials
- 분할 정복을 해야한다.
<header>
<nav>
<a href="/"><h1>노마드 코인</h1></a>
<ul>
<li>
<a href="/">Home</a>
</li>
<li>
<a href="/add">Add</a>
</li>
</ul>
</nav>
<h1>{{.PageTitle}}</h1>
</header>
- route를 상기와 같이 변경했다.
- header와 navigation을 만들었고 ul도 넣고 h1으로 끝냈다.
- mvp.css를 사용하기 때문에 기본 tag만 써도 더 예쁘게 꾸며진다.
- header나 Block을 재사용하고 싶다.
- 아니면 나중에 footer를 재사용 할 수도 있다.
<main>
{{range .Blocks}}
<section>
<ul>
<li>{{.Data}}</li>
<li>{{.Hash}}</li>
{{if .PrevHash}}
<li>{{.PrevHash}}</li>
{{end}}
</ul>
</section>
{{end}}
</main>
- prevHash가 없는 li들은 표시되지 않도록 할 것이다. prevHash가 있을 때에만 보이게 할 것이다.
{{define "head"}}
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/mvp.css">
<title>노마드 코인</title>
</head>
{{end}}
- 재사용하고 싶은 모든 것들을 한번 잘라내보자
- partials의 head.gohtml에 먼저 {{define "head"}}라고 쓰고 head를 붙여넣은 다음 {{end}}를 써준다.
{{define "header"}}
<header>
<nav>
<a href="/"><h1>노마드 코인</h1></a>
<ul>
<li>
<a href="/">Home</a>
</li>
<li>
<a href="/add">Add</a>
</li>
</ul>
</nav>
<h1>{{.PageTitle}}</h1>
</header>
{{end}}
- {{define "header"}}를 쓰고 header를 붙여 넣고 {{end}}을 잊지말고 써준다.
{{define "footer"}}
<footer>© 2022</footer>
{{end}}
- footer에서도 똑같이 한다. {{define "footer"}}
- ⓒ2022라고 적는다.
- {{end}}잊지말아야 한다.
{{define "block"}}
<div>
<ul>
<li>{{.Data}}</li>
<li>{{.Hash}}</li>
{{if .PrevHash}}
<li>{{.PrevHash}}</li>
{{end}}
</ul>
</div>
<hr />
{{end}}
- 이제 Block을 어떻게 재사용하는지 알아보자.
- 필요한 경우를 대비하자.
- block.gohtml을 만들고 {{define "block"}}을 쓰고 붙여넣기 하고 {{end}}를 작성한다.
- 당장 제대로 동작은 하지 않는다.
- 재사용될 조각들을 include해야 한다.
- 지금은 전혀 load되고 있지 않다.
<!DOCTYPE html>
<html lang="en">
{{template "head"}}
<body>
{{template "header"}}
<main>
{{range .Blocks}}
{{template "block"}}
{{end}}
</main>
{{template "footer"}}
</body>
</html>
- 재사용할 조각들을 include하기 위해서는 home.gohtml에 {{template}}라고 쓰기만 하면 된다.
- head라는 template이라면 {{template "head"}}라고 쓴다.
- header template를 불러온다.
- block template를 불러온다.
- footer template를 불러온다.
{{define "home"}}
<!DOCTYPE html>
<html lang="en">
{{template "head"}}
<body>
{{template "header"}}
<main>
{{range .Blocks}}
{{template "block"}}
{{end}}
</main>
{{template "footer"}}
</body>
</html>
{{end}}
- 그리고 이제 이것 또한 하나의 template로 만들 것이다.
- {{define "home"}}이라고 쓴다. 그리고 {{end}}까지
{{define "add"}}
<!DOCTYPE html>
<html lang="en">
{{template "head"}}
<body>
{{template "header"}}
<main>
<form>
<input type="text" placeholder="Data for your block" required />
</form>
</main>
{{template "footer"}}
</body>
</html>
{{end}}
- Add페이지에 대해서도 똑같이 해볼 것이다.
- {{define "add"}}라고 쓴다.
- Add는 Block이 필요없고 대신 form이 필요하다.
- placeholder는 user가 뭘 써야할지 알려주는 기능이다.
- "Data for your block"이라고 하자.
- required까지 써주면 끝이다.
- 이게 나중에 보게 될 Add 페이지가 된 것이다.
- 보이는 것 처럼 template를 define했다.
- 이 변화들에 대해 Go가 어떻게 반응할 것인가?
- 아직 이 template들을 load하지 않았다.
- 그저 home.gohtml을 template로 load 한것이다.
- main.go를 실행하면 아무것도 없다. 아무것도 렌더링 되지 않는다.
- https://pkg.go.dev/text/template
- template package가 있다.
- 'text/template'는 HTML template가 구현하는 package이다.
- 예를 들면 comment가 있고, if나 range, range가 비었을 때 실행될 else 등 유용하다.
- 위의 사이트의 documentation을 참조하라.
- function이 호출되기 전에 파일을 parsing하는 대신 template들을 load해보자.
- home 페이지로 오기도 전에 template는 이미 load가 끝나있을 것이다.
- templates라 함은 partials랑 pages이다.
- 일일이 각 template를 load하지는 않을 것이다.
- home function이 호출될 때마다 home template을 parsing할 것이다.
- 그리고 main에 load 시킬 것이다.
var templates *template.Template
- 이를 위해서 variable 하나 생성할건데, 전체 template들을 관리할 것이다.
- template Object 하나에 모든 template들을 load할 것이다.
- 파일로써가 아니라 define한 이름을 통해서 접근한다.
- "home"이라는 이름은 home template을 보여준다.
- var templates라고 해야하는데 template는 이미 import되어있다(html/template).
- type은 *template.Template이다. template Object같은 것이다.
const (
port string = ":4000"
templateDir string = "templates/"
)
- 그 전에 const 두 개를 만든다.
- 하나는 port 나머지 하나는 string인 templateDir이다. 그 템플릿 경로는 "templates/"가 된다.
func main() {
templates = template.Must(template.ParseGlob(templateDir + "pages/*.gohtml"))
http.HandleFunc("/", home)
fmt.Printf("Listening on http://localhost%s\n", port)
log.Fatal(http.ListenAndServe(port, nil))
}
- 파일을 function안에서 load하고 parsing하는 대신에 route안에서 호출될 것이다.
- templates를 초기화 시킬 것이다. pages에 있는 모든 파일들을 load한 결과물로 말이다.
- pages폴더, add 와 home.
- 오래 걸리니 파일명을 전달해서 구현하진 않는다. 대신 pattern을 사용한다.
- template.Must()를 쓰고 template.parseGlob()
- 이름을 넘기는게 아니라 pattern을 쓴다.
- templateDir내부에 pages 폴더 안에서 .gothml로 끝나는 모든 파일을 가져오도록 한다.
- 여전히 partials을 load하진 않았다.
- 그 이유는 "**/*.gohtml"은 Go에서 지원되지 않는다.
- 모든 폴더의 모든 파일에 접근할 수는 없다.
- templates variable은 이제 모든 load된 template들을 가지고 있다.
- 해야할 건 variable을 업데이트해주는 것이다.
templates = template.Must(template.ParseGlob(templateDir + "pages/*.gohtml"))
templates = template.Must(templates.ParseGlob())
- 이번엔 templates.ParseGlob()를 써서 말이다.
- 첫 번째 줄에서 template를 썼다. standard library에 있는 template이다.

- 첫 번째 line이 실행되고 나면 이제 templates variable은 template Object이다.
- template object는 다른 templates을 load할 수 있다.
templates = template.Must(template.ParseGlob(templateDir + "pages/*.gohtml"))
templates = template.Must(templates.ParseGlob(templateDir + "partials/*.gohtml"))
- partials 폴더 내부에 있는 확장자가 gohtml인 모든 파일을 load하도록 하는 것이다.
- variable을 만들었다. initialize하진 않았지만 type은 지정했다.
- 그리고 main에서 initialize했고 variable을 update했다. 새로 생성한 것이 아니다.
- templates을 load했고, 이제 templates는 template object가 됐다.
- template object가 partials까지 load하게 했다.
- 모든 page와 paritials를 load 하고 있는 template object를 가지고 있다.
func home(rw http.ResponseWriter, r *http.Request) {
data := homeData{"Home", blockchain.GetBlockchain().AllBlocks()}
templates.ExecuteTemplate(rw, "home", data)
}
- home을 정리해준다. 이젠 templates Object를 사용한다.
- templates.ExecuteTemplate()
- argument는 Writer이고 두번째는 template의 이름이다.
- 그리고 data를 넘겨주면 된다.

- 어느 정도 동작을 한다.
- template home을 렌더링하고 있다.
- footer가 있어서 Add로 갈 수 있다.
- 문제는 variable들이 어디로 갔는가
출처 : 노마드코더 노마드코인
728x90
반응형