[Spring Boot] TO-DO List 만들기 - 첫 셋팅 편

aylee·2022년 6월 21일
5

SpringBoot-ToDoList

목록 보기
1/4
post-thumbnail

🌱 포스트 순서 🌱

  1. 계획
  2. 환경 설정
  3. 아이템 등록하기

https://wikidocs.net/book/7601 의 내용을 응용하였습니다.


[1] 계획

🌱 아이템 확인하기 (본 포스트)
🌱 아이템 등록하기
🌱 아이템 삭제하기
🌱 아이템 수정하기

[2] 환경 설정

(1) spring initializr

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로 들어가보면

입력한대로 잘 나온다.

설정이 잘 된 것 같으니, 이젠 진짜 처음에 계획한 걸 만들어보자.

[3] 아이템 등록하기

(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";
    }
}
profile
미래를 구체화 하는 중

1개의 댓글

comment-user-thumbnail
2022년 11월 22일

좋은 글 감사합니다!

답글 달기