새 글 작성하기 (Create) 구현
1) 폼 데이터
폼 데이터는 HTML 요소인 <form> 태그에 담겨서 전송되는 데이터를 의미한다.
( 웹 브라우저 ----데이터-----> 서버 )
<form> 태그로 전송된 데이터는 서버의 컨트롤러가 객체에 담아서 받는다. (객체는 DTO )
그리고 DTO로 받은 데이터는 DB에 저장된다.
2) 폼 데이터를 DTO로 받기
[ new.mustache ]
{{>layouts/header}}
<form class="container" action="/articles/create" method="post">
<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}}
form 태그에 action 속성과 method 속성을 설정한다
action : 어디에 보낼지 정하는 것.
method : 어떻게 보낼지 정하는 것. ( get 또는 post )
[ new.mustache ]
<form class="container" action="/articles/create" method="post">
-> localhost:8080/articles/create 페이지로 폼 데이터를 보낸다는 의미이다.
[ ArticleController.java ]
@PostMapping("/articles/create")
public String createArticle() {
return "";
}
컨트롤러에 새로운 메서드를 추가해준다.
그 때 URL 요청은 GetMapping()을 사용하지 않고 @PostMapping()을 사용한다.
-> 뷰 페이지에서 폼 데이터를 post 방식으로 전송했기 때문!!
DTO 추가 [ ArticleForm.java ]
package com.example.firstproject.dto;
public class ArticleForm {
private String title; // 제목을 받을 필드
private String content; // 내용을 받을 필드
// 생성자 추가
public ArticleForm(String title, String content) {
this.title = title;
this.content = content;
}
// toString() 메서드 추가 ( 데이터를 잘 받았는지 확인 )
@Override
public String toString() {
return "ArticleForm{" +
"title='" + title + '\'' +
", content='" + content + '\'' +
'}';
}
}
컨트롤러에서는 createArticle() 메서드의 매개변수로 DTO 객체를 받아온다.
그리고 view의 <input> 태그에 name 속성을 DTO의 필드명과 일치시켜준다.
[ 결과 ]
폼에 입력하고 전송을 하면 콘솔에 찍히는 것을 확인할 수 있다.
요약
퀴즈 )
1. 다음 중 옳지 않은 것을 고르세요.
① <form> 태그의 action 속성에는 데이터를 전달할 URL 주소가 담긴다.
② <form> 태그의 method 속성에는 get만 사용할 수 있다.
③ @PostMapping 어노테이션은 post 방식으로 전달된 요청을 받아 컨트롤러의 메서드에 전달한다.
④ 폼 데이터를 자동으로 받으려면 입력 폼에서 <input>, <textarea> 태그의 name속성과 DTO 클래스의 필드명이 같아야 한다.
[ 답 ] 2번 -> post 도 사용 가능하다.
3) DTO를 데이터베이스에 저장하기
이제 앞에서 받아온 데이터를 DB에 저장하겠다.
사용 DB : H2 Database
JPA(Java Persistence API)란 ?
-> 자바 언어로 DB에 명령을 내리는 도구로, 데이터를 객체 지향적으로 관리할 수 있게 해준다.

