코드로 배우는 React with 스프링부트 API 서버
Search


리액트 프로젝트 생성
참고링크:
https://tailwindcss.com/docs/installation
•
VSC 터미널에 tailwind css 설치
npm install -D tailwindcss
npx tailwindcss init
•
taliwind.config.js의 content를 다음과 같이 설정
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{js,jsx,ts,tsx}"],
theme: {
extend: {},
},
plugins: [],
}

Tailwind CSS 설정
•
MySQL DB 연동 후 DB와 계정 생성
CREATE DATABASE malldb;
CREATE USER 'malldbuser'@'localhost' IDENTIFIED BY 'Mall1234!';
CREATE USER 'malldbuser'@'%' IDENTIFIED BY 'Mall1234!';
GRANT ALL PRIVILEGES ON malldb.* TO 'malldbuser'@'localhost';
GRANT ALL PRIVILEGES ON malldb.* TO malldbuser@'%';

DB와 부트 프로젝트 생성
React-Router 설정
공통레이아웃설정
Outlet을 이용한 서브메뉴
경로값 추출을 위한 useParams
useSearchParams와 useNavigate
동적 페이지 이동

React-Router
부트 프로젝트 생성 및 확인
엔티티의 테스트
목록(페이징) 처리 구현
서비스계층 만들기
페이지처리를 위한 DTO 설계

스프링부트와 API 서버
•
엔티티 설계
@Entity
@Table(name ="tbl_todo")
@Getter
@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Todo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long tno;
private String title;
private String writer;
private boolean complete;
private LocalDate dueDate;
}
•
엔티티
•
두 가지 경우

엔티티 클래스 만들기
•
build.gradle 설정
buildscript {
ext {
queryDslVersion = "5.0.0"
}
}
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.9'
id 'io.spring.dependency-management' version '1.1.6'
}
group = 'org.zerock'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
//테스트를 위해 추가
testCompileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
// 테스트를 위해 추가
testAnnotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
// QueryDsl
implementation "com.querydsl:querydsl-jpa:${queryDslVersion}:jakarta"
annotationProcessor(
"jakarta.persistence:jakarta.persistence-api",
"jakarta.annotation:jakarta.annotation-api",
"com.querydsl:querydsl-apt:${queryDslVersion}:jakarta")
}
tasks.named('test') {
useJUnitPlatform()
}
compileJava.dependsOn('clean')
•
QTodo
package org.zerock.apiserver.repository.search;
import com.querydsl.jpa.JPQLQuery;
import lombok.extern.log4j.Log4j2;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
import org.zerock.apiserver.domain.Todo;
@Log4j2
public class TodoSearchImpl extends QuerydslRepositorySupport implements TodoSearch {
public TodoSearchImpl() {
super(Todo.class);
}
@Override
public Page<Todo> search1() {
log.info("search1................");
QTodo todo = QTodo.todo;
JPQLQuery<Todo> query = from(todo);
query.where(todo.title.contains("1"));
Pageable pageable = PageRequest.of(1, 10, Sort.by("tno").descending());
this.getQuerydsl().applyPagination(pageable, query);
query.fetch(); // 목록 데이터 가져올 때 활용
query.fetchCount(); // Long 타입
return null;
}
}
•
TodoRepository - TodoSearch 추가
package org.zerock.apiserver.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import org.zerock.apiserver.domain.Todo;
import org.zerock.apiserver.repository.search.TodoSearch;
@Repository
public interface TodoRepository extends JpaRepository<Todo, Long>, TodoSearch {
}

Querydsl 설정하기
•
dto 생성
package org.zerock.apiserver.dto;
import jakarta.persistence.Column;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TodoDTO {
private Long tno;
private String title;
private String content;
private boolean complete;
private LocalDate dueDate;
}
•
service
package org.zerock.apiserver.service;
import org.springframework.transaction.annotation.Transactional;
import org.zerock.apiserver.domain.Todo;
import org.zerock.apiserver.dto.TodoDTO;
@Transactional
public interface TodoService {
TodoDTO get(Long tno);
default TodoDTO entityToDTO(Todo todo) {
return TodoDTO.builder()
.tno(todo.getTno())
.title(todo.getTitle())
.content(todo.getContent())
.complete(todo.isComplete())
.dueDate(todo.getDueDate())
.build();
}
default Todo dtoToEntity(TodoDTO todoDTO) {
return Todo.builder()
.tno(todoDTO.getTno())
.title(todoDTO.getTitle())
.content(todoDTO.getContent())
.complete(todoDTO.isComplete())
.dueDate(todoDTO.getDueDate())
.build();
}
}
•
serviceimpl

DTO 설정과 서비스 계층 만들기



