시작하기
- 템플릿은 임의의 텍스트 파일이 될 수 있으며, HTML로 한정되지 않는다
출력 텍스트의 아래 요소들은 FreeMarker에서 처리되고, 나머지는 있는 그대로 출력된다 - ${...} : FreeMarker는 출력 텍스트에서 이 부분을 중괄호 안 표현식의 값으로 치환한다. Interpolation이라고 부른다
- FTL(FreeMarker Template Language) 태그 == directive : HTML 태그와 유사하지만, #으로 시작한다. 사용자 정의 태그는 @으로 시작한다. 출력에 포함되지 않는다
- 주석 : <#-- -->. HTML 주석과 다르게 출력에 포함되지 않는다
- Built-in : FreeMarker 데이터 모델이 지원하는 메서드
Directive 예 : <#if>, <#elseif>, <#else>, ...
Built-in 예 : ?upper_case, ?length, ?size, ...
Undefined Variable Error 방지
- FreeMarker는 null 예외나 찾을 수 없는 식별자 예외를 동일하게 "undefined variable" error를 발생시킨다
- 기본값 설정 : !
존재 여부 확인 : ?? - 검사 범위 설정 : ()
a.b.c! 또는 a.b.c??는 c의 존재 여부만 체크하지만, (a.b.c)! 또는 (a.b.c)??는 데이터 모델 구조상 모든 노드의 존재 여부를 체크한다
이스케이프
- 적절히 설정되었다면 ${...}을 통해 출력되는 &, <, >, ", ' 등은 자동으로 이스케이프 처리된다
- .ftlh 파일을 이용하면 HTML에 맞추어 자동으로 이스케이프 처리된다
- .ftlx 파일을 이용하면 XML에 맞추어 자동으로 이스케이프 처리된다
타입
- Scalar
- String : 문자열 리터럴은 "", '' 둘 다 이용 가능
- Number : 단일 숫자 타입을 이용하기 때문에, 3/2가 1로 평가되는 일은 없다
- Boolean : true or false
- Date : Date | Time | Date-time
- Container
- Hash : (String 키, 임의 값) 쌍 저장
- Sequence : 요소들을 일렬로 저장. 0부터 시작하는 인덱스 존재. 요소들의 타입을 같지 않아도 된다
- Collection : 제한된 sequence로 크기에 접근할 수 없고, 인덱스 참조도 안 되지만 <#list>에 이용될 수 있다
- Subroutines
- FreeMarker에서 method/function은 일급 객체다
- 사용자 정의 directive 역시 subroutine이며, 일급 객체다
Hash인 동시에 Sequence일 수 있다
템플릿 - 구문
- 리터럴
- 문자열 : "", '' 모두 가능. 이스케이핑 가능(유니코드 : \xXXXX). Raw string 표현을 위해 접두 문자 'r' 사용 가능
- 숫자 : 10진수 표현만 가능. 지수 표현 불가능. 소수점 앞 '0' 생략 불가능
- Boolean : true, false
- Sequence : [] 안에 각 표현식을 콤마로 구분한다
- Range
- start .. end
- start ..< end or start ..! end
- start ..* length
- start ..
- Hash : {"key": "value", keyStringExpression: valueExpression}
- 변수 참조
- Top-level variables: user
- Hash: user.name, user["name"]
- Sequence: products[5]
- Special variables: .variable_name
- 문자열 연산
- Interpolation : "Hello ${user}!"
- Concatenation : "Hello " + user + "!"
- Getting a character: name[0], name?string[0]
- String slice: name[range]
- Sequence operation
- Concatenation: users + ["guest"]
- Sequence slice: name[range]
- Hash operation
- Concatenation: passwords + { "joe": "secret42" }
- Arithmetical calculations: (x * 1.5 + 10) / 2 - y % 100
- Comparison: x == y, x != y, x < y, x > y, x <= y, x >= y, x lt y, x lte y, x gt y, x gte y, ...
- Logical operations: !registered && (firstVisit || fromEurope)
- Built-ins: name?upper_case, path?ensure_starts_with('/')
- Method call: repeat("What", 3)
Range 표현식 자체가 []를 포함하지는 않는다. 할당하고자 할 때는 [] 안에 range 표현식을 작성해야 한다
문자열 내부에서 Interpolation이 이용되는 경우, 자동 이스케이핑 대상에서 제외된다
Interpolation, concatenation 모두 로캐일 설정에 의해 변화된다. 로캐일과 무관하게 처리하려면 "someUrl?id=" + id?c 처럼 ?c를 붙인다
문자 타입은 없으므로, 반환값은 길이 1 문자열이다
name이 string인 동시에 sequence인 경우, sequence 슬라이싱이 이뤄진다. 문자열로서 슬라이싱되려면 ?string[range]로 명시해야 된다
사용자 정의 directive
- 기본 정의 : macro
- 매개변수
- Nested content
- Nested content with 출력 전용 변수
매크로 매개변수는 nested content에서 참조할 수 없다
변수
값을 변경할 수 없는 FreeMarker 데이터 모델과 다르게, 값을 변경할 수 있는 변수를 이용할 수 있다
- "plain" variable : 템플릿 내에 선언되어 해당 템플릿 안에서 참조 가능. <#assign x = 1>
- Local variable : 매크로나 함수 안에서 선언되어 그 안에서만 참조 가능. <#local x = 1>
- Loop variable : list와 같은 directive에 의해 자동으로 만들어지는 변수
- Global variable : Global directive로 선언하여 어느 템플릿에서든 참조 가능. Global 변수는 같은 이름의 데이터 모델을 가린다. <#global x = 1>
Namespace
- 템플릿에서 선언된 변수(매크로, 함수 포함)들에 대한 유니크한 이름과의 매핑
- import : include와는 다르게, 템플릿 네임스페이스에 대한 접근을 가능하게 하는 해시를 생성한다
- auto import : 메인 템플릿(다른 곳에서 include/import되지 않는 top-level 템플릿)에 자동으로 import
import된 템플릿의 네임스페이스는 템플릿의 path로 구분되며, 같은 path로 여러 번 import 하더라도 같은 해시를 갖게 된다
공백 처리
- 설정 변경
- Directive 사용
템플릿 처리 후 불필요한 공백이 많이 발생하기 때문에, 이를 다루는 방법을 몇 가지 제공한다
↓ java
compress directive는 템플릿 처리 결과를 직접 가공한다. single_line 매개변수에 true를 보내면 결과를 한 줄로 요약한다
- © Donggi Kim. MIT License
- w3css : No license
- highlight.js : BSD-3-Clause License
- MathJax : Apache License 2.0
- qrcodejs : MIT License