Spring

[Spring] 스프링 부트 게시판 만들기 (1)

dalooong 2023. 8. 1. 01:17
코딩 자율학습 - 스프링부트3 자바 백엔드 개발 책을 기반으로 작성하였습니다.
 뷰 템플릿 
웹 페이지를 하나의 틀로 만들고 여기에 변수를 삽입해 서로 다른 페이지로 보여 주는 기술입니다. 

 MVC 패턴 
웹 페이지를 화면에 보여 주고(view), 클라이언트의 요청을 받아 처리하고 (controller), 데이터를 관리하는(Model) 역할을 영역별로 나누어 하는 기법을 말합니다. 

3장) 게시판 만들고 새 글 작성하기 : Create

1️⃣ 폼 데이터를 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" name="title">
    </div>
    <div class="mb-3">
        <label class="form-label">내용</label>
        <textarea class="form-control" rows="3" name="content"></textarea>
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
</form>
{{>layouts/footer}}

2️⃣ 컨트롤러 만들기 

앞에서 작성한 페이지를 웹 브라우저에서 보기 위해 컨트롤러 생성 

ArticleController 생성

@Controller
public class ArticleController {
    @Autowired
    private ArticleRepository articleRepository;

    @GetMapping("/articles/new")
    public String newArticleForm(){
        return "articles/new";
    }

    //create
    @PostMapping("/articles/create")
    public String createArticles(ArticleForm form){
        System.out.println(form.toString());
        // 1. DTO를 엔티티로 변환
        Article article = form.toEntity();
        // DTO가 엔티티로 잘 반환되는지 확인 출력
        System.out.println(article.toString());
        // 2. Repository로 엔티티를 DB에 저장
        Article saved = articleRepository.save(article);
        // article이 DB에 잘 저장되는지 확인 출력
        System.out.println(saved.toString());
        return "";
    }
}

3️⃣ DTO 만들기 

컨트롤러에서 폼 데이터를 받을 때 필요한 DTO 생성

ArticleForm 클래스 생성 

public class ArticleForm {
    private String title; // 제목을 받을 필드
    private String content; // 내용을 받을 필드

    // 전송받은 제목과 내용을 필드에 저장하는 생성자 추가
    public ArticleForm(String title, String content) {
        this.title = title;
        this.content = content;
    }

    @Override
    public String toString() {
        return "ArticleForm{" +
                "title='" + title + '\'' +
                ", content='" + content + '\'' +
                '}';
    }

    public Article toEntity() {
        return new Article(null, title, content);
    }
}
✅ Entity
자바 객체를 DB가 이해할 수 있게 만든 것으로, 이를 기반으로 테이블이 만들어진다. 
 Repository 
Entity가 DB 속 테이블에 저장 및 관리 될 수 있게 하는 인터페이스 

4️⃣ DTO를 엔티티로 변환하기 

Article 클래스 만들기 

@Entity
public class Article {
    @Id
    @GeneratedValue
    private Long id;
    @Column
    private String title;
    @Column
    private String content;
    // 생성자 추가

    // Article 생성자 추가
    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 + '\''+
                '}';
    }
}

5️⃣ ArticleRepository 생성 

public interface ArticleRepository extends CrudRepository<Article, Long> {
}

6️⃣ 실행 

  • http://localhost:8080/articles/new 접속

  • 출력 결과
ArticleForm{title='가가가가', content='1111'}
Article{id=null, title='가가가가', content ='1111'}
Article{id=1, title='가가가가', content ='1111'}

 

7️⃣ 정리

  • DTO : 폼 데이터에 실어 보낸 데이터는 서버의 컨트롤러가 객체에 담아 받는데, 이 객체를 DTO라고 합니다. DTO로 받은 데이터는 최종적으로 데이터베이스에 저장됩니다. 
  • JPA : 자바 언어로 DB에 명령을 내리게 하는 도구로, 데이터를 객체 지향적으로 관리하도록 도와줍니다. JPA의 핵심 도구로는 Entity와 Repository가 있습니다.
  • 의존성 주입 : 외부에서 만들어진 객체를 필요한 곳으로 가져오는 기법읠 의존성 주입 DI라고 합니다. 스프링 부트는 @Autowired 어노테이션으로 의존성 주입을 할 수 있습니다. 

 

4장) 롬복과 리팩터링

앞에서 폼 데이터를 DB에 저장했습니다. 폼 데이터를 DTO로 받아 엔티티로 변환한 후 Repository를 이용해 DB에 저장하는 과정을 했습니다. 

