3일차 - 게시판 CRUD 만들기 (새 글 작성하기)
폼 데이터란
HTML 요소인 <form> 태그에 실려 전송되는 데이터를 말한다. form 을 통해 전송 버튼을 누르면 웹 브라우저에서 서버로 데이터를 전송하게 된다.
form 을 통해 보낸 데이터는 서버의 컨트롤러가 DTO(Data Transfer Object) 에 저장한다. DTO 로 받은 데이터는 최종적으로 데이터베이스에 저장된다.
폼 데이터를 DTO로 받기
입력 폼 만들기
src/main/resources/templates/articles 경로에 new.mustache 파일을 만들어 간단한 form 페이지를 만들어준다.
{{>layouts/header}}
<form class="container">
<div class="mb-3">
<label class="form-label">제목</label>
<input type="text" class="form-control">
</div>
<div class="mb-3">
<label class="form-label">내용</label>
<textarea class="form-control" rows="3"></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
{{>layouts/footer}}
컨트롤러 만들기
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class ArticleController {
@GetMapping("/articles/new")
public String newArticleForm() {
return "articles/new";
}
}
- 컨트롤러임을 선언한다.
- /articles/new 주소로 GET 요청을 받는 newArticleForm() 메서드를 작성한다.
- 뷰 페이지를 반환한다.
폼 데이터 전송하기
<form> 태그에 데이터를 어디로, 어떻게 보낼지에 관한 정보를 설정해주어야 한다.
- action : form 데이터를 보낼 URL 연결 주소를 적는다
- method : get, post 2가지 방식 중 하나를 선택한다.
<form class="container" action="/articles/create" method="post">
폼 데이터 받기
@PostMapping("/articles/create")
public String createArticle() {
return "";
}
간단하게 form 데이터를 받을 URL 연결 주소를 매핑하는 메서드를 작성한다.
DTO 만들기
컨트롤러에서 form 데이터를 받을 때 DTO 에 담아 받기 위해 객체를 생성한다. title, content 필드를 선언하여 작성한다.
데이터를 잘 받았는지 확인하기 위해 toString() 메서드도 추가한다.
폼 데이터를 DTO에 담기
- 폼에서 전송한 데이터를 컨트롤러의 createArticle() 메서드의 매개변수로 받는다.
- 폼에서 전송한 데이터가 DTO 에 잘 담겼는지 form.toString() 메서드를 호출해 확인한다.
입력 폼과 DTO 필드 연결하기
입력 폼에서 전송한 데이터를 DTO의 필드 title, content 에 값이 들어가려면 폼에 필드명을 지정해줘야 한다.
제목을 입력하는 <input> 과 내용을 입력하는 <textarea>에 name 속성을 이용하여 DTO 의 필드명과 동일한 이름을 지정해준다.
DTO를 데이터베이스에 저장하기
데이터베이스와 JPA
DB는 SQL 언어를 사용하기 때문에 자바를 이해하지 못한다. 자바 언어로 DB에 명령을 내리는 도구로, 데이터를 객체 지향적으로 관리할 수 있게 해주는 JPA를 사용한다.
JPA의 핵심 도구로는 entity와 repository가 있다.
- entity
- 자바 객체를 DB가 이해할 수 있게 만든 것으로, 이를 기반으로 테이블이 만들어진다.
- repository
- entity가 DB 속 테이블에 저장 및 관리될 수 있게 하는 인터페이스이다.
DTO를 엔티티로 변환하기
DTO를 엔티티로 변환하기 위해 form 객체의 toEntity() 메서드를 호출해서 반환값을 Article 엔티티에 저장한다.
- Entity 클래스 Article 생성하기
- Article 클래스는 기본패키지/entity 경로에 생성한다.
- 엔티티 설정
- @Entity 를 Article 클래스에 붙여 이 클래스 기반으로 DB에 테이블이 생성된다.
- 필드 설정
- DTO 필드와 같이 title, content 를 선언하여 DB에서 인식할 수 있게 @Column 을 붙인다.
- 엔티티에는 대표값이 있어야한다. id 필드를 선언하고 @Id , @GeneratedValue 을 붙인다. @Id 는 엔티티의 대표값을 지정하고, @GeneratedValue 는 id 값을 자동 생성해준다.
- 객체 생성 및 초기화
- All Args 생성자 생성
- No Args 생성자 생성
- toString() 추가
- toEntity() 추가하기
- ArticleForm 에 toEntity() 메소드를 생성한다
- public Article toEntity() { return new Article(null, title, content); }
- toEntity()
- 폼 데이터를 담은 DTO 객체를 Article 엔티티로 반환한다.
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
@Entity public class Article {
@Id @GeneratedValue private Long id;
@Column
private String title;
@Column
private String content;
public Article() { }
public Article(Long id, String title, String content) {
this.id = id;
this.title = title;
this.content = content;
}
@Override public String toString() {
return "Article{" + "id=" + id + ",
title='" + title + '\\'' + ",
content='" + content + '\\'' + '}';
}
}
repository로 entity를 DB에 저장하기
- repository 만들기
- 기본패키지/repository 경로에 ArticleRepository 인터페이스를 생성한다.
- CrudRepository<T, ID> 를 상속받아 사용한다.
- T : 관리 대상 엔티티의 클래스 타입이다.
- ID : 관리 대상 엔티티의 대표값 타입이다.
- 객체 주입
- @Autowired 어노테이션을 사용하여 컨트롤러의 필드에 붙이면 스프링 부트가 만들어 놓은 객체를 가져와 주입해주는데, 이것을 의존성 주입(DI; Dependency Injection)이라고 한다.
- controller 에서 repository 를 사용하기 위해 선언할 때 구현체를 만들지 않아도 @Autowired 를 사용하면 된다.
import com.example.firstproject.dto.ArticleForm; import com.example.firstproject.entity.Article; import com.example.firstproject.repository.ArticleRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; @Controller public class ArticleController { @Autowired private ArticleRepository articleRepository; @GetMapping("/articles/new") public String newArticleForm() { return "articles/new"; } @PostMapping("/articles/create") public String createArticle(ArticleForm form) { System.out.println(form.toString()); // 1. DTO를 엔티티로 변환 Article article = form.toEntity(); // 2. 리포지토리로 엔티티를 DB에 저장 Article saved = articleRepository.save(article); return ""; } }
- 데이터 저장 확인하기
- localhost:8080/articles/new 에서 제목과 내용을 입력하여 전달하면 form 의 action 에 의해 localhost:8080/article/create 로 데이터가 전달된다.
@PostMapping("/articles/create") public String createArticle(ArticleForm form) { System.out.println("form 에서 전달된 데이터 : " + form.toString()); // 1. DTO를 엔티티로 변환 Article article = form.toEntity(); System.out.println("DTO를 엔티티로 변환 : " + article.toString()); // 2. 리포지토리로 엔티티를 DB에 저장 Article saved = articleRepository.save(article); System.out.println("엔티티 DB 저장 : " + saved.toString()); return ""; }
- form 에서 전달받은 데이터는 DTO인 ArticleForm 에 저장되었다.
- DTO에서 엔티티로 변환된 데이터는 Article 엔티티에 id 값 없이 저장되었다.
- Article 엔티티가 DB에 저장될 때 id는 자동으로 생성되어 1이 출력되었다.
DB 데이터 조회하기
H2 DB 접속하기
- application.properties 에 spring.h2.console.enabled=true 를 작성한다. H2 DB에 웹 콘솔로 접근할 수 있도록 허용하는 설정이다.
- localhost:8080/h2-console 페이지에 접속하면, H2 console 페이지가 나온다.
- 인텔리제이의 console에 보면 H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:...’ 을 확인할 수 있다. 이는 JDBC H2 DB가 해당 주소 메모리에서 동작한다는 의미이다.