스터디/back

Part 2) 게시판 만들기(1)

ㅈㅣ니 2023. 11. 21.
반응형

새 글 작성하기 (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 역할

 

JPA 핵심 도구
엔티티 자바 객체를 DB가 이해할 수 있게 만들었다. 이것을 기반으로 테이블이 생성
리파지터리 엔티티가 DB 속 테이블에 저장 및 관리될 수 있게 하는 인터페이스이다.

 

ArticleController.java

-> 현재 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 페이지에서 데이터를 입력하고 다시 테이블을 존재했더니 데이터가 나왔다.

ARTICLE 테이블

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> {
}

DB에 회원 정보가 잘 들어간다.

반응형