프로젝트 : springbootclass-bbs01

의존성 설정

Spring Starter Project 메뉴를 이용해 스프링 부트 프로젝트를 생성할 때 프로젝트에 필요한 기본적인 의존성을 선택해서 프로젝트를 생성했기 때문에 아직까지 build.gradle 파일에 추가적인 설정은 필요 없다.
프로젝트 환경 설정 파일인 application.properties 파일에 데이터베이스 등의 설정을 다음과 같이 추가하자.
src/main/resources/application.properties
src/main/resources/application.properties
#Database
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useSSL=false&useUnicode=tr
ue&serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=12345678
#JPA
#데이터베이스 종류
spring.jpa.database=mysql
#특정 DB 고유 기능을 JPA 방언(Dialect)이라고 부름
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
#console에 SQL 문을 보기 좋게 출력
spring.jpa.properties.hibernate.format_sql=true
#엔티티 클래스를 기준으로 DB 테이블 변경 규칙
spring.jpa.hibernate.ddl-auto=update
#SQL 문 로깅 활성화 여부
spring.jpa.show-sql=true
#해당 메서드가 끝날 때 JPA의 영속성 컨텍스트가 DB 커넥션 반환
spring.jpa.open-in-view=false
#정적 파일 변경 실시간 반영
spring.devtools.remote.restart.enabled=false
spring.devtools.livereload.enabled=true
#Thymeleaf 뷰 설정 - prefix와 suffix는 아래 경로가 기본 값임
#spring.thymeleaf.prefix=classpath:/templates/
#spring.thymeleaf.suffix=.html
#spring.thymeleaf.view-names=views/*
#thymeleaf에 대한 캐시를 남기지 않음, cache=false 설정(운영시는 true)
spring.thymeleaf.cache =false
#Thymeleaf 사용 활성화
#spring.thymeleaf.enabled=true
#렌더링 전에 템플릿 존재여부 확인 옵션
#spring.thymeleaf.check-template=false
#template 위치 존재여부 확인 옵션 - 없으면 오류 발생
#spring.thymeleaf.check-template-location=true
프로젝트에 com.springbootstudy.bbs.domain 패키지를 새로 만들어서 게시 글 하나의 정보를 관리하며 springbbs 테이블과 1:1로 맵핑되는 Board Entity 클래스를 다음 코드를 참고해 작성하자.
Entity 클래스는 실제 DB 테이블과 1:1로 맵핑되는 핵심 클래스로 DB 테이블에 존재하는 컬럼을
필드로 가지며 테이블에 없는 컬럼을 가져서는 안 된다.
@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name="springbbs")
public class Board {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int no;
@Column(name="title", length=50, nullable = false)
private String title;
@Column(length=10, nullable=false)
private String writer;
@Column(columnDefinition = "TEXT", nullable=false)
private String content;
@Temporal(TemporalType.TIMESTAMP)
@Column(nullable=false)
private Timestamp regDate;
@Column(precision=5, nullable=false)
private int readCount;
@Column(length=20, nullable=false)
private String pass;
private String file1;
}
public interface BoardRepository extends JpaRepository<Board, Integer> {
// JpaRepository를 상속하여 기본적인 CRUD 메서드를 상속받음
}
@Service
@Slf4j
public class BoardService {
@Autowired
private BoardRepository boardRepository;
public List<Board> boardList() {
log.info("BoardService: boardList()");
return boardRepository.findAll(Sort.by(Sort.Direction.DESC, "no"));
}
}
엔티티 (Board): JPA 어노테이션을 사용하여 데이터베이스 테이블을 나타내는 클래스.
리포지토리 (BoardRepository): JpaRepository를 확장하여 Board 엔티티에 대한 기본 CRUD 작업을 상속받음.
서비스 (BoardService): 비즈니스 로직을 구현하며, 여기서는 no를 기준으로 정렬된 게시글 목록을 가져옵니다.
컨트롤러 (BoardController): HTTP 요청을 처리하며, BoardService를 사용하여 데이터를 가져와 Thymeleaf 뷰에 전달합니다.
이 구성은 Spring Boot 애플리케이션에서 Spring Data JPA를 사용하여 데이터를 영구 저장하는 일반적인 구조를 보여줍니다. 특정 애플리케이션 요구사항이나 추가 기능에 따라 필요에 맞게 조정할 수 있습니다.
뷰페이지를 보면 메뉴와 푸터 부분은 여러 페이지에 표시되기 때문에 이부분은 매번 중복되는데 이렇게 중복되는 코드를 줄이고 효율적으로 뷰 페이지를 관리하기 위해서 중복되는 코드를 header,content,footer 부분으로 나눠서 각각의 파일로 모듈화 해보자
페이지 모듈화는 하나의 페이지를 표현하는 템플릿을 나눠서 여러 개의 템플릿 조각 파일로 나눠서 저장하고 실행될 때 다시 하나로 동작하도록 만들면 되는데 Thymeleaf에서 하나의 페이지를 템플릿 조각으로 나눠서 저장하기 위해서 fragment와 layout을 사용한다. 그맇고 여러개로 나눠진 fragment와 layout을 사용한다. 그리고 여러 개로 나눠진 fragment와 layout 파일을 하나로 묶어 주는 메인 레이아웃 파일을 만들어서 이들을 하나로 동작할 수 있도록 설정하면 된다.

build.gradle에 추가하고 Refresh Gradle Project 실행
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<!--/* header */-->
<!--/* 아래와 같이 block으로 한 번 감싸도 괜찮음
<th:block th:fragment="header">
*/-->
<div th:fragment="header" class="row border-bottom border-primary">
<!--헤더 폼-->
</div>
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<!--/* footer */-->
<div th:fragment="footer" class="row border-top border-primary my-5">
<!--푸터 폼-->
</div>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layouts/main_layout}">
<!--/* content */-->
<!--/*
block을 사용해도 되고 div에 직접 layout:fragment를 적용해도 됨
main_layout.html에서 지정한 layout:fragment의 이름과 같아야 함
*/-->
<th:block layout:fragment="content">
<!--content폼-->
</th:block >
<!DOCTYPE html>
<!--/* Thymeleaf와 Thymeleaf Layout을 사용하기 위한 NameSpace 정의 */-->
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>BoardService</title>
<link th:href="@{bootstrap/bootstrap.min.css}" rel="stylesheet" >
<style>
</style>
</head>
<body>
<div class="container">
<!--/* header */-->
<!--/* 경로는 templates을 기준으로 지정하면 됨 *-->
<div th:replace="~{fragments/header::header}"></div>
<!--/* content : 요청 마다 변경되는 부분 */-->
<div layout:fragment="content"></div>
<!--/* footer */-->
<div th:replace="~{fragments/footer::footer}"></div>
</div>
<script th:src="@{bootstrap/bootstrap.bundle.min.js}"></script>
</body>
</html>
이런식으로 header,content,footer를 분리하여 중복되는 코드를 나누는것이 좋다.