IntelliJ IDEA를 사용하여 스프링 부트(Spring Boot) 기반의 웹 애플리케이션을 개발하며, JPA(Java Persistence API)를 통해 MySQL 데이터베이스를 사용하고 Thymeleaf를 사용하여 간단한 게시판의 CRUD(Create, Read, Update, Delete) 기능을 구현하는 과정을 설명합니다. 이 프로젝트를 만들기 위한 단계별 가이드입니다.
전제 조건:
- IntelliJ IDEA 설치
- JDK 11 설치
- 스프링 부트 프로젝트 생성 및 설정
- MySQL 데이터베이스 설치 및 설정
IntelliJ IDEA로 스프링 부트 프로젝트 생성
IntelliJ IDEA를 열고 "File" 메뉴에서 "New"를 선택한 다음 "Project"를 클릭합니다.
"Spring Initializr"를 선택하고 프로젝트 설정을 진행합니다.
프로젝트 유형: Gradle 선택
언어: Java 선택
패키징 : War 선택
자바 버전 : 11 선택
의존성 추가: "Spring Boot DevTools", "Spring Web", "Lombok", "Thymeleaf", "Spring Data JPA", "MySQL Driver" 추가
"Next"를 클릭하고 프로젝트 디렉토리 및 이름을 설정한 다음 "Finish"를 클릭하여 프로젝트를 생성합니다.
출력결과
게시판 기본 기능
- list
- read
- write
- update
- delete
- search (type, keyword)
build.gradle
plugins {
id 'java'
id 'war'
id 'org.springframework.boot' version '2.7.14'
id 'io.spring.dependency-management' version '1.1.2'
}
group = 'com.naya'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '11'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.mysql:mysql-connector-j'
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
annotationProcessor 'org.projectlombok:lombok'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
resources/application.yml
server:
address: localhost
port: 8080
spring:
jpa:
show-sql: true
database: mysql
properties:
hibernate:
ddl-auto: create
format_sql: true
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/dbname?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Seoul
username: username
password: password
thymeleaf:
cache: false
prefix: file:src/main/resources/templates/
suffix: .html
devtools:
restart:
enabled: true
프로젝트 구조
controller/BbsController
package com.naya.shopjpa.controller;
import com.naya.shopjpa.model.Bbs;
import com.naya.shopjpa.service.BbsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
@Controller
@RequestMapping("/bbs")
public class BbsController {
@Autowired
private BbsService bbsService;
@GetMapping("/list")
public String bbsList(Model model) {
List<Bbs> bbs = bbsService.getList();
model.addAttribute("bbs", bbs);
return "bbs/list";
}
@PostMapping("/search")
public String bbsSearchList(Model model, @RequestParam String type, @RequestParam String keyword) {
List<Bbs> bbs = bbsService.getSearchList(type, keyword);
model.addAttribute("bbs", bbs);
return "bbs/list";
}
@GetMapping("/{id}")
public String bbsRead(Model model, @PathVariable Long id) {
Optional<Bbs> item = bbsService.getById(id);
model.addAttribute("item", item);
return "bbs/read";
}
@GetMapping("/write")
public String bbsWriteForm() {
return "bbs/write";
}
@PostMapping("/write")
public String bbsWrite(Model model, Bbs bbs) {
bbsService.addBbs(bbs);
return "redirect:/bbs/list";
}
@GetMapping("/remove/{id}")
public String bbsRemove(Bbs bbs, @PathVariable Long id) {
bbsService.deleteBbs(id);
return "redirect:/bbs/list";
}
@GetMapping("/update/{id}")
public String bbsUpdateForm(Model model, @PathVariable Long id) {
Optional<Bbs> item = bbsService.getById(id);
model.addAttribute("item", item);
return "bbs/update";
}
@PostMapping("/update")
public String bbsUpdate(Bbs bbs) {
System.out.println(bbs.toString());
bbsService.updateBbs(bbs);
return "redirect:/bbs/list";
}
}
게시판 list / search list
위 컨트롤러는 /bbs 경로를 기반으로 다양한 HTTP 요청을 처리하고, 서비스 클래스인 BbsService를 사용하여 데이터를 관리합니다.
@Controller 및 @RequestMapping("/bbs")
클래스에 @Controller 어노테이션을 붙여서 스프링에게 이 클래스가 컨트롤러임을 알립니다.
@RequestMapping("/bbs")는 이 컨트롤러의 모든 메소드에 적용되는 기본 URL 경로를 정의합니다.
@Autowired private BbsService bbsService;
BbsService 인터페이스를 구현한 BbsService 빈을 주입받습니다.
@GetMapping("/list")
HTTP GET 요청을 처리하는 메소드로, /bbs/list 경로로 요청이 오면 실행됩니다.
bbsService.getList()를 호출하여 게시글 목록을 가져온 다음, Thymeleaf 모델에 bbs라는 이름으로 추가합니다.
@PostMapping("/search")
HTTP POST 요청을 처리하는 메소드로, /bbs/search 경로로 요청이 오면 실행됩니다.
@RequestParam을 사용하여 type, keyword라는 파라미터를 받아옵니다.
bbsService.getSearchList(type,keyword)를 호출하여 검색 결과를 가져온 다음, Thymeleaf 모델에 bbs라는 이름으로 추가합니다.
게시판 read
@GetMapping("/{id}")
HTTP GET 요청을 처리하는 메소드로, /bbs/{id} 경로로 요청이 오면 실행됩니다. {id}는 게시글의 고유한 식별자입니다.
@PathVariable을 사용하여 id라는 경로 변수를 받아옵니다. URL 에서 받아옵니다.
bbsService.getById(id)를 호출하여 해당 게시글을 가져온 다음, Thymeleaf 모델에 item이라는 이름으로 추가합니다.
게시판 write
@GetMapping("/write")
HTTP GET 요청을 처리하는 메소드로, /bbs/write 경로로 요청이 오면 실행됩니다.
게시글 작성 폼을 표시하는 페이지로 리다이렉션합니다.
@PostMapping("/write")
HTTP POST 요청을 처리하는 메소드로, /bbs/write 경로로 요청이 오면 실행됩니다.
Bbs 객체를 파라미터로 받아서 게시글을 작성하고, 작성된 게시글을 목록 페이지로 리다이렉션합니다.
게시판 delete
@GetMapping("/remove/{id}")
HTTP GET 요청을 처리하는 메소드로, /bbs/remove/{id} 경로로 요청이 오면 실행됩니다.
@PathVariable을 사용하여 id라는 경로 변수를 받아옵니다.
해당 id에 해당하는 게시글을 삭제하고, 게시글 목록 페이지로 리다이렉션합니다.
게시판 update
@GetMapping("/update/{id}")
HTTP GET 요청을 처리하는 메소드로, /bbs/update/{id} 경로로 요청이 오면 실행됩니다.
@PathVariable을 사용하여 id라는 경로 변수를 받아옵니다.
해당 id에 해당하는 게시글을 수정하기 위한 폼 페이지로 이동합니다.
@PostMapping("/update")
HTTP POST 요청을 처리하는 메소드로, /bbs/update 경로로 요청이 오면 실행됩니다.
수정된 게시글 정보를 저장하고, 게시글 목록 페이지로 리다이렉션합니다.
search/BbsSearch.java
package com.naya.shopjpa.service;
import com.naya.shopjpa.model.Bbs;
import java.util.List;
import java.util.Optional;
public interface BbsService {
List<Bbs> getList();
List<Bbs> getSearchList(String type, String keyword);
Optional<Bbs> getById(Long id);
boolean addBbs(Bbs bbs);
void deleteBbs(Long id);
boolean updateBbs(Bbs bbs);
}
위 코드는 BbsService라는 인터페이스를 정의한 것으로, Spring Boot 애플리케이션에서 사용되는 게시글 서비스의 메서드를 정의하고 있습니다. 이 인터페이스를 구현한 클래스는 게시글 관련 기능을 구현하게 됩니다.
List<Bbs> getList(): 게시글 목록을 가져오는 메서드입니다. 이 메서드는 모든 게시글을 가져와서 리스트로 반환합니다.
List<Bbs> getSearchList(String type, String keyword): 특정 키워드를 포함하는 게시글 목록을 가져오는 메서드입니다. 검색 기능을 위해 type과 키워드를 입력받고, 해당 키워드를 포함하는 게시글들을 리스트로 반환합니다.
Optional<Bbs> getById(Long id): 게시글의 고유한 식별자(ID)를 기반으로 게시글을 가져오는 메서드입니다. ID를 입력받고 해당 ID에 해당하는 게시글을 Optional 객체로 반환합니다. Optional은 값이 없을 수도 있는 경우를 다룰 때 사용됩니다.
boolean addBbs(Bbs bbs): 새로운 게시글을 추가하는 메서드입니다. Bbs 객체를 입력받아서 데이터베이스에 저장하고, 성공 여부를 불리언으로 반환합니다.
void deleteBbs(Long id): 게시글을 삭제하는 메서드입니다. 삭제할 게시글의 ID를 입력받아 해당 게시글을 삭제합니다.
boolean updateBbs(Bbs bbs): 게시글을 수정하는 메서드입니다. 수정할 게시글 정보를 입력받아 데이터베이스에서 해당 게시글을 찾아 수정하고, 성공 여부를 불리언으로 반환합니다.
이 BbsService 인터페이스를 구현한 클래스는 이러한 메서드들을 구현하여 실제 게시글 서비스를 제공하게 됩니다. 이렇게 인터페이스와 구현 클래스를 분리함으로써 코드의 유지보수와 확장성을 높일 수 있습니다.
service/BbsServiceImpl.java
package com.naya.shopjpa.service;
import com.naya.shopjpa.model.Bbs;
import com.naya.shopjpa.repository.BbsRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
@Service
public class BbsServiceImpl implements BbsService {
@Autowired
private BbsRepository bbsRepository;
@Transactional
public List<Bbs> getList() {
return bbsRepository.findAll();
}
@Transactional
public List<Bbs> getSearchList(String type, String keyword) {
if ("title".equals(type)) {
return bbsRepository.findByTitleContaining(keyword);
} else if ("name".equals(type)) {
return bbsRepository.findByNameContaining(keyword);
} else if ("content".equals(type)) {
return bbsRepository.findByContentContaining(keyword);
} else {
// 지원하지 않는 검색 유형인 경우 빈 리스트 반환
return Collections.emptyList();
}
}
@Transactional
public Optional<Bbs> getById(Long id) {
return bbsRepository.findById(id);
}
@Transactional
public boolean addBbs(Bbs bbs) {
return bbsRepository.save(bbs) != null;
}
@Transactional
public void deleteBbs(Long id) {
bbsRepository.deleteById(id);
}
@Transactional
public boolean updateBbs(Bbs bbs) {
return bbsRepository.save(bbs) != null;
}
}
위 코드는 BbsService 인터페이스를 구현한 BbsServiceImpl 클래스입니다. 이 클래스는 게시글 서비스의 실제 구현을 담당합니다.
아래에서 코드의 주요 내용을 설명하겠습니다.
@Service 어노테이션: 이 어노테이션은 스프링 프레임워크에게 해당 클래스가 서비스 클래스임을 알려줍니다. 이것은 컴포넌트 스캔을 통해 스프링 애플리케이션 컨텍스트에 빈으로 등록되게 합니다.
@Autowired 어노테이션: 이 어노테이션은 BbsRepository 인스턴스를 자동으로 주입하도록 스프링에게 알려줍니다. BbsRepository는 JPA를 사용하여 데이터베이스와 상호 작용하기 위한 인터페이스입니다.
@Transactional 어노테이션: 이 어노테이션은 각각의 메서드가 트랜잭션 내에서 실행되어야 함을 나타냅니다. 이것은 메서드 내에서 일어나는 모든 데이터베이스 작업을 하나의 트랜잭션으로 묶어줍니다.
getList(): 이 메서드는 모든 게시글을 데이터베이스에서 조회하고 리스트로 반환합니다. bbsRepository.findAll() 메서드를 사용하여 모든 게시글을 가져옵니다.
getSearchList(String keyword): 이 메서드는 특정 키워드를 포함하는 게시글을 검색하고 리스트로 반환합니다. findByTitleContaining(keyword) 메서드는 제목에 주어진 키워드가 포함된 게시글을 검색합니다.
getById(Long id): 이 메서드는 게시글의 고유 ID를 기반으로 게시글을 조회합니다. bbsRepository.findById(id)를 사용하여 해당 ID의 게시글을 가져옵니다.
addBbs(Bbs bbs): 새로운 게시글을 추가하는 메서드입니다. bbsRepository.save(bbs)를 사용하여 게시글을 데이터베이스에 저장하고 저장 성공 여부를 반환합니다.
deleteBbs(Long id): 게시글을 삭제하는 메서드입니다. bbsRepository.deleteById(id)를 사용하여 주어진 ID의 게시글을 삭제합니다.
updateBbs(Bbs bbs): 게시글을 수정하는 메서드입니다. bbsRepository.save(bbs)를 사용하여 게시글을 데이터베이스에 저장하고 저장 성공 여부를 반환합니다.
이 클래스는 BbsService 인터페이스를 구현하여 게시글 서비스의 핵심 로직을 구현하고, 데이터베이스와의 상호 작용을 BbsRepository를 통해 수행합니다.
repository/BbsRepository.java
package com.naya.shopjpa.repository;
import com.naya.shopjpa.model.Bbs;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface BbsRepository extends JpaRepository<Bbs, Long> {
List<Bbs> findByTitleContaining(String keyword);
List<Bbs> findByNameContaining(String keyword);
List<Bbs> findByContentContaining(String keyword);
}
위 코드는 Spring Data JPA에서 제공하는 인터페이스인 JpaRepository를 확장하여 만든 BbsRepository 인터페이스입니다. 이 인터페이스는 데이터베이스 작업을 위한 CRUD(Create, Read, Update, Delete) 메서드를 제공하는데, 여기서는 Bbs 엔티티와 관련된 데이터베이스 작업을 할 수 있는 메서드를 선언하고 있습니다.
JpaRepository<Bbs, Long>: Bbs 엔티티와 기본 키인 Long 형식의 Id 필드를 사용하는 JpaRepository를 정의합니다.
그리고 아래와 같이 몇 가지 메서드를 선언하고 있습니다.
List<Bbs> findByTitleContaining(String keyword): title 필드에서 keyword를 포함하는 모든 레코드를 검색합니다.
List<Bbs> findByNameContaining(String keyword): name 필드에서 keyword를 포함하는 모든 레코드를 검색합니다.
List<Bbs> findByContentContaining(String keyword): content 필드에서 keyword를 포함하는 모든 레코드를 검색합니다.
이렇게 선언된 메서드들은 Spring Data JPA가 자동으로 해당 쿼리를 생성하고 실행할 수 있도록 도와주며, 개발자는 간단한 메서드 선언으로 데이터베이스 작업을 수행할 수 있습니다.
model/Bbs.java
package com.naya.shopjpa.model;
import lombok.Data;
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
@Data
@Table(name = "bbs")
public class Bbs {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idx;
private String title;
private String content;
private String name;
@Column(name = "reg_date", updatable = false)
private LocalDateTime reg_date;
@Column(name = "update_date")
private LocalDateTime update_date;
@PrePersist
protected void onCreate() {
reg_date = update_date = LocalDateTime.now();
}
@PreUpdate
protected void onUpdate() {
update_date = LocalDateTime.now();
}
@Override
public String toString() {
return "Bbs{" +
"idx=" + idx +
", title='" + title + '\'' +
", content='" + content + '\'' +
", name='" + name + '\'' +
", reg_date=" + reg_date +
", update_date=" + update_date +
'}';
}
}
위 코드는 JPA(Java Persistence API)를 사용하여 데이터베이스와 상호작용하는 엔티티 클래스인 Bbs 클래스를 정의한 것입니다. 아래는 코드의 주요 부분을 설명한 것입니다.
@Entity: 엔티티 클래스임을 나타내는 애노테이션입니다. JPA가 이 클래스를 데이터베이스 테이블과 매핑합니다.
@Data: Lombok 라이브러리에서 제공하는 애노테이션으로, getter, setter, toString, equals, hashCode 등의 메서드를 자동으로 생성합니다.
@Table(name = "bbs"): 해당 엔티티를 매핑할 데이터베이스 테이블의 이름을 지정합니다.
@Id: 해당 필드를 엔티티의 기본 키(primary key)로 사용한다는 것을 나타냅니다.
@GeneratedValue(strategy = GenerationType.IDENTITY): 기본 키 값을 자동으로 생성하는 전략을 지정합니다. 여기서는 데이터베이스의 자동 증가(auto-increment) 값을 사용하도록 설정했습니다.
@Column(name = "reg_date", updatable = false): 데이터베이스 컬럼과 매핑되는 필드에 대한 설정입니다. updatable = false로 설정하여 업데이트 시에는 해당 필드의 값을 변경하지 않도록 했습니다.
@PrePersist와 @PreUpdate: 엔티티가 저장 또는 업데이트되기 전에 실행되는 메서드입니다. onCreate 메서드는 엔티티가 생성될 때(INSERT) 호출되며, onUpdate 메서드는 엔티티가 업데이트될 때(UPDATE) 호출됩니다. 여기서는 reg_date를 생성 시점의 현재 날짜와 시간으로 설정하고, update_date는 업데이트 시점의 현재 날짜와 시간으로 설정합니다.
@Override toString(): 객체를 문자열로 표현하기 위한 메서드를 재정의합니다. 이 메서드는 객체의 정보를 문자열로 반환합니다.
이렇게 정의된 Bbs 클래스는 JPA를 사용하여 데이터베이스와 상호작용하며, reg_date와 update_date 필드를 자동으로 관리하고, toString() 메서드를 통해 객체의 내용을 문자열로 표현할 수 있습니다.
'프로그래밍 > Java' 카테고리의 다른 글
spring boot 와 JPA + mysql 사용한 두개 테이블 조인 Insert (0) | 2023.08.23 |
---|---|
spring boot 와 JPA 사용한 프로젝트 전체 구조 (0) | 2023.08.23 |
IntelliJ 이용하여 스프링 부트 + JPA + Mysql 간단한 예제 (0) | 2023.08.22 |
[인텔리제이 2020.3] 스프링 부트 + Java + thymeleaf 수정시 자동 리로드(새로고침) 방법 (최종) (1) | 2023.08.21 |
intelliJ Springboot + MyBatis + MySQL + thymeleaf 셋팅 및 연동(3) (0) | 2023.08.18 |