✅ 롬복이란? 
코드를 간소화해 주는 라이브러리입니다. 롬복을 사용하면 필수 코드를 간편하게 작성할 수 있습니다. 
또, 로깅 기능을 통해 println()문을 개선할 수 있습니다.
 로깅이란?
프로그램의 수행 과정을 기록으로 남기는 것을 말하는데, 일종의 자동차 블랙박스와 같습니다. 
 리팩터링이란?
코드의 기능에는 변함이 없이 코드의 구조 또는 성능을 개선하는 작업을 말합니다

1️⃣ DTO 리팩터링 하기 

@AllArgsConstructor
@ToString
public class ArticleForm {
    private String title; // 제목을 받을 필드
    private String content; // 내용을 받을 필드


    public Article toEntity() {
        return new Article(null, title, content);
    }
}

2️⃣ Article Entity 리팩토링하기 

@AllArgsConstructor
@ToString
@Entity
public class Article {
    @Id
    @GeneratedValue
    private Long id;
    @Column
    private String title;
    @Column
    private String content;
}

3️⃣ 컨트롤러에 로그 남기기

@Controller
@Slf4j
public class ArticleController {
    @Autowired
    private ArticleRepository articleRepository;

    @GetMapping("/articles/new")
    public String newArticleForm(){
        return "articles/new";
    }

    //create
    @PostMapping("/articles/create")
    public String createArticles(ArticleForm form){
        // 1. DTO를 엔티티로 변환
        Article article = form.toEntity();
        log.info(form.toString());
        
        // 2. Repository로 엔티티를 DB에 저장
        Article saved = articleRepository.save(article);
        // 로깅 코드 추가
        log.info(form.toString());
        
        return "";
    }
}

4️⃣ 정리

  • 롬복 : 코드를 간소화해주는 라이브러리
  • 로깅 : 프로그램의 수행 과정을 기록으로 남기는 것
  • 리팩터링 : 코드의 기능에는 변함이 없이 코드의 구조 또는 성능을 개선하는 작업, 코드의 가독성이 좋아지고 길이가 짧아져 개발시간이 단축된다는 장점이 있다. 
  • @AllArgsConstructor : 클래스 안쪽의 모든 필드를 매개변수로 하는 생성자를 만드는 어노테이션, 클래스 내에 별도의 생성자를 만들지 않아도 된다는 장점이 있다.
  • @ToString : toString() 메서드를 사용한 것과 똑같은 효과를 낸다. 별도의 toString() 메서드를 사용하지 않아도 된다.
  • @Slf4j : 로깅할 때 사용하며, 로그를 찍으면 나중에라도 그동안 찍힌 로그를 찾아 볼 수 있다. log.info()문으로 사용한다. 

5장) 게시글 읽기 : Read

단일데이터 조회하기 

1️⃣ ArticleController에 articles/id로 조회했을 때 이를 받아줄 컨트롤러 추가 

    @GetMapping("/articles/{id}")
    public String show (@PathVariable Long id, Model model){ // 매개변수로 id 받아오기
        log.info("id = " + id); // id를 잘 받아오는지 확인하는 로그 생성
        // 1. id를 조회해 데이터 가져오기
        Article articleEntity = articleRepository.findById(id).orElse(null);
        // 2. 모델에 데이터 등록하기
        model.addAttribute("article", articleEntity);
        // 3. 뷰 페이지 설정하기
        return "articles/show";
    }

2️⃣ show.mustache 파일 생성

{{>layouts/header}}
<table class="table">
    <thead>
    <tr>
        <th scope="col">Id</th>
        <th scope="col">Title</th>
        <th scope="col">Content</th>
    </tr>
    </thead>
    <tbody>
    {{#article}}
    <tr>
        <th>{{id}}</th>
        <td>{{title}}</td>
        <td>{{content}}</td>
    </tr>
    {{/article}}
    </tbody>
</table>
{{>layouts/footer}}

3️⃣ Article 클래스 수정

@AllArgsConstructor
@NoArgsConstructor // 기본생성자 추가 어노테이션
@ToString
@Entity
public class Article {
    @Id
    @GeneratedValue
    private Long id;
    @Column
    private String title;
    @Column
    private String content;
}

4️⃣ 실행

http://localhost:8080/articles/new
http://localhost:8080/articles/1

데이터 목록 조회하기 

    @GetMapping("/articles")
    public String index(){
        // 1. 모든 데이터 가져오기
        List<Article> articleEntityList = articleRepository.findAll();
        // 2. 모델에 데이터 등록하기
        // 3. 뷰 페이지 설정하기
        return "";
    }

 

public interface ArticleRepository extends CrudRepository<Article, Long> {
    @Override
    ArrayList<Article> findAll(); // Iterable -> ArrayList로 형변환
}