Backend
home
🖋️

6일차

생성일
2024/07/15 15:11
태그
본 프로젝트는 “스프링부트 3 백엔드 개발자 되기” 서적을 참고하여 진행하였음

블로그 글 목록 뷰 구현

요청을 받아 사용자에게 뷰를 보여주려면 뷰 컨트롤러가 필요함
뷰 컨트롤러 메서드는 뷰의 이름을 반환하고, 모델 객체에 값을 담음
뷰에 전달하기 위한 객체 생성
package com.example.msblog.dto; import com.example.msblog.domain.Article; import lombok.Getter; @Getter public class ArticleListViewResponse { private final Long id; private final String title; private final String content; public ArticleListViewResponse(Article article) { this.id = article.getId(); this.title = article.getTitle(); this.content = article.getContent(); } }
Java
복사
/article GET 요청을 처리할 코드 작성 - 블로그 글 전체 리스트를 담은 뷰를 반환
addAttribute() 메서드를 사용해 모델에 값을 저장
“articles” 키에 블로그 글들을, 즉, 글 리스트를 저장
package com.example.msblog.controller; import com.example.msblog.dto.ArticleListViewResponse; import com.example.msblog.service.BlogService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import java.util.List; @RequiredArgsConstructor @Controller public class BlogViewController { private final BlogService blogService; @GetMapping public String getArticles(Model model) { List<ArticleListViewResponse> articles = blogService.findAll().stream() .map(ArticleListViewResponse::new) .toList(); model.addAttribute("articles", articles); // 블로그 글 리스트 저장 return "articleList"; // articleList.html 라는 뷰 조회 } }
Java
복사
HTML 뷰 만들기
th:each로 “articles” 키에 담긴 데이터 개수만큼 반복
th:text 는 반복 대상 객체의 id, “text” 를 출력
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>블로그 글 목록</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"> </head> <body> <div class="p-5 mb-5 text-center</> bg-light"> <h1 class="mb-3">My Blog</h1> <h4 class="mb-3">블로그에 오신 것을 환영합니다.</h4> </div> <div class="container"> <div class="row-6" th:each="item : ${articles}"> <!-- article 개수만큼 반복 --> <div class="card"> <div class="card-header" th:text="${item.id}"> <!-- item의 id 출력 --> </div> <div class="card-body"> <h5 class="card-title" th:text="${item.title}"></h5> <p class="card-text" th:text="${item.content}"></p> <a th:href="@{/articles/{id}(id=${item.id})}" class="btn btn-primary">보러가기</a> </div> </div> <br> </div> </div> </body> </html>
HTML
복사
출력 화면 확인

블로그 글 뷰 구현

블로그 화면 상의 [보러 가기] 버튼을 누르면 블로그 글이 보이도록 블로그 글 뷰를 구현
엔티티에 생성 시간, 수정 시간 추가하고, 컨트롤러 메서드를 만든 후 HTML 뷰를 만들고 확인하는 과정으로 개발
도메인에 생성 시간, 수정 시간 지정하는 컬럼 추가
// Article.java @CreatedDate // 엔티티가 생성될 때 생성 시간 지정 @Column(name = "created_at") private LocalDateTime createdAt; @LastModifiedDate // 엔티티가 수정될 때 수정 시간 지정 @Column(name = "updated_at") private LocalDateTime updatedAt;
Java
복사
data.sql - 생성 시간, 수정 시간 값 추가
INSERT INTO article (title, content) VALUES ('제목 1', '내용 1', NOW(), NOW()) INSERT INTO article (title, content) VALUES ('제목 2', '내용 2', NOW(), NOW()) INSERT INTO article (title, content) VALUES ('제목 3', '내용 3', NOW(), NOW())
SQL
복사
created_at, updated_at 자동 업데이트 위한 @EnableJpaAuditing 애노테이션 추가
package com.example.msblog; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; @EnableJpaAuditing // created_at, updated_at 자동 업데이트 @SpringBootApplication public class MsblogApplication { public static void main(String[] args) { SpringApplication.run(MsblogApplication.class, args); } }
Java
복사
컨트롤러 메서드 작성
뷰에서 사용할 DTO 작성
package com.example.msblog.dto; import com.example.msblog.domain.Article; import lombok.Getter; import lombok.NoArgsConstructor; import java.time.LocalDateTime; @NoArgsConstructor @Getter public class ArticleViewResponse { private Long id; private String title; private String content; private LocalDateTime createdAt; public ArticleViewResponse(Article article) { this.id = article.getId(); this.title = article.getTitle(); this.content = article.getContent(); this.createdAt = article.getCreatedAt(); } }
Java
복사
블로그 글 뷰 컨트롤러 작성
// 블로그 글 반환 // 인자 id에 URL로 넘어온 값을 받아 findById() 메서드로 넘겨 글을 조회하고, // 화면에서 사용할 모델에 데이터 저장 후 // 보여줄 화면의 템플릿 이름을 반환 @GetMapping("/articles/{id}") public String getArticle(@PathVariable Long id, Model model) { Article article = blogService.findById(id); model.addAttribute("article", new ArticleViewResponse(article)); return "article"; }
Java
복사
HTML 뷰 만들기
article.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>블로그 글 목록</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"> </head> <body> <div class="p-5 mb-5 text-center</> bg-light"> <h1 class="mb-3">My Blog</h1> <h4 class="mb-3">블로그에 오신 것을 환영합니다.</h4> </div> <div class="container mt-5"> <div class="row"> <div class="col-lg-8"> <article> <input type="hidden" id="article-id" th:value="${article.id}"> <header class="mb-4"> <h1 class="fw-bolder mb-1" th:text="${article.title}"></h1> <div class="text-muted fst-italic mb-2" th:text="|Posted on ${#temporals.format(article.createdAt, 'yyyy-MM-dd HH:mm')} By ${article.author}|"></div> </header> <section class="mb-5"> <p class="fs-5 mb-4" th:text="${article.content}"></p> </section> <button type="button" id="modify-btn" th:onclick="|location.href='@{/new-article?id={articleId}(articleId=${article.id})}'|" class="btn btn-primary btn-sm">수정</button> <button type="button" id="delete-btn" class="btn btn-secondary btn-sm">삭제</button> </article> </div> </body> </html>
HTML
복사

트러블 슈팅

updated_at, created_at 값을 추가하지 않아 에러 발생
INSERT INTO article (title, content, created_at, updated_at) VALUES ('제목 1', '내용 1', NOW(), NOW()) INSERT INTO article (title, content, created_at, updated_at) VALUES ('제목 2', '내용 2', NOW(), NOW()) INSERT INTO article (title, content, created_at, updated_at) VALUES ('제목 3', '내용 3', NOW(), NOW())
SQL
복사