

package com.mysite.sbb.question;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor---①
@Controller
public class QuestionController {
private final QuestionRepository questionRepository;
@GetMapping("/question/list")
public String list(Model model)💡 {
List<Question> questionList = this.questionRepository.findAll();
model.addAttribute("questionList", questionList);
return "question_list";
}
}
① : RequiredArgsConstructor 애너테이션으로 questionRepository 속성을 포함하는 생성자를 생성.
롬복이 제공하는 애너테이션으로, final이 붙은 속성을 포함하는 생성자를 자동으로 생성하는 역할을 한다.
@Getter, @Setter가 자동으로 Getter, Setter 메서드를 생성하는 것과 마찬가지로 @RequiredArgsConstructor는 자동으로 생성자를 생성한다.
따라서 스프링 의존성 주입 규칙에 의해 questionRepository 객체가 자동으로 주입된다.
💡 Model 객체 : 따로 생성할 필요 없이, 컨트롤러 메서드의 매개변수로 지정하기만 하면 스프링부트가 자동으로 Model 객체를 생성한다.
Question 리포지터리의 findAll 메서드를 사용하여 질문 목록 데이터인 questionList를 생성, Model 객체에 questionList라는 이름으로 값을 저장했다.
Model 객체는 자바 클래스와 템플릿 간의 연결고리 역할을 한다.
Model 객체에 값을 담아두면 템플릿에서 그 값을 사용할 수 있다.
1. @Autowired 속성
: 속성에 애너테이션을 적용해 객체를 주입하는 방식
2. 생성자
: 생성자를 작성하여 객체를 주입하는 방식(권장하는 방식)
3. Setter
: Setter 메서드를 작성하여 객체를 주입하는 방식(메서드에 @Autowired 애너테이션 적용이 필요하다.)
테스트코드 SbbApplicationTests.java에서는 속성에 @Autowired 애너테이션을 사용하여 객체를 주입했다.
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table>
<thead>
<tr>
<th>제목</th>
<th>작성일시</th>
</tr>
</thead>
<tbody>
<tr th:each="question : ${questionList}">
<td th:text="${question.subject}"></td>
<td th:text="${question.createDate}"></td>
</tr>
</tbody>
</table>
</body>
</html>
th: 로 시작하는 속성은 타임리프 템플릿 엔진이 사용하는 속성이다. 이 부분이 자바 코드와 연결된다.
<tr th:each="question : ${questionList}">
QuestionController의 list 메서드에서 조회한 질문 목록 데이터를 questionList 라는 이름으로 Model 객체에 저장했다.
타임리프는 Model 객체에 저장된 값을 읽을 수 있으므로 템플릿에서 questionList 를 사용할 수 있게 되는 것이다.
questionList의 갯수만큼 반복하여 출력하는 역할을 한다.
questionList에 저장된 데이터를 하나씩 꺼내 question 객체에 대입하여 반복구간 내에서 사용할 수 있게 한다.
자바의 for each문을 떠올리면 쉽게 이해할 수 있다.
<td th:text="${question.subject}"></td>
위의 코드 for문에서 얻은 question 객체의 제목을 td 엘리먼트의 텍스트로 출력한다.

th:if="${question != null}"
question 객체가 null이 아닌 경우 해당 엘리먼트가 표시된다.
th:each="question : ${questionList}"
th:each="question, loop : ${questionList}"
반복 횟수만큼 해당 엘리먼트를 반복하여 표시한다. 자바의 for each 문과 유사하다.

출처 : https://wikidocs.net/161186
th:text="${question.subject}"<tr th:each="question : ${questionList}">
<td>[[${question.subject}]]</td>
<td>[[${question.createDate}]]</td>
</tr>