상세 컨텐츠

본문 제목

타임리프 정리

카테고리 없음

by kail 2022. 3. 30. 17:38

본문

https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#the-template-engine

 

Tutorial: Using Thymeleaf

1 Introducing Thymeleaf 1.1 What is Thymeleaf? Thymeleaf is a modern server-side Java template engine for both web and standalone environments, capable of processing HTML, XML, JavaScript, CSS and even plain text. The main goal of Thymeleaf is to provide a

www.thymeleaf.org

여기서 타임리프에 관한 설명을 읽으며 모르는 단어는 번역기 돌려 보고 문장도 모르겠으면 통째로 번역해서 다시 번역해보고

잘 모르겠거나 정리용으로 블로그 글 들을 뒤져보곤 하는데,

아무도 ITemplateResolver가 TemplateResolver로 구현되어있는데,

왜 ServletContextTemplateResolver의 객체로만 보이는지에 대한 자세한 설명이 없다.

이에 대해 의문이 들어 자바/스프링 단톡방에도 질문하였으나, 평일 오후라 그런지 다들 답변이 없으셨다.

스택오버플로우에도 딱히 관련된 사항이 없는 것 같아 한번 간단히 정리하였다.(결론적으로 내 예상이 맞았다..)

2번의 The tymleaf Resolver에 관한 내용을 읽어보면

Template Resolvers are objects that implement an interface from the Thymeleaf API called org.thymeleaf.templateresolver.ITemplateResolver:

라는 설명이 있다.

번역하자면, Template Resolvers는 Thymleaf API에서 요청한 인터페이스의 ITemplateResolver를 구현한 객체라는 말이다.

자 그러면 코드를 보자.

ServletContextTemplateResolver templateResolver = 
        new ServletContextTemplateResolver(servletContext);

여기서 templateResolver는 ServletContextTemplateResolver class를 참조하는 것 같다

(당연하지만 추상 class나 interface면, new로 인스턴스화 작업이 일어나지 않는다

추상 class에서 default 함수만 쓸 경우 그냥 class를 쓰는 것이 낫기 때문에 쓸 필요가 없다)

그러면 여기서, templateResolver는 ITemplateResolver를 구현한 객체인데, 왜 templateResolver는 ServletContextTemplateResolver를 참조한다고 할까?

그러면 당연히 ServletContextTemplateResolver의 부모 class나 인터페이스가 ITemplateResolver라고 생각할 수 있다.

나도 여기까지는 예상했다.

그런데 다시 의문이 생긴다.

그러면, TemplateResolver라는 네이밍으로

구현하면되는 걸, 왜 네이밍할때 ServletContextTemplateResolver로 구현했는가에 대한 의문이 생긴다.

다시말해 ITemplateResolver랑 ServletContextTemplateResolver가 네이밍으로 봤을 때

서로가 1차적으로 연결된 관계가 아니란 점은 도출해 볼 수 있다는 말이다.

2시간동안 찾아보니 상속 관계는 위와 같고(링크: https://www.thymeleaf.org/apidocs/thymeleaf/3.0.0.BETA03/org/thymeleaf/templateresolver/ServletContextTemplateResolver.html)

 

구현의 관계는 위와 같다

 

즉 AbstractTemplateResolver가 ItemplateResolver를 구현하고,

AbstractConfigurableTemplateResolver , DefaultTemplateResolver , StringTemplateResolver 라는 자식 class가 존재한다

org.thymeleaf.templateresolver.AbstractConfigurableTemplateResolverClassLoaderTemplateResolver, FileTemplateResolver, ServletContextTemplateResolver, UrlTemplateResolver 라는 자식 class가 존재한다

AbstractTemplateResolver라는 추상 class는

 

protected boolean computeResolvable 함수로 resolver가 적용가능한지 체크하고,

protected abstract TemplateMode

enum으로 templateResolver.templateMode = TemplateMode.HTML여기서 쓰는 것처럼

HTML,CSS 형식으로 setting 하는 것이 가능하고,

protected abstract ICacheEntryValidity

템플릿이 캐시에 들어가는 게 가능한지나, 템플릿이 여전히 유효한 지 검사할 수 있고,

boolean getCheckExistence()

템플릿이 리턴하기 전에 존재하는 지 검사할 수 있고,

String getName()

템플릿 확인자 이름을 반환하는 것이나

등등을 알 수 있다.

 

AbstractConfigurableTemplateResolver 라는 class에서는

여기서 prefix랑 suffix를 set으로 설정하는 것을 알 수 있다.

 

templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");

이걸로 타임리프를 사용할 떄 접두사 접미어로 (상위폴더,하위이름) 실제 파일의 이름을 쉽게 찾아서 사용한다

여기서 이제, controller에서 view resolver로 보내줄 때

return "thymleafpractice1";

이렇게 보내주는데 이러면, (또는 thymeleafpractice1.html로 보내주기도 하는데, 이렇게 해도 아마 .html이 접미어랑 중복되면 자동으로 접미어만 빼거나 하는식으로 해주지않을까 싶다)

servletContext.getResourceAsStream("/WEB-INF/templates/thymleafpractice1.html")

그러면 내부적으로 함수를 호출해 다음과 같이 처리해준다는 얘기인 것 같다

그리고, 캐시라는 말이 애매하게 보여서 찾아보니 https://countryxide.tistory.com/8 에서

캐싱하는 것이 임시저장소에서 바로 등록했던 걸 가져오고 하는 시간인 것 같다.

그래서, 

templateResolver.setCacheTTLMs(3600000L);

이렇게 작성하면 대략 1시간 정도 내가 코드를 바꿔도 임시저장소에서 있던 걸 그대로 보내주는 시간을 정해주는 작업인것같다

60*60*1000ms(1s)

templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(templateResolver);

결과적으로 , 템플릿 엔진에서는 이렇게 만든 템플릿리졸버를 값으로 받는데 이 과정은 CGVT 엔진에서 동작한다

public class GTVGApplication {
  
    
    ...
    private final TemplateEngine templateEngine;
    ...
    
    
    public GTVGApplication(final ServletContext servletContext) {

        super();

        ServletContextTemplateResolver templateResolver = 
                new ServletContextTemplateResolver(servletContext);
        
        // HTML is the default mode, but we set it anyway for better understanding of code
        templateResolver.setTemplateMode(TemplateMode.HTML);
        // This will convert "home" to "/WEB-INF/templates/home.html"
        templateResolver.setPrefix("/WEB-INF/templates/");
        templateResolver.setSuffix(".html");
        // Template cache TTL=1h. If not set, entries would be cached until expelled
        templateResolver.setCacheTTLMs(Long.valueOf(3600000L));
        
        // Cache is set to true by default. Set to false if you want templates to
        // be automatically updated when modified.
        templateResolver.setCacheable(true);
        
        this.templateEngine = new TemplateEngine();
        this.templateEngine.setTemplateResolver(templateResolver);
        
        ...

    }

}