해결된 질문
작성
·
74
·
수정됨
0
여기서 experience를 모델에서 못찾아서??
experience.startYearMonth 등 인식이 안되는것 같습니다.
cannot resolve라고 뜹니다. 혹시 제가 컨트롤러라든지 DTO라든지 잘못적고 놓쳤나보다 하고 봤는데 왜 안되는지 못찾겠습니다. 한번 확인 가능할까요?
컨트롤러
서비스
DTO
데이터 초기화
이렇게 타임리프 적용이 안될 떄는 어떻게 찾는게 좋은 방법일까요?
답변 2
1
안녕하세요 정보근입니다:)
접근 방법 위주로 설명드리겠습니다.
먼저 cannot resolve란 문구가 뜨는 걸로 봤을 때, 다음과 같은 문제를 의심해볼 수 있을 것 같습니다.
모델에 데이터가 안 넘어왔다.
모델에 잘못된 데이터가 넘어왔다.
뷰에서 적절하게 데이터를 핸들링하지 못했다.
1번의 경우 컨트롤러에서 resume를 넣어주고 있으니 데이터는 잘 넘어갔을 것 같고요.
그럼 2번, resume 데이터가 어떻게 들어갔는지 확인이 필요할 것 같습니다.
가장 간단한 방법은 컨트롤러에서 로그를 찍어보는 것입니다.
필드명에 오타가 없는지, 값은 null이 아닌지 등을 확인해보시면 될 것 같아요.
여기까지 문제가 없을 경우 서버의 문제는 아니고, 프론트의 문제일 가능성이 높습니다.
이 때 브라우저에서 F12(크롬 기준)를 누른 뒤,
개발자 도구의 console 탭에 들어가시면 에러 메시지가 있을텐데요.
여기서 힌트를 얻으실 수 있습니다.
제가 직접 볼 수 있는 게 아니라 추정만 해보자면,
fragement까지 experience 데이터가 안 넘어왔을 수 있을 것 같아요.
올려주신 fragment-card-experience.html은,
experiences 리스트의 각각의 experience에 대해서 풀어주는 화면입니다.
그보다 상위의 resume.html에서 아래 코드와 같이 experiences에 대해 반복을 돌며
각 experience를 fragment로 넣어주고 있는지 확인해보셔도 좋을 것 같아요.
<!-- Experience Cards -->
<th:block th:each="experience :{resume.experiences}">
<div th:replace="~{presentation/fragments/fragment-card-experience :: card(${experience}) }"></div>
</th:block>
필요에 따라 자바스크립트로 experiences나 experience를 로그를 찍어보셔도 좋습니다.
이와 같이 접근하셨을 때 해결이 어려우시다면
깃허브 리포지토리를 공유해주시면 한 번 봐보겠습니다.
감사합니다.
안녕하세요:)
프로젝트 클론해서 실행시켜 봤는데,
localhost:8080/resume로 접속할 경우 화면이 잘 나와서요.
아마 강의 따라하며 작업하시던 중에 resolve 관련 문제 있어서 질문 올리시고,
작업 중이시던 내용은 커밋 안 하신 것 같은데요.
별도로 브랜치 생성하거나 해서 리포지토리에 올려주시고 답글 주시면 다시 봐보겠습니다.
아 빠른 정답 감사합니다. 그 resume홈페이지는 잘나오는데 experience가 계속 cannot resolve가 떠서 현 상태 커밋은완료했습니다. 한번 처음부터 코드를 다시 다 작성 해볼까요?
2시 46분에 커밋하신 타임리프-템플릿수정(index)가 최신 맞을까요?
제가 해당 소스에서 resume.html만 아래와 같이 수정하면 잘 나오거든요.
experience가 resolve 안 된다는 게 resume 화면 조회할 때 얘기가 아닐까요?
fragment-card-experience까지 잘 동작하는걸로 보여서요.
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/html">
<div th:replace="~{presentation/fragments/fragment-head :: head}"></div>
<body class="d-flex flex-column h-100 bg-light">
<main class="flex-shrink-0" id="content">
<!-- Page Content-->
<div class="container px-5 my-5">
<div class="text-center mb-5">
<h1 class="display-5 fw-bolder mb-0"><span class="text-gradient d-inline">Resume</span></h1>
</div>
<div class="row gx-5 justify-content-center">
<div class="col-lg-11 col-xl-9 col-xxl-8">
<!-- Experience Section-->
<section>
<div class="d-flex align-items-center justify-content-between mb-4">
<h2 class="text-primary fw-bolder mb-0">Experience</h2>
</div>
<!-- Experience Cards -->
<th:block th:each="experience : ${resume.experiences}">
<div th:replace="~{presentation/fragments/fragment-card-experience :: card(${experience}) }"></div>
</th:block>
</section>
<!-- Achievement Section-->
<!-- <section>-->
<!-- <h2 class="text-secondary fw-bolder mb-4">Achievement</h2>-->
<!-- <!– Achievement Cards –>-->
<!-- <th:block th:each="achievement : ${resume.achievements}">-->
<!-- <div th:replace="~{presentation/fragments/fragment-card-achievement :: card(${achievement}) }"></div>-->
<!-- </th:block>-->
<!-- </section>-->
<!-- Divider-->
<div class="pb-5"></div>
<!-- Skills Section-->
<!-- <section>-->
<!-- <!– Skillset Card–>-->
<!-- <div class="card shadow border-0 rounded-4 mb-5">-->
<!-- <div class="card-body p-5">-->
<!-- <!– Skills list–>-->
<!-- <th:block th:each="skillType: ${skillTypes}">-->
<!-- <div th:replace="~{presentation/fragments/fragment-list-skill :: list(${resume.skills}, ${skillType.name()}) }"></div>-->
<!-- </th:block>-->
<!-- </div>-->
<!-- </div>-->
<!-- </section>-->
</div>
</div>
</div>
</main>
</body>
</html>
조금 더 상황을 자세히 설명해주시거나,
전체 에러 로그를 주셔도 좋을 것 같습니다.
아니면 https://github.com/infomuscle/portfolio-yongback 에서 소스 받으셔서
현재 작업 중이신 강의의 커밋으로 리셋하신 후 비교해보셔도 도움될 것 같습니다.
혹시 다시 한번 해봐 주실수 있나요? 방금 커밋했구
https://github.com/kimauto/portfolio-kimauto
Exception evaluating SpringEL expression: "experience.startYearMonth" (template: "presentation/fragments/fragment-card-experience" - line 9, col 57)] with root cause 이런한 오류로 resume 페이지가 안열립니다. 죄송합니다. ㅠ
최종 버전에 fragement-card-experience.html이 삭제되어 있어서,
복구하고 실행시켜보니 Exception evaluating SpringEL expression: "experience.startYearMonth"와 같은 로그가 뜨네요.
이 상황에서 제 접근법을 설명드려보겠습니다.
일단 에러 로그를 보면 experience.startYearMonth를 찾지 못해서 에러가 발생하는 것으로 추정됩니다.
startYearMonth 필드의 문제인지, experience 자체의 문제인지 확인하기 위해 해당 라인을 주석 처리 해봤어요.
그랬더니 experience.description에 대해 똑같은 에러가 떠서 experience 데이터가 템플릿으로 제대로 전달되지 못하고 있다고 생각했습니다.
그럼 해당 fragment는 th:fragment="card(experience)"와 같이 선언되어있고,
card(experience)를 통해서 experience 데이터를 받죠?
이 fragment를 호출하는 곳에서 제대로 데이터를 넣어주는지 확인하기 위해 resume.html을 봤습니다.
그랬더니 아래와 같이 선언되어 있었어요.
<th:block th:each="experience : ${resume.experiences}">
<div th:replace="~{presentation/fragments/fragment-card-experience :: card(experience)}"></div>
</th:block>
여기서 card(experience) 부분만 card(${experience})로 바꿔주니
resume 페이지가 정상 조회됩니다.
이제 설명을 드리면,
th:block 태그에서 th:each 속성을 활용해서 resume.experiences 리스트의 각각 요소를 반복하는데,
이 요소를 experience라고 저희가 선언했습니다.
그런데 th:block 태그 안에서 해당 요소를 선택하려면 ${}로 감싸줘야 합니다.
이건 타임리프 문법적인 부분이고요.
그런데 단순히 experience를 넣어줬으니 리스트 안의 experience 데이터가 아니고
experience라는 문자열이 들어가게 된겁니다.
문자열은 startYearMonth 같은 필드가 없으니 오류가 발생했고요.
이 부분을 코틀린 코드로 표현하자면 다음 코드 중 아래와 같은 상황이었다고 보시면 이해가 되실 것 같아요.
// 정상적으로 experience 데이터를 넣는 경우
for (experience in resume.experiences) {
println(experience)
}
// experiences 리스트에 대해 반복을 돌면서 "experience" 문자열을 넣는 경우
for (experience in resume.experiences) {
println("experience")
}
아니면 card(${experience})가 아니고 card(experience)라고 선언한 상태에서,
fragement-card-experience.html을 다음과 같이 바꿔보세요.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="card shadow border-0 rounded-4 mb-5" th:fragment="card(experience)">
<div class="card-body p-5">
<div class="row align-items-center gx-5">
<div th:text="${experience}"></div>
</div>
</div>
</div>
</body>
</html>
fragment에 들어온 데이터가 experience 객체가 아니고 "experience"라는 문자열이었단 걸 확인하실 수 있습니다.
해결했습니다. 정말 친절하게 답변해주셔서 감사합니다. 앞으로는 좀 더 정확하게 해결해보겠습니다. 덕분에 공부에 지친 마음에 힘이됩니다. 아직 제가 전체적인 지식이 많이 부족한 것같습니다. 혼자 해결하려는 습관을 기르도록하겠습니다! 감사합니다!!
0
안녕하세요, 인프런 AI 인턴입니다.
김병곤님의 질문을 바탕으로 하여, Thymeleaf 템플릿에서 모델이 제대로 인식되지 않는 문제에 대해 유사한 해결 방안을 제시했던 링크를 찾았습니다. 문제 해결에 도움이 될 수 있을 것 같아 추천드립니다.
제시된 사례와 유사하게, 김병곤님의 문제도 Thymeleaf 템플릿에서 experience
객체의 startYearMonth
, endYearMonth
등의 프로퍼티를 인식하지 못하는 것으로 보입니다. 이 경우, 컨트롤러에서 Model
객체에 experience
객체 또는 이를 포함하는 resume
객체를 정확하게 전달하고 있는지, DTO에서 해당 프로퍼티를 정의하였는지 등을 확인할 필요가 있습니다.
또한, Thymeleaf 템플릿에서 객체를 정상적으로 참조하기 위해서는 컨트롤러, 서비스, DTO 간의 데이터 전달이 올바르게 이루어지고 있는지 점검하는 것이 중요합니다. 특히 Model
객체에 데이터를 추가할 때 사용하는 키 값들이 뷰(Template)에서 사용하는 이름과 일치하는지 확인해보세요.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
안녕하세요 혼자 해결하려고 노력을 해봤는데 코드 하나하나 다봐봤는데 너무 안찾아지는데 혹시 도움을 주실수있을까요? https://github.com/kimauto/portfolio-kimauto