관리 메뉴

나만의공간

Spring Boot Template Engine 연결 (Pebble Template) 본문

IT/Spring

Spring Boot Template Engine 연결 (Pebble Template)

밥알이 2022. 1. 20. 10:41

Template Engine에 종류는 다양하게 존재 합니다.
그 중 Pebble Template Engine을 Spring Boot와 연결하는 예제를 만들었습니다.
서버에서 HTML에 Data Mapping을 끝내고 완성된 HTML을 Client Browser로 내려보내기 때문에 화면 View 노출이 빠르게 됩니다.

이전 연재에서 사용했던 소스를 기반으로 Pebble Template을 추가 하니 이전 연재도 참조 하시면 됩니다.
https://bobr2.tistory.com/entry/Spring-Boot-Project-Initializr-스프링-부트-초기생성-방법

 

Spring Boot Project Initializr (스프링 부트 프로젝트 생성법) #1

프로젝트를 진행하면 아키텍쳐팀에서 프로젝트에 사용할 기본 골격을 만들어서 개발을 진행하게 배포를 해준다. 매번 이런식으로 프로젝트에 기본 뼈대는 안보구 개발만 하다보니, Spring Boot를

bobr2.tistory.com

Pebble Template을 연결하기 위한 설정 Dependency 설정들을 설명 드립니다.

Pebble Dependency 추가

build.gradle Dependency 추가

buildscript {
	ext {
		// pebble version
		pebbleVersion = "3.1.4"
	}
}

implementation("io.pebbletemplates:pebble-spring-boot-starter:${pebbleVersion}")

 

Pebble Template 설정 Class 추가

-. Pebble 관련 파일명 규칙 / Pebble 파일 위치 등을 설정합니다.

package com.study.studyTwo.core;

import com.mitchellbosecke.pebble.PebbleEngine;
import com.mitchellbosecke.pebble.loader.ClasspathLoader;
import com.mitchellbosecke.pebble.loader.Loader;
import com.mitchellbosecke.pebble.spring.servlet.PebbleViewResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@EnableWebMvc
@Configuration
@ComponentScan({"com.study.studyTwo.web"})
public class SpringWebConfig implements WebMvcConfigurer {

	/* pebble */
	/** a Loader that will pick template files ending in .pebble from /templates/ dir on the classpath */
	@Bean
	public Loader<?> pebbleLoader() {
		ClasspathLoader loader = new ClasspathLoader();
		loader.setPrefix("/templates/");
		loader.setSuffix(".peb");
		return loader;
	}

	/** a PebbleEngine with default settings, configured with the previous loader */
	@Bean
	public PebbleEngine pebbleEngine() {
		// loader 에서 설정해주고 .loader 로 가져올수 있는것 같음.
		return new PebbleEngine.Builder()
			.loader(pebbleLoader())
			.cacheActive(false)
			.build();
	}

	/** a ViewResolver that will output text/html in UTF-8 */
	@Bean
	public PebbleViewResolver pebbleViewResolver() {
		PebbleViewResolver pebbleViewResolver = new PebbleViewResolver(this.pebbleEngine());
		pebbleViewResolver.setPrefix("/templates/");
		pebbleViewResolver.setSuffix(".peb");
		pebbleViewResolver.setCache(false);
		return pebbleViewResolver;
	}

	@Override
	public void addViewControllers(ViewControllerRegistry registry) {
		registry.addRedirectViewController("/", "/pebble/sample");
	}
}

 

Pebble Template File static Map에 저장

-. 서버가 시작 될때 Pebble Template File을 Disk에서 읽어 들인 후 메모리에서 가져오도록 처리 한다.
-. 성능상에 이슈는 크케 못느끼지만 DIsk에서 Template File을 읽는것 보다는 메모리에서 읽는게 더 빠르다고 생각되어 static Map에 정의되어 있는 Template File을 모두 넣어 놓는다.
-. JVM에 올라가는 관계로 JVM Memory Size가 작을경우 이슈가 발생할수도 있다.
-. 아래와 같이 적용해 보았는데 OOM(Out Of Memory) 오류는 미 발생했습니다.

package com.study.studyTwo.web;

import com.mitchellbosecke.pebble.PebbleEngine;
import com.mitchellbosecke.pebble.template.PebbleTemplate;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

@Configuration
@Component
@RequiredArgsConstructor
public class FirstStoryTemplates {
	private final PebbleEngine pebbleEngine;

	private static Map<String, PebbleTemplate> pebbleTemplates;

	@PostConstruct
	private void init() throws Exception {
		// PebbleTemplate 등록
		Map<String, PebbleTemplate> templates = new HashMap<>();
		for (TemplatePath templatePath : TemplatePath.values()) {
			templates.put(templatePath.name(), pebbleEngine.getTemplate(templatePath.getUrl()));
		}
		pebbleTemplates = templates;
	}

	private static PebbleTemplate getTemplate(TemplatePath templatePath) {
		return pebbleTemplates.get(templatePath.name());
	}

