👣롬복!
롬복은 코드를 간소화해주는 라이브러리입니다. 개발하다보면 자주사용하는 getter, setter, constructor, toString같은 필수 메서드를 반복하지 않게 자동으로 만들어주는 라이브러리입니다.
또 로깅(logging)으로 프로그램의 수행과정을 기록으로 남길 수 있습니다.
실습💦
1. build.gradle을 다음과 같이 작성합니다.
plugins {
id 'java'
id 'org.springframework.boot' version '3.4.2'
id 'io.spring.dependency-management' version '1.1.7'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
repositories {
mavenCentral()
}
dependencies {
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-mustache'
implementation 'org.springframework.boot:spring-boot-starter-web'
runtimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}
오른쪽 위에 나타나는 버튼을 눌러(코끼리 버튼) 롬복 플러그인을 활성화합니다.

그다음 IDE에서 Lombok 플러그인을 설치하고, **"Enable Annotation Processing"**을 활성화해줍니다.

2. DTO수정
ArticleForm이라는 DTO를 수정하겠습니다.
package com.example.demo.dto;
import com.example.demo.entity.Article;
import lombok.AllArgsConstructor;
import lombok.ToString;
@AllArgsConstructor
@ToString
public class ArticleForm {
private String title;
private String content;
public Article toEntity() {
return new Article(null, title, content);
}
}
@AllArgsConstructor로 title과 content를 매개변수로 하는 생성자를 , @ToString으로 toString메서드를 만들 수 있습니다.
http://localhost:8080/articles/new에서 잘되는 지 확인합니다.

3. Entity refactoring
default 생성자가 없다는 오류가 나기는 하지만 서버를 실행하는 데는 문제가 없습니다.
package com.example.demo.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.ToString;
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Entity
public class Article {
@Id
@GeneratedValue
private Long id;
@Column
private String title;
@Column
private String content;
}
4. Controller에 로그남기기 logging
println문으로 확인하고 싶은 데이터를 확인하면 기록에 남지 않을 뿐더러 서버의 성능에도 악영향을 끼칩니다.
package com.example.demo.controller;
import com.example.demo.dto.ArticleForm;
import com.example.demo.entity.Article;
import com.example.demo.repository.ArticleRepository;
import lombok.extern.slf4j.Slf4j;
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;
@Slf4j
@Controller
public class ArticleController {
@Autowired
private ArticleRepository articleRepository;
@GetMapping("/articles/new")
public String newArticleForm() {
return "articles/new";
}
@PostMapping("/articles/new")
public String createArticle(ArticleForm form){
log.info(form.toString());
//1. DTO를 엔티티로 변환
Article article = form.toEntity();
//2. 리포지터리로 엔티티를 DB에 저장
Article saved = articleRepository.save(article);
log.info(article.toString());
log.info(saved.toString());
return "";
}
}


🤚지난시간 간단 요약)
뷰는 URL로 요청을 보내고 Controller는 URL요청을 받아 DTO를 통해 게시글을 생성할 수 있습니다.
DTO는 controller에서 entity로 변환되고 controller에서 리포지터리로 엔티티를 DB에 저장합니다.
🐔5단원. READ : 게시글 읽기
DB에 저장된 데이터를 조회해 웹 페이지에 출력하는 법을 알아봅시다.
사용자가 데이터를 조회해 달라고 웹 페이지에 URL 요청을 보내면 서버의 controller가 요청을 받아(DTO) 해당 URL이 요청하는 정보가 어떤 것인지(Entity) repository에 전달합니다. repository는 해당 정보로 DB에 데이터 조회를 요청하고 DB는 해당 데이터를 찾아 entity로 반환합니다. 반환된 entity는 모델을 통해 뷰 템플릿으로 전달돕니다.
http://localhost:8080/articles/{id}이런 식으로 게시글 하나의 id당 url조회를 할 수 있도록 실습해봅시다.
실습💦
1. URL요청을 받아줄 Controller 만들기
1) 반환형이 Article이 아닌 문제 해결1
Optional<Article> articleEntity = articleRepository.findById(id);
Optional<T>는 null을 안전하게 처리하기 위한 Java 8의 기능입니다.
위 코드에서 findById(id)의 반환 타입이 Optional<Article>인 이유는, id에 해당하는 Article이 없을 수도 있기 때문입니다.
2) 반환형이 Article이 아닌 문제 해결2
id값으로 데이터를 찾을 때 해당 데이터값이 없으면 null을 반환하는 메서드입니다.
Article articleEntity = articleRepository.findById(id).orElse(null);
orElse()는 Optional 객체에 값이 존재하면 그 값을 반환하고, 값이 없으면 지정한 기본값을 반환하는 메서드입니다.
2. 모델에 데이터 등록하기 &뷰에 반환
Spring MVC에서 Model은 컨트롤러에서 뷰(View)로 데이터를 전달하는 객체입니다.
즉, 컨트롤러에서 데이터를 가공한 후 뷰에서 사용할 수 있도록 저장하는 역할을 합니다.
Spring에서는 Model 객체를 자동으로 생성하고 컨트롤러 메서드의 파라미터로 넘겨줍니다.따라서 Model model을 메서드의 매개변수로 선언하기만 하면, Spring이 자동으로 주입해줍니다.
ArticleController
@GetMapping("/articles/{id}")
public String show(@PathVariable Long id, Model model){
log.info("id= " + id);
// 1. id를 조회해 데이터 가져오기
Article articleEntity = articleRepository.findById(id).orElse(null);
// 2. 모델에 데이터 등록하기
model.addAttribute("article", articleEntity);
// 3. 뷰 페이지 반환하기
return "articles/show";
}
addAttribute는 모델의 이름을 등록하는 것입니다. 모델은 뷰에 전달할 객체를 말합니다.
3. mustache(뷰)에서 article 모델 가져오기
model.addAttribute("article", articleEntity);
앞서 이렇게 articleEntity를 article이라는 이름의 모델로 등록했습니다.
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}}
이제 articles/new에 값을 넣을 때마다 1,2,3,... 순서로 id에 저장되고 그것을 article/{id}에서 확인할 수 있습니다.

