Jump to String Boot - 2

현곤·2024년 12월 26일

목록 페이지

build.gradle (타임리프)

implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'

2-07 Controller

@RequestMapping("/question")
@Controller
public class QuestionController {
    @GetMapping("/list")
    public String list() {
        return "question_list";
    }
}

2-07 Controller 안에 Repository

@RequiredArgsConstructor
@RequestMapping("/question")
@Controller
public class QuestionController {

    private final QuestionRepository questionRepository;

    @GetMapping("/list")
    public String list(Model model) {
        List<Question> questionList = this.questionRepository.findAll();
        model.addAttribute("questionList", questionList);
        return "question_list";
    }
}

매개변수로 model 지정시 객체가 자동으로 생성

@RequiredArgsController 애너테이션으로
생성자 방식 QuestionRepository 객체 주입

스프링 부트가 내부적으로 QuestionController 를 생성할 때,

롬복으로 만들어진 생성자에 의해

QuestionRepository 객체가 자동으로 주입

QuestionRepositoryfindAll 메서드를 사용

질문 목록 데이터 questionList 를 생성

Model 객체에 'questionList' 라는 이름으로 저장

Model 객체에 값을 담아두면 템플릿에서 그 값을 사용할 수 있음

Model 객체는 따로 생성할 필요 없이 컨트롤러의 메서드에 매개변수로

지정하기만 하면 스프링 부트가 자동으로 Model 객체 생성

Model 객체는 자바 클래스와 템플릿을 이어주는 연결고리 역할

2-07 question_list.html

<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>

타임리프는 다음에 배우기

2-08 MainController

@GetMapping("/")
    public String root() {
        return "redirect:/question/list";
    }

root 메서드에 / URL 매핑

이렇게 하면 기본적으로 /question/list 페이지가 나옴

2-09 Service 만들기

@RequiredArgsConstructor
@Service
public class QuestionService {
    private QuestionRepository questionRepository;
    
    public List<Question> getList() {
        return this.questionRepository.findAll();
    }
}

@Service 어노테이션 붙이기

@RequiredArgsConstructor = questionRepository 생성자 방식 주입

getList() 조회 메서드 만들기

2-10 질문 내용

<table>
    <thead>
    <tr>
        <th>제목</th>
        <th>작성일시</th>
    </tr>
    </thead>
    <tbody>
    <tr th:each="question : ${questionList}">
        <td>
            <a th:href="@{|/question/detail/${question.id}|}" th:text="${question.subject}"></a>
        </td>
        <td th:text="${question.createDate}"></td>
    </tr>
    </tbody>
</table>

<td th:text="${question.subject}"></td>

요게 없어지고 저게 들어감

질문 목록의 제목을 텍스트로 출력하던 것을

질문의 상세 내용이 담긴 웹 페이지로 이동할 수 있는 링크로 변경

2-10 Controller detail 추가

@GetMapping(value = "/detail/{id}")
    public String detail(Model model, @PathVariable("id") Integer id) {
        return "question_list";
    }

detail/2 처럼 변하는 id 값을 얻기 위해선 @PathVariable("id") 를 사용

이때 (value= "/detail/{id}"){id}
@PathVariable("id") 가 같아야함

value의 id = Variable = id
id가 아니더라도 매개변수의 이름이 이와 같이 동일해야 한다.

2-10 상세 페이지에 서비스 사용

질문 데이터 조회를 위해 서비스 수정

public Question getQuestion(Integer id) {
        Optional<Question> question = this.questionRepository.findById(id);
        if (question.isPresent()) {
            return question.get();
        } else {
            throw new DataNotFoundException("question not found");
        }
    }

id 값으로 질문 데이터를 조회하기 위해 getQuestion 메서드 추가

리포지터리로 얻은 Question 객체 = Optional 객체

if, else 문을 통해 isPresent 메서드로
해당 데이터가 존재하는지 검사하는 과정 추가

id 값에 해당하는 데이터가 없다면,
예외 클래스인 DataNotFoundException 이 실행

2-10 DataNotFoundException

public class DataNotFoundException extends RuntimeException{
    private static final long serialVersionUTD = 1L;
    public DataNotFoundException(String message) {
        super(message);
    }
}

데이터베이스에서 특정 엔티티 또는 데이터를 찾을 수 없을 때
발생시키는 예외 클래스

이게 발생하면 스프링 부트는 설정된
HTTP 상태 코드 (HTTPStatus.NOT_FOUND)
이유 ("entity not found") 를 포함한 응답을 생성해 클라이언트에게 반환

여기선 404 오류를 반환하도록 작성

DataNotFoundExceptionRuntimeException 을 상속받는 이유는, 데이터가 없다는 상황을 언체크 예외로 처리함으로써 개발자가 예외를 명시적으로 처리하지 않아도 되게 하기 위함입니다.
이를 통해 더 깔끔하고 간결한 코드를 작성할 수 있습니다.

2-10 Controller getQuestion 추가

@GetMapping(value = "/detail/{id}")
    public String detail(Model model, @PathVariable("id") Integer id) {
        Question question = this.questionService.getQuestion(id);
        model.addAttribute("question", question);
        return "question_detail";
    }

Service 안에 있는 getQuestion 메서드를 호출하여,

Question 객체를 템플릿이랑 이어주는 model.addAttribute 사용

2-10 question_detail.html 수정

<h1 th:text="${question.subject}"></h1>
<div th:text="${question.content}"></div>

'제목', '내용' 문자열 대신 subject (제목) , content (내용) 을 출력

profile
코딩하는 곤쪽이

0개의 댓글