	/**
	 * Static으로 정의해놓은 Pebble Template을 불러오는 기능 제공
	 * @param templatePath
	 * @param dataMap
	 * @return
	 * @throws IOException
	 */
	public static String evaluate(TemplatePath templatePath, Map<String, Object> dataMap) throws IOException {
		Writer writer = new StringWriter();
		PebbleTemplate template = FirstStoryTemplates.getTemplate(templatePath);
		template.evaluate(writer, dataMap, Locale.KOREA);
		return writer.toString();
	}
}

 

Pebble Template Path Enum 설정

-. Pebble File이 있는곳에 위치를 Enum으로 설정하여 Hard Coding이 없도록 합니다.

package com.study.studyTwo.web;

import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor
@Getter
public enum TemplatePath {

	ERROR_FILE_NOT_FOUND("pebble/hello")

	// common page
    , COMMON_HEADER("commonHeader")
	, PEBBLE_SAMPLE("sample/pebbleSample")

	;
	private String url;
}

Controller 추가

-. pebbleSample 메소드: pebble Template 파일을 Disk에서 읽어 들어 html 파일로 변환 후 브라우저 노출
-. pebbleMemorySample 메소드 : pebble Template을 static Map에서 읽어 들어 html 파일로 변환 후 브라우저 노출
-. 아래 2개 메소드가 처리 하는 방식에 차이가 있습니다.

package com.study.studyTwo.controller;

import com.study.studyTwo.web.FirstStoryTemplates;
import com.study.studyTwo.web.TemplatePath;
import java.util.HashMap;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;

@Slf4j
@Controller
public class StudyPebbleSampleController {

    @GetMapping({"/pebble/sample"})
    public ModelAndView pebbleSample() throws Exception {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("locationMove","https://bobr2.tistory.com/");
        modelAndView.setViewName(TemplatePath.ERROR_FILE_NOT_FOUND.getUrl());
        return modelAndView;
    }

    @GetMapping({"/pebble/memory/sample"})
    public ModelAndView pebbleMemorySample() throws Exception {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName(TemplatePath.PEBBLE_SAMPLE.getUrl());

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("sample1", "Pebble Template을 Static 메모리에서 읽어 오는 예제 입니다.");
        dataMap.put("sample2", "File에서 매번 조회를 하게 되면 I/O가 발생하여 별로 인듯 합니다.");

        String strPebble = FirstStoryTemplates.evaluate(TemplatePath.COMMON_HEADER, dataMap);

        modelAndView.addObject("commonHeaderStr",strPebble);
        return modelAndView;
    }


}

 

Template File 위치

-. HTML 내용을 노출하고, Data 값을 매핑할 Template File에 위치를 아래와 같이 만듭니다.
-. 해당 폴더 위치에 hello.peb / pebbleSample.peb 파일도 만듭니다.

hello.peb 내용

-. HTML과 간단한 Pebble을 모아서 화면노출

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ko">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Pebble Sample</title>
    <style>

        html, body {
            height: 100%;
        }
        a {
            display:inline-block;
            font-size:12px;
            text-decoration: none;
            cursor:pointer;
            color: #333;
        }
        button {
            border: 0;
            background: none;
            cursor: pointer;
        }
        .pebWrap {
            display: flex;
            align-items:center;
            background:#fff;
            justify-content: center;
            height:100vh;
            min-height: 720px;
        }
        .errorContainer .pebCont {
            text-align: center;
        }
        .pebCont p {
            font-size:15px;
            color:#666;
            line-height:1.47;
        }


    </style>
</head>
<body>
<div class="pebWrap">
    <div class="pebContainer">
        <i class="ico">
        <div class="pebCont">
            <h1>Pebble Sample 페이지에 오신것을 환영 합니다.</h1>
            <p>
                Pebble Template들을 서버 부팅시 Java Static을 이용하여 메모리에 올렸습니다.<br>
                좀더 빠른 화면 로딩을 가능하게 합니다.<br>
                <b>Pebble Template Engine 괜찮네여</b>
            </p>
            <div class="btnArea">
                <button type="button" class="btn" onclick="location.href='{{ locationMove }}'">나만의공간 이동</button>
            </div>
        </div>
    </div>
</div>
</body>

pebbleSample.peb 내용

-. static Map에서 Template File을 읽어 Data Mapping 한후 HTML 노출

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ko">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
</head>

<body>
<div class="errorWrap">
    {{ commonHeaderStr | raw }}
</div>
</body>

pebbleTemplate 공식 가이드 사이트

https://pebbletemplates.io/

 

Pebble Templates

Pebble Templates Pebble is a Java templating engine inspired by Twig and similar to the Python Jinja Template Engine syntax. It features templates inheritance and easy-to-read syntax, ships with built-in autoescaping for security, and includes integrated s

pebbletemplates.io


GitHub : https://github.com/abilitybobr/secondStory

 

GitHub - abilitybobr/secondStory: Pebble Template Engine 연결

Pebble Template Engine 연결. Contribute to abilitybobr/secondStory development by creating an account on GitHub.

github.com

 

Comments