AmberAx

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

· 4 min read
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 코드로 변환할 수 있습니다. 다음은 그 과정과 사용 예제입니다.

  1. hello.templ 파일 생성:
package main

templ hello(name string) {
	<div>Hello, { name }</div>
}
  1. 컴파일 명령 실행:
templ generate

templ이 hello_templ.go 파일을 생성합니다.

  1. 생성된 코드를 활용한 렌더링:
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을 적극 활용하는것이 어떨까요?

Did you find this post helpful?
Share it with others!