https://wikidocs.net/book/7601 의 내용을 응용하였습니다.
🌱 아이템 확인하기 (본 포스트)
🌱 아이템 등록하기
🌱 아이템 삭제하기
🌱 아이템 수정하기
project : Gradle Project
Language : Java
Spring Boot : 2.7.0
Project Metadata : 원하는 대로
Packaging : Jar
Java : 11
Dependencies : Spring Web 추가
설정이 끝나면 Generate
다운 받은 것 압축 풀고 IntellJ에서 Open
(2) IntelliJ
@Controller - 컨트롤러
@RequestMapping("/hello") - url과 hello 맵핑
@ResponseBody - hello 메서드의 응답 결과가 문자열 그 자체라는 것을 알려줌
제대로 동작하는 지 확인하고 싶으면
오른쪽 사이드 바 - Gradle - Tasks - applications - bootRun
그리고 localhost:8080/hello로 들어가보면
입력한대로 잘 나온다.
설정이 잘 된 것 같으니, 이젠 진짜 처음에 계획한 걸 만들어보자.
(1) 롬복 설치하기
build.gradle의 dependecies에
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
이후, refresh gradle을 해준다.
(2) h2 데이터베이스 설치하기
build.gradle의 dependecies에
runtimeOnly 'com.h2database:h2'
이후, refresh gradle을 해준다.
application.properties에
# DATABASE
// H2 콘솔의 접속을 허용할지 여부
spring.h2.console.enabled=true
// 콘솔 접속을 위한 URL 경로
spring.h2.console.path=/h2-console
// 데이터베이스 접속을 위한 경로
// jdbc:h2~/local = 사용자의 홈디렉터리 밑에 local.mv.db라는 파일이 있어야 함.
spring.datasource.url=jdbc:h2:~/local
// 데이터베이스 접속시 사용하는 드라이버
spring.datasource.driverClassName=org.h2.Driver
// 데이터베이스의 사용자명 (기본값 sa)
spring.datasource.username=sa
// 패스워드 설정
spring.datasource.password=
다음을 추가한다.
(3) JPA 설정
자바 프로그램에서 데이터베이스에 데이터를 저장하거나 조회하려면 JPA를 사용해야 한다.
build.gradle의 dependecies에
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
를 추가한다.
그리고 application.properites에
# JPA
// 데이터베이스 엔진 종류를 설정한다
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
// 엔티티를 기준으로 테이블을 생성하는 규칙을 정의한다.
spring.jpa.hibernate.ddl-auto=update
이 내용을 추가한다.
(4) 엔티티
엔티티는 데이터베이스 테이블과 매핑되는 자바 클래스를 의미한다. To Do List 를 위한 엔티티를 만들어야 한다.
나는 각 to do list 아이템의 id, content, completed를 원함으로 다음과 같이 작성하였다.
package com.mysite.todo;
import javax.persistence.*;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
// @Controller 처럼 @Entity라고 작성해야한다.
public class ToDoEntity {
@Id // 기본키로 설정한다.
@GeneratedValue(strategy = GenerationType.IDENTITY)
// 데이터를 저장할 때 해당 속성에 따로 값을
// 셋팅하지 않아도 1씩 자동으로 증가
// strategy는 고유 번호를 생성하는 옵션
// GenerationType.IDENTITY는 해당 컬럼만의
// 독립적인 시퀀스를 생성하여 번호를 증가시킬 때
// 사용한다.
private Integer id;
@Column(length=200)
// Column의 세부 설정을 위해 사용
private String content;
@Column(nullable = false)
private Boolean completed;
}
(5) JPA 리포지터리
엔티티만으로는 데이터베이스에 데이터를 저장하거나, 조회할 수 없다. 데이터 처리를 위하여 JPA 리포지터리가 필요.
package com.mysite.todo;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ToDoRepository extends JpaRepository<ToDoEntity,Integer> {
}
JpaRepository 인터페이스를 상속. 리포지터리의 대상이 되는 엔티티의 타입과 해당 엔티티의 PK의 속성 타입을 지정해야함.
(6) 테스트
데이터가 잘 들어가는 지 test 해보기
package com.mysite.todo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ToDoListApplicationTests {
@Autowired
private ToDoRepository toDoRepository;
@Test
void testJpa(){
ToDoEntity todo1 = new ToDoEntity();
todo1.setContent("밥먹기");
todo1.setCompleted(Boolean.TRUE);
this.toDoRepository.save(todo1);
ToDoEntity todo2 = new ToDoEntity();
todo2.setContent("스프링 공부하기");
todo2.setCompleted(Boolean.FALSE);
this.toDoRepository.save(todo2);
}
}
localhost는 종료하고, test를 돌려보자
localhost:8080/h2-console로 들어가서
엔티티 이름 적으면 된다.
select * from TO_DO_ENTITY
입력해보면 우리가 넣은 데이터가 나온다.
(7) 템플릿 연결
이제 템플릿을 연결해서 아이템을 확인할 수 있도록 해보자
타임리프 방식을 사용할 것이고
build.gradle의 dependecies에
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
이후, refresh gradle을 해준다.
resources - templates - todolist.html
더 이상 @ResponseBody는 필요없다.
return "html이름"으로 바꿔주면 된다.
그 결과가 다음과 같다.
(8) 화면에 데이터 전송
이제 템플릿으로 데이터를 보내서 화면에 보여지게끔 만들어보자
Controller를 먼저 수정하자면,
package com.mysite.todo;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@RequiredArgsConstructor
@Controller
public class ToDoController {
private final ToDoRepository toDoRepository;
@RequestMapping("/todo")
public String list(Model model){
List<ToDoEntity> toDoEntityList = this.toDoRepository.findAll();
model.addAttribute("toDoEntityList",toDoEntityList);
return "todolist";
}
}
@RequiredArgsConstructors는 ToDoRepository 속성을 포함하는 생성자를 자동으로 생성하는 것.
@Autowired : 속성에 객체를 주입하는 방식
이제 todolist.html을 수정해보자
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>To Do List</title>
</head>
<body>
<h1>투두리스트</h1>
<table>
<thead>
<tr>
<th>번호</th>
<th>할 일</th>
<th>수행 여부</th>
</tr>
</thead>
<tbody>
<tr th:each="todoentity : ${toDoEntityList}">
<td th:text="${todoentity.id}"></td>
<td th:text="${todoentity.content}"></td>
<td th:text="${todoentity.completed}"></td>
</tr>
</tbody>
</table>
</body>
</html>
> <tr th:each="todoentity : ${toDoEntityList}">
"toDoEntityList"라는 이름으로
데이터를 Model 객체에 저장했기 때문에
<td th:text="${todoentity.content}"></td>
객체의 내용을 텍스트로 출력하기
(9) 리다이렉트
현재는 localhost:8080/에 해당하는 값이 없기때문에
에러가 뜬다. localhost:8080/로 진입할 경우, 우리의 todolist를 보여주는 화면으로 리다이렉트 시켜보자.
package com.mysite.todo;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@RequiredArgsConstructor
@Controller
public class ToDoController {
private final ToDoRepository toDoRepository;
@RequestMapping("/todo")
public String list(Model model){
List<ToDoEntity> toDoEntityList = this.toDoRepository.findAll();
model.addAttribute("toDoEntityList",toDoEntityList);
return "todolist";
}
@RequestMapping("/")
public String root(){
return "redirect:/todo";
}
}
컨트롤러에 root()로 향할 수 있는 메서드를 하나 만들어준다.
(10) 서비스
현재는 컨트롤러에서 리포지토리를 직접 사용하지만, 대규모의 스프링부트 프로젝트는 직접 사용이 아닌 서비스를 통하여 사용한다. 서비스는 데이터 처리를 위해 작성하는 클래스이다.
package com.mysite.todo;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@RequiredArgsConstructor
@Service
public class ToDoService {
private final ToDoRepository toDoRepository;
public List<ToDoEntity> getList(){
return this.toDoRepository.findAll();
}
}
Controller도 수정해주자.
package com.mysite.todo;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@RequiredArgsConstructor
@Controller
public class ToDoController {
private final ToDoService toDoService;
@RequestMapping("/todo")
public String list(Model model){
List<ToDoEntity> toDoEntityList = this.toDoService.getList();
model.addAttribute("toDoEntityList",toDoEntityList);
return "todolist";
}
@RequestMapping("/")
public String root(){
return "redirect:/todo";
}
}
좋은 글 감사합니다!