JPA 핵심 도구 | |
엔티티 | 자바 객체를 DB가 이해할 수 있게 만들었다. 이것을 기반으로 테이블이 생성 |
리파지터리 | 엔티티가 DB 속 테이블에 저장 및 관리될 수 있게 하는 인터페이스이다. |
-> 현재 Article 클래스와 toEntity() 메서드가 없는 상태
- entity 패키지에 Article 클래스를 생성
[ Article.java ]
package com.example.firstproject.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
@Entity // 엔터티 선언 ( 이 어노테이션이 붙은 클래스를 기반으로 DB에 테이블이 생성 )
public class Article {
@Id // 엔터티의 대표값 지정
@GeneratedValue // 대표값 자동생성 ( 시퀀스 키? 숫자 자동으로 매겨짐...)
private Long id;
@Column // 필드 선언, DB 테이블의 title 열과 연결
private String title;
@Column // 필드 선언, DB 테이블의 content 열과 연결
private String content;
// 생성자
public Article(Long id, String title, String content) {
this.id = id;
this.title = title;
this.content = content;
}
// toString() 메서드 추가
@Override
public String toString() {
return "Article{" +
"id=" + id +
", title='" + title + '\'' +
", content='" + content + '\'' +
'}';
}
}
- toEntity() 메서드 생성하기
- ArticleForm.java에 생성한다.(DTO)
[ ArticleForm.java ]
public Article toEntity() {
return new Article(null, title, content); // 생성자 입력 양식에 맞게 작성..
// ArticleForm 객체에 id 정보가 없기 때문에. id는 null 이 들어간다.
}
}
리포지토리 생성하기 [ ArticleRepository.java ]
package com.example.firstproject.repository;
import com.example.firstproject.entity.Article;
import org.springframework.data.repository.CrudRepository;
/**
* CrudRepository 는 JPA에서 제공하는 인터페이스
* 상속받으면 엔터티를 관리 (생성, 조회, 수정, 삭제) 할 수 있다.
* <> 제네릭 요소...
* -> Article : 관리 대상 엔터티의 클래스 타입
* -> Long : 관리 대상 엔터티의 대표값 타입. id 가 대표값으로 지정되어있음.
*
* */
public interface ArticleRepository extends CrudRepository<Article, Long> {
}
1분 퀴즈)
( ㉠ )(이)란 JPA에서 제공하는 어노테이션으로, 이를 부여받은 클래스를 기반으로 DB 속 테이블이 생성됩니다.
=> ㄱ: Entity
( ㉡ )(이)란 JPA에서 제공하는 인터페이스로, 이를 상속해 엔티티를 관리(생성, 조회, 수정, 삭제)할 수 있습니다. 해당 인터페이스는 2개의 제네릭 요소를 받습니다. 하나는 관리할 대상 엔티티의 클래스 타입이고, 또 다른 하나는 그 엔티티의 대푯값 타입입니다.
=> ㄴ: CrudRepository<>
( ㉢ )은/는 스프링 부트에서 제공하는 어노테이션으로, 이를 컨트롤러의 필드에 부여할 수 있습니다. 해당 어노테이션은 스프링 부트가 만들어 놓은 객체를 가져와 주입해 줍니다.
=> ㄷ: Autowired
4) DB 데이터 조회하기
H2 Database 접속하기
먼저 서버를 실행시키고, http://localhost:8080/h2-console 로 접속한다.
그리고 run 에서 jdbc 를 검색하고.
메모리 주소를 복사해온다.
복사한 URL 은 JDBC URL 에 붙여넣고, Connect 버튼을 클릭하여 DB에 접속한다.
DB에 접속해서 Article 테이블을 조회 했더니, ID, CONTENT, TITLE 컬럼이 나왔다.
현재는 서버를 재시작했기 때문에 데이터가 날아갔다.
아까 만들어 둔 Form 페이지에서 데이터를 입력하고 다시 테이블을 존재했더니 데이터가 나왔다.
1분 퀴즈)
• ( ㉠ ): DB에서 데이터를 저장하는 틀
• ( ㉡ ): 테이블의 행(row)을 표현하는 또 다른 말
• ( ㉢ ): 데이터의 생성/조회/수정/삭제를 뜻하는 말
• ( ㉣ ): 테이블에 데이터를 생성하는 SQL 문
• ( ㉤ ): 테이블에 데이터를 조회하는 SQL 문
ㄱ: 테이블
ㄴ: 레코드
ㄷ: CRUD
ㄹ: select
ㅁ: insert
셀프체크) 회원가입 페이지 만들기
members 폴더에 [ new.mustache 파일 생성 ]
{{>layouts/header}}
<form class="container" action="/join" method="post">
<div class="mb-3">
<label class="form-label">이메일</label>
<input type="email" class="form-control" name="email"> <!-- name = "email" DTO의 email 필드와 연결-->
</div>
<div class="mb-3">
<label class="form-label">비밀번호</label>
<input type="password" class="form-control" name="password"></input> <!-- DTO의 password 필드와 연결 -->
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<a href="/members">Back</a>
</form>
{{>layouts/footer}}
[ MemberController.java ]
package com.example.firstproject.controller;
import com.example.firstproject.dto.MemberForm;
import com.example.firstproject.entity.Member;
import com.example.firstproject.repository.MemberRepository;
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 MemberController {
@Autowired
private MemberRepository memberRepository;
@GetMapping("/signup")
public String signUp() {
return "members/new";
}
@PostMapping("/join")
public String createMember(MemberForm form) {
System.out.println(form.toString());
Member member = form.toEntity();
Member saved = memberRepository.save(member);
return "";
}
}
DTO 생성 [ MemberForm.java ]
package com.example.firstproject.dto;
import com.example.firstproject.entity.Member;
public class MemberForm {
private String email;
private String password;
public MemberForm(String email, String password) {
this.email = email;
this.password = password;
}
@Override
public String toString() {
return "MemberForm{" +
"email='" + email + '\'' +
", password='" + password + '\'' +
'}';
}
public Member toEntity() {
return new Member(null, email, password);
}
}
Entity 생성 [ Member.java ]
package com.example.firstproject.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
@Entity
public class Member {
@Id
@GeneratedValue
Long id;
@Column
String email;
@Column
String password;
public Member(Long id, String email, String password) {
this.id = id;
this.email = email;
this.password = password;
}
@Override
public String toString() {
return "Member{" +
"id=" + id +
", email='" + email + '\'' +
", password='" + password + '\'' +
'}';
}
}
MemberRepository 생성. (이건 인터페이스로 생성해준다.)
[ MemberRepository.java ]
package com.example.firstproject.repository;
import com.example.firstproject.entity.Member;
import org.springframework.data.repository.CrudRepository;
public interface MemberRepository extends CrudRepository<Member, Long> {
}
'스터디 > back' 카테고리의 다른 글
12장 ~ 14장 (0) | 2023.12.21 |
---|---|
Part 3) REST API와 JSON | HTTP와 REST 컨트롤러 (0) | 2023.12.14 |
Part 2) 게시판 만들기 (3) - 리다이렉트 / update / delete / SQL 쿼리 (1) | 2023.12.07 |
Part 2) 게시판 만들기(2) (1) | 2023.11.23 |
Part1 ) 스프링 부트 개요 (0) | 2023.11.15 |