본문 바로가기

Issue 해결

[타임리프]org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing

안녕하세요 인포돈 입니다.


타임리프 템플릿을 랜더링 할 때, 자원을 찾지 못하는 오류

 

프로젝트에서 타임리프를 활용하면서, Model에 값을 넣어주어 활용하였다. 오류가 나는 부분은 아래와 같다.

 

오류 내용

org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/chatbot/chat.html]")

Caused by: org.attoparser.ParseException: Could not parse as expression: "favoriteKeyword : ${favoriteKeywords}" (template: "chatbot/chat" - line 288, col 6)

Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression: "favoriteKeyword : ${favoriteKeywords}" (template: "chatbot/chat" - line 288, col 6)

org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression: "favoriteKeyword : ${favoriteKeywords}" (template: "chatbot/chat" - line 288, col 6)

Controller

   @RequestMapping("/chat")
    public String chatGET(Model model){

        HashMap<String, String> favoriteKeywords = new HashMap<>();
        ~~~~
        ~~~~

        model.addAttribute("favoriteKeywords", favoriteKeywords);

        return "chatbot/chat";
    }

Tymeleaf

<div th:for="favoriteKeyword : ${favoriteKeywords}">
    <a th:href="@{/{id}(id = ${favoriteKeyword.value})}" th:text="${favoriteKeyword.key}"></a>
</div>

 

분명히 모델에 넣어주고, Map을 꺼내기 위해서 key와 value를 사용했지만,,, 오류가 나는 것을 확인할 수 있었다.

 

 

무엇이 문제인지 모르기 때문에, 기초적인 부분부터 하나씩 실험해 보자

 

 1) 기본적인 String 출력

model.addAttribute("hello", "hello");

<div th:text="${hello}"></div>

뭐... 크게 어렵지 않게 꺼내올 수 있었다. 그렇게 된다면, HashMap 자료구조를 통해 꺼내오는 방식이나, th:each의 부분에서 오류가 났을 확률이 높아 보인다. 하나씩 실험해 보자

 

 2) th:each 고쳐보기

아..... 이 부분에서 실수했다..... th:each를 활용하려 했으나,,, th:for을 사용해버렸다... 자동 완성되는 기능을 빠르게 이용하다 보니 나온 실수이다.

 

<div th:each="favoriteKeyword : ${favoriteKeywords}">
    <div th:text="${favoriteKeyword.key}"></div>
    <div th:text="${favoriteKeyword.value}"></div>
</div>

해당 코드를 통해 잘 출력됨을 알 수 있다.

 

 * 여기서 th:for을 보고 헷갈릴 수 있다. 이 의미는 우리는 기본적인 프로그래밍 문법에서 for는 반복을 나타낸다. 그러나 타임리프에서 th:for은 <label>의 속성을 나타낸다.

 

 * 참고로 <label> 태그의 for 속성은 <input>과 같이 쓰이며, <label> 태그를 눌러도, 해당 <input>이 체크되거나, focus 되는 속성이다.