[2편] React + Spring Boot 풀스택 CRUD

홍정민·2023년 10월 15일

FullStack

목록 보기
2/2
post-thumbnail

이전 포스팅에 이어서 이번엔 React+Spring의 CRUD 를 만들어 보겠다.

이전 포스팅의 프로젝트를 그대로 가져왔기 때문에 이전 포스팅을 꼭 참고하도록 하자!

01. Create

우리의 웹 페이지에서 DB에 새로운 User를 생성해 보자!

일단 서버에 데이터를 보내기 위해 우리의 DB구조에 맞게 프론트 엔드의 form 태그를 작성한다.

기존 코드에 주석 처리한 부분만 추가시키면 된다.

※ 컴포넌트는 다른 파일에 작성해서 import로 가져와 사용해야 하지만 편의상 같은 App.js 파일에 CreateUser 컴포넌트를 만들었다.

리액트

//App.js
import { useEffect, useState } from "react"
import axios from "axios"

//CreateUser 컴포넌트 추가
function CreateUser() {

  return (
      <form method="post" action="/user/create">
          <h3>이름</h3>
          <input type="text" name="name"></input>
          <h3>나이</h3>
          <input type="number" name="age"></input>
          <h3>소개</h3>
          <textarea name="introduce" rows="5"></textarea>
          
          <br></br>
          <input type="submit" value="생성"></input>
      </form>
  )
}
export default function App() {
  const [users, setUsers] = useState();

  useEffect(() => {
    async function getUser() {
      const response = await axios.get(`/user`);
      const data = response.data;

      setUsers(data);
    }

    getUser();
  }, []);

  return (
    <div>
    //CreateUser 컴포넌트 사용
      <CreateUser></CreateUser>
    
      {
        users ? users.map((user) =>
          <div key={user.id}>
            <h3>{user.name} {user.age}</h3>
            <p>{user.introduce}</p>
          </div>
        ) : null
      }
    </div>
  )
}

스프링

백엔드의 컨트롤러와 서비스에 Create 로직을 작성하자

//UserController.java
@Controller
public class UserController {

    @Autowired
    private UserService userService;

    @ResponseBody
    @GetMapping("/user")
    public List<User> userApi() {

        return userService.getUserApi();
    }

	//해당url 경로에 form양식의 데이터를 보내면 매개변수 user에 담아온다.
    @PostMapping("/user/create")
    public String createUserPro(User user) {
        userService.createUser(user);
		
        //post를 하고난 뒤 표시할 url
        //리액트의 서버 포트가 3000을 사용하므로 localhost:3000
        return "redirect:http://localhost:3000/";
    }
}

}
//UserService.java
@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public List<User> getUserApi() {

        return userRepository.findAll();
    }
    
	//createUser 비즈니스 로직 생성
    public void createUser(User user) {
        userRepository.save(user);
    }

02. Delete

사용자 delete할 url은 "/user/delete?id="로 get mapping할 것이다.

리액트

get 호출을 할 링크 태그를 만들어 준다.

//App.js
import { useEffect, useState } from "react"
import axios from "axios"

function CreateUser() {
	//...
}
export default function App() {
  //...
  
  return (
    <div>
      <CreateUser></CreateUser>
      {
        users ? users.map((user) =>
          <div key={user.id}>
            <h3>{user.name} {user.age}</h3>
            <p>{user.introduce}</p>
  			//user 삭제 버튼 추가
            <a href={`/user/delete?id=${user.id}`}>삭제 ID: {user.id}</a>
          </div>
        ) : null
      }
    </div>
  )
}

스프링

user 삭제에 대한 컨트롤러와 서비스 로직을 작성한다.

//UserController.java
@Controller
public class UserController {

    @Autowired
    private UserService userService;

    //...
    
    @GetMapping("/user/delete")
    public String userDeletePro(Integer id) {
        userService.userDelete(id);

        return "redirect:http://localhost:3000/";
    }
}
//UserService.java
@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    //...
    
    public void userDelete(Integer id) {
        userRepository.deleteById(id);
    }
}

03. Update

최대한 내용을 간소화 하기 위해 user의 소개만 변경하는 것으로 만들자.

리액트

//App.js
function CreateUser() { ... }

