Go 템플릿 엔진 비교: Templ 추천

Go 언어는 백엔드 개발에서 간결하고 효율적인 코드 작성을 지원하며, 다양한 템플릿 엔진을 통해 동적인 HTML을 생성할 수 있습니다.
이 글에서는 Go에서 자주 사용하는 템플릿 엔진인 html/template, 그리고 Templ, Pongo2, Ace, Amber와 같은 외부 라이브러리에 대해 알아보고, 각각의 특징, 예제, 그리고 장단점을 비교해보겠습니다.
html/template (Go 표준 라이브러리) #
특징
- Go의 표준 라이브러리에서 제공하는 HTML 템플릿 엔진.
- HTML 및 웹 응답 생성에 최적화되어 있음.
- XSS(크로스 사이트 스크립팅) 방지 기능이 내장되어 보안성이 뛰어남.
- 간단한 문법과 높은 성능 제공.
예제
package main
import (
"html/template"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
tmpl, _ := template.New("example").Parse("<h1>Hello, {{.Name}}!</h1>")
tmpl.Execute(w, map[string]string{"Name": "Go Developer"})
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
장점
- Go 표준 라이브러리로 별도의 설치 필요 없음.
- 자동 XSS 방지로 보안 강화.
- 간단한 문법과 높은 성능.
단점
- 문법이 제한적이고 복잡한 템플릿 작업에는 불편함.
- HTML 전용으로 설계되어 JSON이나 다른 출력 형식에는 적합하지 않음.
Templ (외부 라이브러리) #
Templ은 Go 생태계에서 떠오르는 템플릿 엔진으로, 타입 안전성과 컴파일 타임 검증을 중시합니다.
특징
- 순수 Go 코드로 작성된 템플릿.
- 컴파일 타임에 템플릿을 검증하여 런타임 오류 방지.
- HTML 자동 이스케이프를 통한 보안 기능 제공.
- 템플릿 문법이 Go와 동일하여 학습 곡선이 낮음.
예제
Templ에서는 templ generate
명령어를 통해 템플릿을 컴파일 타임에 Go 코드로 변환할 수 있습니다. 다음은 그 과정과 사용 예제입니다.
hello.templ
파일 생성:
package main
templ hello(name string) {
<div>Hello, { name }</div>
}
- 컴파일 명령 실행:
templ generate
templ이 hello_templ.go
파일을 생성합니다.
- 생성된 코드를 활용한 렌더링:
package main
import (
"context"
"os"
)
func main() {
component := hello("John")
component.Render(context.Background(), os.Stdout)
}
출력
<div>Hello, John</div>
장점
- 타입 안전성을 통해 컴파일 타임에 오류를 방지.
- 높은 성능: 컴파일 시 템플릿을 Go 코드로 변환.
- Go 문법과 유사하여 학습이 쉬움.
단점
- 초기 학습 곡선이 있을 수 있음.
- 표준 라이브러리가 아니므로 외부 종속성이 추가됨.
Pongo2 #
2023년 이후 커밋이 존재하지 않습니다.
Pongo2는 Django 템플릿 엔진의 문법을 모방한 Go용 템플릿 엔진입니다.
특징
- 익숙한 Django 스타일의 템플릿 문법.
- 템플릿 상속, 조건문, 반복문 등 강력한 기능 제공.
예제
package main
import (
"github.com/flosch/pongo2"
"os"
)
func main() {
tmpl, _ := pongo2.FromString(`
{% block header %}
<h1>Welcome to Pongo2</h1>
{% endblock %}
<p>Hello, {{ name }}! Thanks for visiting our site.</p>
`)
tmpl.ExecuteWriter(pongo2.Context{"name": "Go Developer"}, os.Stdout)
}
출력
<h1>Welcome to Pongo2</h1>
<p>Hello, Go Developer! Thanks for visiting our site.</p>
장점
- 강력하고 익숙한 문법 제공.
- 템플릿 상속과 같은 고급 기능 지원.
단점
- 외부 의존성 필요.
- 런타임에 템플릿을 파싱하므로 컴파일 타임 검증 부족.
Ace #
2018년 이후 커밋이 존재하지 않습니다.
Ace는 Go 표준 템플릿 엔진을 확장하여 템플릿 상속과 블록 기능을 추가한 템플릿 엔진입니다.
특징
- 템플릿 상속과 블록 기반 설계 지원.
- Go 표준 라이브러리인
html/template
와 호환.
예제
템플릿 파일
base.ace
= doctype html
html lang=en
head
meta charset=utf-8
title Ace example
= css
h1 { color: blue; }
body
h1 Base Template : {{.Msg}}
#container.wrapper
= yield main
= yield sub
= include inc .Msg
= javascript
alert('{{.Msg}}');
inner.ace
= content main
h2 Inner Template - Main : {{.Msg}}
= content sub
h3 Inner Template - Sub : {{.Msg}}
inc.ace
h4 Included Template : {{.}}
코드
package main
import (
"net/http"
"github.com/yosssi/ace"
)
func handler(w http.ResponseWriter, r *http.Request) {
tpl, err := ace.Load("base", "inner", nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err := tpl.Execute(w, map[string]string{"Msg": "Hello Ace"}); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
출력
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Ace example</title>
<style type="text/css">
h1 { color: blue; }
</style>
</head>
<body>
<h1>Base Template : Hello Ace</h1>
<div id="container" class="wrapper">
<h2>Inner Template - Main : Hello Ace</h2>
<h3>Inner Template - Sub : Hello Ace</h3>
<h4>Included Template : Hello Ace</h4>
</div>
<script type="text/javascript">
alert('Hello Ace');
</script>
</body>
</html>
장점
- 템플릿 상속과 재사용성 강화.
html/template
과 호환되어 보안성과 익숙함 유지.
단점
- 외부 의존성 필요.
- 복잡한 문법으로 학습 곡선 존재.
Amber #
2017년 이후 커밋이 존재하지 않습니다.
Amber는 Pug(Jade) 스타일의 간결한 문법을 제공하는 Go용 템플릿 엔진입니다.
특징
- 들여쓰기 기반의 간결한 문법.
- Go 표준 템플릿 엔진 위에서 확장되어 동작.
예제
템플릿 코드
h1 Welcome to Amber!
p Hello, {{.Name}}! This is a simple Amber example.
코드
package main
import (
"bytes"
"fmt"
"github.com/eknkc/amber"
)
func main() {
compiler := amber.New()
err := compiler.Parse(`h1 Welcome to Amber!\np Hello, {{.Name}}! This is a simple Amber example.`)
if err != nil {
fmt.Println("Error parsing template:", err)
return
}
tmpl, _ := compiler.Compile()
var buf bytes.Buffer
tmpl.Execute(&buf, map[string]string{"Name": "Go Developer"})
fmt.Println(buf.String())
}
출력
<h1>Welcome to Amber!</h1>
<p>Hello, Go Developer! This is a simple Amber example.</p>
장점
- 간결한 문법으로 빠른 템플릿 작성 가능.
- 표준 라이브러리를 기반으로 보안성과 성능 유지.
단점
- 들여쓰기 오류로 인해 디버깅이 어려울 수 있음.
- 외부 의존성 필요.
템플릿 엔진 비교 #
템플릿 엔진 | 특징 | 장점 | 단점 |
---|---|---|---|
html/template |
HTML 전용 표준 라이브러리 | 간단하고 보안성이 뛰어남 | 문법 제한, 복잡한 작업에 부적합 |
Templ |
타입 안전성과 컴파일 타임 검증 | 성능 우수, Go 문법과 유사, 컴파일 타임 오류 방지 | 외부 의존성, 초기 학습 필요 |
Pongo2 |
Django 스타일 템플릿 문법 | 강력한 기능, 템플릿 상속 지원 | 런타임 파싱, 외부 의존성 필요 |
Ace |
템플릿 상속과 블록 기반 설계 | 재사용성 강화, html/template 과 호환 |
외부 의존성, 복잡한 문법 |
Amber |
Pug 스타일의 간결한 문법 | 간결한 문법, 표준 라이브러리 기반 | 들여쓰기 오류에 민감, 외부 의존성 필요 |
결론 #
Go에서 템플릿 엔진을 선택할 때는 프로젝트의 요구사항과 복잡성에 따라 적절한 도구를 선택하는 것이 중요합니다. 단순한 HTML 템플릿이라면 표준 라이브러리의 html/template
로 충분하며, 복잡한 작업이나 성능 최적화가 필요하다면 Templ
, Pongo2
, Ace
, 또는 Amber
와 같은 외부 라이브러리를 고려해볼 수 있습니다.
하지만 위에서 언급했듯이 현재 Templ을 제외하면 나머지 프로젝트는 거의 유지되지 않고 있습니다. 그러므로 Templ을 적극 활용하는것이 어떨까요?