2024. 5. 6. 01:14ㆍFull Stack Course 풀스택과정/SPRING
배울내용:
Springboot 비동기식 게시판
Springboot 비동기식 방명록 만들기
Springboot 방명록만들기
스프링 부트 방명록 만들기
스프링 부트 비동기식
먼저 동기와 비동기의 차이는 아래와 같다
- 동기식(Synchronous) 방명록
- 사용자 요청을 처리하는 동안 다른 요청을 처리하지 않고 대기합니다. 이는 요청을 순차적으로 처리한다는 의미입니다.
- 한 요청이 처리되는 동안 다른 요청이 대기하기 때문에 동시에 많은 요청을 처리하기 어려울 수 있습니다.
- 대부분의 경우 작업이 순차적으로 실행되기 때문에 코드가 간단하고 예측하기 쉽습니다.
- 비동기식(Asynchronous) 방명록
- 사용자 요청을 처리하는 동안 다른 요청을 처리할 수 있습니다. 이는 요청을 동시에 처리할 수 있다는 의미입니다.
- 비동기식 방식은 요청을 받으면 해당 요청을 처리하는 동안 다른 작업을 처리할 수 있어서 시스템의 확장성과 성능을 향상시킬 수 있습니다.
- 비동기식 코드는 일반적으로 콜백 함수나 Future, CompletableFuture 등을 사용하여 작성됩니다. 이는 작업이 완료되면 특정 동작을 실행하는 방식으로 동작합니다
스프링 부트에서 비동기식 방명록을 만들려면
@Async 어노테이션을 사용하여 비동기적으로 실행될 메서드를 지정하고,
@EnableAsync 어노테이션을 구성 클래스에 추가하여 비동기 기능을 활성화해야 합니다.
이를 통해 비동기식으로 작업을 처리할 수 있고, 동시에 다른 요청도 처리할 수 있습니다.
먼저 DB는 MYSQL 을 사용할것이다
SpringBoot 에서 Gradle로 만든뒤에
build.gradle을 아래처럼 만들어준다
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.5'
id 'io.spring.dependency-management' version '1.1.4'
}
group = 'com.codehows'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
runtimeOnly 'com.h2database:h2'
}
tasks.named('test') {
useJUnitPlatform()
}
프로젝트이름/main/resource/application.properties 를 아래와 같이 만들고
mysql workbench 를 이용해 ID 와 PW 를 확인후 "나의 MYSQL ID, PW 위치에 넣어준다"
application.properties
spring.application.name=portfolio
server.port=8080
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/portfolio
spring.datasource.username=나의 Mysql ID 넣기
spring.datasource.password=나의 MYsql PW 넣기
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.type.descriptor.sql=trace
spring.jpa.hibernate.ddl-auto=create
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
그다음에 방명록에 남길 "이름" 과 "내용" 을 넣을 Entity를 만들어준다
entity 패키지를 만든후 Guestbook.java 를 만들어준다
Guestbook
package com.codehows.portfolio.entity;
import jakarta.persistence.*;
import lombok.*;
@Entity
@Table(name="guestbook")
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Guestbook {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String guestName;
@Column(nullable = false)
private String guestContent;
@Builder
public Guestbook(String guestName, String guestContent) {
this.guestName = guestName;
this.guestContent = guestContent;
}
}
위의 코드는 스프링 부트에서 JPA(Java Persistence API)를 사용하여 방명록(Guestbook)을 위한 엔티티 클래스를 정의한 것입니다. 각 부분을 설명해보겠습니다.
- @Entity
- 이 어노테이션은 JPA 엔티티 클래스를 나타내는데 사용됩니다. 데이터베이스의 테이블과 매핑됩니다.
- @Table(name="guestbook")
- 이 어노테이션은 해당 엔티티가 매핑되는 데이터베이스 테이블의 이름을 지정합니다. 여기서는 "guestbook"이라는 테이블에 매핑됩니다.
- @Getter, @Setter
- Lombok 어노테이션인 @Getter와 @Setter는 해당 클래스의 필드에 대한 Getter와 Setter 메서드를 자동으로 생성해줍니다. 이를 통해 필드에 접근하고 수정하는 메서드를 별도로 작성할 필요가 없습니다.
- @NoArgsConstructor(access = AccessLevel.PROTECTED)
- 이 어노테이션은 매개변수가 없는 기본 생성자를 생성하며, AccessLevel.PROTECTED를 설정하여 외부에서 생성자에 접근하지 못하도록 제한합니다. 주로 JPA에서 엔티티를 생성할 때 사용됩니다.
- @Id, @GeneratedValue(strategy = GenerationType.IDENTITY)
- @Id는 해당 필드가 엔티티의 식별자(primary key)임을 나타내며, @GeneratedValue는 식별자의 값을 자동으로 생성하는 전략을 설정합니다. 여기서는 데이터베이스의 자동 증가(AUTO_INCREMENT) 기능을 사용하는 방식을 선택했습니다.
- @Column(nullable = false)
- 이 어노테이션은 해당 필드가 데이터베이스 컬럼에 매핑될 때의 속성을 지정합니다. 여기서는 nullable = false를 사용하여 해당 필드는 NULL 값이 허용되지 않음을 나타냅니다.
- @Builder
- Lombok의 @Builder 어노테이션은 빌더 패턴을 자동으로 생성해줍니다. 생성자 대신에 빌더를 통해 객체를 생성할 수 있게 해줍니다. 이를 통해 객체 생성 시에 편리하게 초기화할 수 있습니다.
이렇게 정의된 Guestbook 엔티티 클래스는 데이터베이스의 guestbook 테이블과 매핑되며, 해당 테이블에는 id, guestName, guestContent라는 세 개의 컬럼이 존재하게 됩니다. 이 클래스를 사용하여 방명록 데이터를 저장하고 조회할 수 있습니다.
그리고 dto 패키지를 만든후 GuestbookResponse.java 파일을 만들고 아래처럼 넣어준다.
GuestbookResponse
package com.codehows.portfolio.dto;
import com.codehows.portfolio.entity.Guestbook;
import lombok.Getter;
@Getter
public class GuestbookResponse {
private final Long id;
private final String guestName;
private final String guestContent;
public GuestbookResponse(Guestbook guestbook) {
this.id = guestbook.getId();
this.guestName = guestbook.getGuestName();
this.guestContent = guestbook.getGuestContent();
}
}
위의 코드는 DTO(Data Transfer Object) 패턴을 사용하여 방명록(Guestbook) 엔티티의 정보를 전달하는 클래스를 정의한 것입니다.
GuestbookResponse 클래스는 Guestbook 엔티티의 정보 중에서 필요한 부분만을 선택하여 전달하는 역할을 합니다. 이는 클라이언트에게 필요한 정보만을 전달함으로써 데이터의 불필요한 노출을 줄이고, 데이터 전송의 효율성을 높이는 데 도움이 됩니다. 이런 식으로 DTO를 사용하면 데이터 전송 과정에서 발생할 수 있는 불필요한 오버헤드를 최소화할 수 있습니다.
그리고 repository 패키지를 만든후 GuestbookRepository.java 파일을 만들고 아래처럼 넣어준다.
GuestbookRepository
package com.codehows.portfolio.repository;
import com.codehows.portfolio.entity.Guestbook;
import org.springframework.data.jpa.repository.JpaRepository;
public interface GuestbookRepository extends JpaRepository<Guestbook, Long> {
}
GuestbookRepository를 사용하면 별도의 SQL 쿼리를 작성하지 않고도 Guestbook 엔티티에 대한 데이터 액세스를 간편하게 수행할 수 있습니다. JpaRepository가 제공하는 기능(CRUD) 들을 활용하여 데이터베이스와의 상호작용을 쉽게 처리할 수 있습니다.
그리고 service 패키지를 만든후 GuestbookRepository.java 파일을 만들고 아래처럼 넣어준다.
GuestbookRepository
package com.codehows.portfolio.service;
import com.codehows.portfolio.dto.AddGuestbookRequest;
import com.codehows.portfolio.entity.Guestbook;
import com.codehows.portfolio.repository.GuestbookRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
@RequiredArgsConstructor
@Service
public class GuestbookService {
private final GuestbookRepository guestbookRepository;
public List<Guestbook> findAll() {
return guestbookRepository.findAll();
}
}
- private final GuestbookRepository guestbookRepository;
- GuestbookRepository 인스턴스를 필드로 선언합니다. @RequiredArgsConstructor 어노테이션에 의해 생성자 주입을 받습니다.
- public List<Guestbook> findAll() { ... }
- 모든 방명록 데이터를 조회하는 메서드입니다. GuestbookRepository의 findAll() 메서드를 호출하여 모든 방명록 데이터를 리스트로 반환합니다.
이 코드에서 GuestbookService 클래스는 GuestbookRepository를 사용하여 데이터베이스와의 상호작용을 처리합니다. 현재는 모든 방명록 데이터를 조회하는 메서드만 구현되어 있지만, 필요에 따라 추가적인 비즈니스 로직을 구현할 수 있습니다. 예를 들어, 방명록을 추가하는 메서드나 삭제하는 메서드 등을 추가할 수 있습니다. 이렇게 서비스 클래스를 사용하면 컨트롤러에서 비즈니스 로직을 분리하여 코드의 유지보수성과 재사용성을 높일 수 있습니다.
그리고 controller 패키지를 만든후 GuestbookController.java 파일을 만들고 아래처럼 넣어준다.
GuestbookController
package com.codehows.portfolio.controller;
import com.codehows.portfolio.dto.AddGuestbookRequest;
import com.codehows.portfolio.dto.GuestbookResponse;
import com.codehows.portfolio.entity.Guestbook;
import com.codehows.portfolio.service.GuestbookService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RequiredArgsConstructor
@RestController
public class GuestbookController {
private final GuestbookService guestbookService;
@GetMapping("/api/guestbooks")
public ResponseEntity<List<GuestbookResponse>> findAllGuestbooks() {
List<GuestbookResponse> guestbooks = guestbookService.findAll()
.stream()
.map(GuestbookResponse::new)
.toList();
return ResponseEntity.ok()
.body(guestbooks);
}
}
- private final GuestbookService guestbookService;
- GuestbookService 인스턴스를 필드로 선언합니다. @RequiredArgsConstructor 어노테이션에 의해 생성자 주입을 받습니다.
- @GetMapping("/api/guestbooks")
- GET 메서드를 처리하는 /api/guestbooks 엔드포인트를 정의합니다. 모든 방명록을 조회하는 요청을 처리합니다.
- public ResponseEntity<List<GuestbookResponse>> findAllGuestbooks() { ... }
- 모든 방명록을 조회하는 메서드입니다. GuestbookService의 findAll 메서드를 호출하여 모든 방명록을 가져온 후, 이를 GuestbookResponse로 매핑하여 리스트로 변환하여 HTTP 응답으로 반환합니다.
GuestbookController 클래스는 RESTful 웹 서비스를 제공하기 위해 필요한 엔드포인트들을 정의하고, GuestbookService를 사용하여 비즈니스 로직을 처리합니다. 클라이언트가 POST 요청으로 새로운 방명록을 추가하거나 GET 요청으로 모든 방명록을 조회할 수 있습니다.
그리고 이번엔
main/resource 위치에
template Directory를 만든뒤
guestview.html 을 아래처럼 작성한다
guestview.html
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>방명록</title>
</head>
<body>
<div id="refreshDiv">
<h1>방명록</h1>
<div>
<h3>방명록 입력</h3>
<input id="guestnn" placeholder="이름을 입력하세요">
<input id="guestct" placeholder="내용을 입력하세요">
<input value="등록" type="button" onclick="dataSend()">
</div>
<div>
<table>
<thead>
<tr><!DOCTYPE html>
<th>번호</th>
<th>작성자</th>
<th>내용</th>
</tr>
</thead>
<tbody>
<div th:each="guestbook : ${guestbooks}">
<tr>
<td th:text="${guestbook.id}"></td>
<td th:text="${guestbook.guestName}"></td>
<td th:text="${guestbook.guestContent}"></td>
</tr>
</div>
</tbody>
</table>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.js"></script>
<script>
function dataSend() {
var guestDto = {
guestName : $("#guestnn").val(),
guestContent : $("#guestct").val()
}
var guest = JSON.stringify(guestDto);
$.ajax({
url: "/view",
type: "POST",
data: guest,
contentType : "application/json",
success: function(data) {
$('#refreshDiv').replaceWith(data);
}
});
}
</script>
</body>
</html>
그리고 application을 실행한뒤에 컨트롤러에 Getmapping 에 나오는 경로인
localhost:8080/api/guestbooks 를 가보면 어떠한 빈 배열이 나오면 성공한것이다
아까 저장했던 html 을보려면 viewController 도 필요하다
그리고 기존에 만든 controller 패키지에 GuestbookViewController.java 파일을 만들고 아래처럼 넣어준다.
GuestbookViewController
package com.codehows.portfolio.controller;
import com.codehows.portfolio.dto.AddGuestbookRequest;
import com.codehows.portfolio.dto.GuestbookResponse;
import com.codehows.portfolio.dto.GuestbookViewResponse;
import com.codehows.portfolio.entity.Guestbook;
import com.codehows.portfolio.service.GuestbookService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RequiredArgsConstructor
@Controller
public class GuestbokkViewController {
private final GuestbookService guestbookService;
@GetMapping(value="view")
public String GuestbooksView(Model model) {
List<GuestbookViewResponse> guestbooks = guestbookService.findAll()
.stream()
.map(GuestbookViewResponse::new)
.toList();
model.addAttribute("guestbooks", guestbooks);
return "/guestview";
}
}
스프링 MVC에서 Thymeleaf를 사용하여 방명록(Guestbook) 데이터를 화면에 표시하는 Controller 클래스를 정의한 것입니다. 코드를 살펴보고 각 부분을 설명해보겠습니다.
- private final GuestbookService guestbookService;
- GuestbookService 인스턴스를 필드로 선언합니다. @RequiredArgsConstructor 어노테이션에 의해 생성자 주입을 받습니다.
- @GetMapping(value="view")
- GET 메서드를 처리하는 view 엔드포인트를 정의합니다. 화면에 모든 방명록을 표시하는 요청을 처리합니다.
- public String GuestbooksView(Model model) { ... }
- 모든 방명록을 조회하여 화면에 표시하는 메서드입니다. GuestbookService의 findAll 메서드를 호출하여 모든 방명록을 가져온 후, 이를 GuestbookViewResponse로 매핑하여 리스트로 변환합니다. 그리고 이 리스트를 모델에 추가하여 View로 전달합니다.
- model.addAttribute("guestbooks", guestbooks);
- 모델에 "guestbooks"라는 속성으로 guestbooks 리스트를 추가합니다. 이는 View에서 guestbooks 리스트에 접근할 수 있게 합니다.
- return "/guestview";
- 화면을 표시할 View의 이름을 반환합니다. 여기서는 "/guestview"라는 Thymeleaf 템플릿을 사용하여 방명록 데이터를 화면에 표시할 것으로 예상됩니다.
GuestbokkViewController 클래스는 스프링 MVC에서 화면을 템플릿으로 표현할 때 사용하는 컨트롤러입니다. Thymeleaf를 사용하여 화면에 방명록 데이터를 표시하기 위해 GuestbookService를 사용하여 데이터를 조회하고, 이를 모델에 추가하여 View로 전달합니다.
이렇게 만든뒤 http://localhost:8080/view 로 들어가보면 아래처럼 보이게 된다.
그런데 아직 등록이 작동을 안한다
그이유는 AddController를 따로 만들어줘야하기때문이다
'Full Stack Course 풀스택과정 > SPRING' 카테고리의 다른 글
SpringBoot - OAuth2 로 카카오 로그인 (0) | 2024.05.10 |
---|---|
스프링부트 비동기식 방명록 만들기 ( 2 ) (0) | 2024.05.06 |
SpringBoot - TOAST UI Editor 로 게시글 사진 업로드 (0) | 2024.04.24 |
SpringBoot 게시글 기본 업로드 VS TOAST UI Editor 로 업로드 (0) | 2024.04.24 |
SpringBoot - OAuth2 로 구글 로그인 (2) OAuth2 실행테스트 (0) | 2024.04.23 |