//UpdateUser 컴포넌트 생성 
//어떤 user의 소개글을 식별하기 위해 id를 인자로 받음
function UpdateUser({id}) {
  return (
    <form method="post" action="/user/update">
      <input type="" name="id" value={id}></input>
      <br></br>
      <input type="text" name="introduce"></input>
      <input type="submit" value="소개 수정"></input>
    </form>
  )
}
export default function App() {
  // ...
  
  return (
    <div>
      <CreateUser></CreateUser>
      {
        users ? users.map((user) =>
          <div key={user.id}>
            <h3>{user.name} {user.age}</h3>
            <p>{user.introduce}</p>
            <a href={`/user/delete?id=${user.id}`}>삭제 ID: {user.id}</a>
			//Update 컴포넌트 사용
            <UpdateUser id={user.id}></UpdateUser>
          </div>
        ) : null
      }
    </div>
  )
}

스프링

//UserController.java
@Controller
public class UserController {

    @Autowired
    private UserService userService;

	// ...
    
    @PostMapping("/user/update")
    public String userUpdatePro(Integer id, User user) {
        User userTemp = userService.userDetail(id);
        userTemp.setIntroduce(user.getIntroduce());

        userService.createUser(userTemp);
        return "redirect:http://localhost:3000/";
    }
}
//UserService

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

	//...
   	
    //특정 id에 대한 데이터 가져오기
    public User userDetail(Integer id) {
        return userRepository.findById(id).get();
    }
}

최종 사용자 CRUD한 UI이다. form양식을 통하여 User(id, name, age, introduce)데이터 형식의 데이터를 생성하며, id로 삭제 및 수정을 한다.

전체 코드

이 포스팅에선 리액트와 스프링의 컨트롤러 및 서비스 코드만 수정했다.

App.js

import { useEffect, useState } from "react"
import axios from "axios"

function CreateUser() {

  return (
    <form method="post" action="/user/create">
      <h3>이름</h3>
      <input type="text" name="name"></input>
      <h3>나이</h3>
      <input type="number" name="age"></input>
      <h3>소개</h3>
      <textarea name="introduce" rows="5"></textarea>

      <br></br>
      <input type="submit" value="생성"></input>
    </form>
  )
}
function UpdateUser({id}) {
  return (
    <form method="post" action="/user/update">
      <input type="" name="id" value={id}></input>
      <br></br>
      <input type="text" name="introduce"></input>
      <input type="submit" value="소개 수정"></input>
    </form>
  )
}
export default function App() {
  const [users, setUsers] = useState();

  useEffect(() => {
    async function getUser() {
      const response = await axios.get(`/user`);
      const data = response.data;

      setUsers(data);
    }

    getUser();
  }, []);

  return (
    <div>
      <CreateUser></CreateUser>
      {
        users ? users.map((user) =>
          <div key={user.id}>
            <h3>{user.name} {user.age}</h3>
            <p>{user.introduce}</p>
            <a href={`/user/delete?id=${user.id}`}>삭제 ID: {user.id}</a>
            <UpdateUser id={user.id}></UpdateUser>
          </div>
        ) : null
      }
    </div>
  )
}

UserController.java

package com.example.demo.controller;

import com.example.demo.entity.User;
import com.example.demo.service.UserService;
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;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
public class UserController {

    @Autowired
    private UserService userService;

    @ResponseBody
    @GetMapping("/user")
    public List<User> userApi() {

        return userService.getUserApi();
    }

    @PostMapping("/user/create")
    public String createUserPro(User user) {
        userService.createUser(user);

        return "redirect:http://localhost:3000/";
    }

    @GetMapping("/user/delete")
    public String userDeletePro(Integer id) {
        userService.userDelete(id);

        return "redirect:http://localhost:3000/";
    }

    @PostMapping("/user/update")
    public String userUpdatePro(Integer id, User user) {
        User userTemp = userService.userDetail(id);
        userTemp.setIntroduce(user.getIntroduce());

        userService.createUser(userTemp);
        return "redirect:http://localhost:3000/";
    }
}

UserService.java

package com.example.demo.service;

import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;


@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public List<User> getUserApi() {

        return userRepository.findAll();
    }

    public User userDetail(Integer id) {
        return userRepository.findById(id).get();
    }
    public void createUser(User user) {
        userRepository.save(user);
    }
    public void userDelete(Integer id) {
        userRepository.deleteById(id);
    }
}

최대한 간소화 시켜서 풀스택 유저 목록 사이트를 만들어 보았다. 추가적으로 리액트 라우터를 사용해서 개인적으로 만들어 보도록 하자

2개의 댓글

comment-user-thumbnail
2024년 5월 10일

제가 찾던건데 너무 감사합니다~

1개의 답글