위 실습에서 DB에서 데이터(entity꼴)를 가져오고, 모델( 뷰에 전달할 객체 )로 뷰에 전달하는 법을 배웠습니다.
이제 다음 실습에서 단일 데이터가 아닌 데이터 목록을 조회하는 법을 알아보겠습니다.
실습💦💦
ArticleController
@GetMapping("/articles")
public String index(Model model){
//1. 모든 데이터 가져오기
List<Article> articleEntityList = articleRepository.findAll();
//2. 모델에 데이터 등록하기
model.addAttribute("articleList", articleEntityList);
//3. 뷰 설정하기
return "articles/index";
}
1. 모든 데이터를 가져오기 위해서 레포지터리를 이용해 findAll메소드를 사용합니다.
보면 List 데이터를 articleEntityList가 받아야 하는데 findAll메소드 가 Iterable 값을 반환하는 문제가 있다고 합니다.
type casting을 사용해 해결합시다.
1) Iterable값을 List로 downcasting
List<Article> articleEntityList = (List<Article>)articleRepository.findAll();
2) List값을 Iterable로 upcasting
Iterable<Article> articleEntityList = articleRepository.findAll();
3) 많이 사용되는 ArrayList쓰기
이 방법을 사용하려면 CrudRepository의 메서드를 오버라이딩해야 합니다.
ArticleRepository
package com.example.demo.repository;
import com.example.demo.entity.Article;
import org.springframework.data.repository.CrudRepository;
import java.util.ArrayList;
public interface ArticleRepository extends CrudRepository<Article, Long> {
//save 저장하기
//findId id값으로 찾기 기능을 제공한다.
@Override
ArrayList<Article> findAll(); //Iterable->ArrayList
}
우리는 세번째 방법을 이용할 것입니다.
2. index.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>
{{#articleList}}
<tr>
<th>{{id}}</th>
<td><a href="/articles/{{id}}">{{title}}</a></td>
<td>{{content}}</td>
</tr>
{{/articleList}}
</tbody>
</table>
<a href="/articles/new">New Article</a>
{{>layouts/footer}}
머스테치 변수가 데이터 묶음일 경우에는 그 안쪽의 코드를 반복 실행한다고 합니다.

'대외활동 > DRACONIST-백엔드' 카테고리의 다른 글
스스로 공부하는 스프링부트. 10단원 REST API~12단원 (1) | 2025.02.14 |
---|---|
스스로 공부하는 스프링부트. 6,7,8,9단원 CRUD완성 (0) | 2025.02.13 |
스스로 공부하는 스프링부트. 3단원 CREATE (0) | 2025.02.11 |
스스로 공부하는 스프링부트 2.4 mustache 사용하기 (0) | 2025.02.10 |
스프링부트 스터디 4주차. 8단원 EC2서버에 프로젝트 배포하기 (0) | 2025.02.03 |