웹 개발

클라이언트(Frontend)와 서버(Backend) 간의 데이터 흐름

Blue_bull 2025. 2. 26. 20:15

클라이언트(Frontend)와 서버(Backend) 간의 데이터 흐름

🚀 GET 요청의 전체 흐름: Front → Back → Front (React + Spring Boot + MySQL + Axios 사용)

📌 기본 개념

  • Frontend (React + Axios) → 데이터를 요청
  • Backend (Spring Boot + JPA) → 요청을 처리하고 DB에서 데이터 조회
  • Database (MySQL) → 데이터를 저장하고 조회

🔄 전체 흐름 (GET 요청)

1️⃣ React (사용자가 데이터 요청)
   ⬇️ Axios GET 요청 전송 (HTTP 요청)
2️⃣ Spring Boot Controller (요청 수신)
   ⬇️ Service 계층으로 전달
3️⃣ Spring Boot Service (비즈니스 로직 실행)
   ⬇️ Repository에서 데이터 조회
4️⃣ Spring Boot Repository (DB에서 데이터 가져오기)
   ⬆️ 조회된 데이터를 Service로 반환
5️⃣ Service (Entity → DTO 변환 후 반환)
   ⬆️ Controller로 반환
6️⃣ Controller (프론트엔드로 JSON 응답 반환)
   ⬆️ HTTP 응답 (JSON 데이터)
7️⃣ React (Axios 응답 받아 UI 업데이트)

1️⃣ Frontend → Backend (GET 요청 보내기)

📌 React에서 사용자가 데이터를 요청하면 Axios를 통해 백엔드에 GET 요청을 보냄

📌 Axios를 사용한 API 호출 (React)

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

function UserProfile({ userId }) {
    const [user, setUser] = useState(null);

    useEffect(() => {
        axios.get(`http://localhost:8080/users/${userId}`)
            .then(response => setUser(response.data))  // JSON 데이터 저장
            .catch(error => console.error("Error fetching user:", error));
    }, [userId]);

    if (!user) return <p>Loading...</p>;

    return <h1>Welcome, {user.name}!</h1>;
}

export default UserProfile;

📌 요청 흐름

  1. useEffect에서 Axios를 사용해 GET /users/{userId} 요청
  2. 응답 데이터를 setUser로 상태 업데이트
  3. UI에서 사용자 이름을 표시

2️⃣ Backend Controller (요청을 받아 처리)

📌 Spring Boot의 @GetMapping을 사용해 요청을 처리
📌 Service에 데이터를 요청하고, 결과를 JSON으로 반환

@RestController
@RequestMapping("/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/{userId}")
    public ResponseEntity<UserDTO> getUser(@PathVariable Long userId) {
        UserDTO user = userService.getUserById(userId);
        return ResponseEntity.ok(user);  // JSON 응답 반환
    }
}

📌 흐름

  1. 프론트엔드에서 /users/{userId}GET 요청
  2. @PathVariable을 사용해 URL의 {userId} 값을 가져옴
  3. userService.getUserById(userId) 호출

3️⃣ Backend Service (비즈니스 로직 처리)

📌 비즈니스 로직을 수행하고, DB에서 데이터를 조회한 후 DTO로 변환

@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public UserDTO getUserById(Long userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("User not found"));

        return new UserDTO(user);  // Entity → DTO 변환 후 Controller로 반환
    }
}

📌 흐름

  1. Repository.findById(userId)를 호출하여 DB에서 데이터 조회
  2. 조회된 User(Entity)UserDTO로 변환
  3. UserDTOController로 반환

4️⃣ Backend Repository (DB에서 데이터 가져오기)

📌 MySQL에서 데이터를 조회하는 역할

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

📌 흐름

  1. JpaRepositorySELECT * FROM users WHERE id = ? 실행
  2. 조회된 데이터를 User(Entity) 객체로 변환하여 반환

5️⃣ Entity vs DTO 변환 (프론트엔드에 맞게 데이터 가공)

📌 Entity: DB와 1:1 매핑되는 객체
📌 DTO: 프론트엔드로 전달할 데이터만 포함하는 객체

// Entity (DB 테이블과 매핑됨)
@Entity
@Table(name = "users")
public class User {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private String email;

    public User() {}

    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // Getter & Setter
}

// DTO (클라이언트에 반환할 데이터만 포함)
public class UserDTO {
    private String name;
    private String email;

    public UserDTO(User user) {
        this.name = user.getName();
        this.email = user.getEmail();
    }
}

📌 흐름

  1. Entity는 DB의 users 테이블과 1:1 매핑
  2. UserService에서 User(Entity)UserDTO 변환
  3. UserDTOJSON으로 변환 후 프론트엔드로 전달

6️⃣ Backend → Frontend (JSON 응답 반환)

📌 Controller에서 DTO를 JSON으로 변환 후 프론트엔드로 반환

return ResponseEntity.ok(user);

📌 응답 데이터 예시

{
  "name": "John Doe",
  "email": "john@example.com"
}

7️⃣ Frontend에서 응답을 받아 UI 업데이트

📌 React에서 데이터를 받아 화면을 업데이트

axios.get(`http://localhost:8080/users/1`)
  .then(response => console.log(response.data));  // { name: "John Doe", email: "john@example.com" }

📌 React 컴포넌트에서 UI 업데이트

function UserProfile({ userId }) {
    const [user, setUser] = useState(null);

    useEffect(() => {
        axios.get(`http://localhost:8080/users/${userId}`)
            .then(response => setUser(response.data))
            .catch(error => console.error("Error fetching user:", error));
    }, [userId]);

    if (!user) return <p>Loading...</p>;

    return <h1>Welcome, {user.name}!</h1>;
}

📌 흐름

  1. 백엔드에서 JSON 응답을 반환
  2. 프론트엔드에서 응답을 받아 useState에 저장
  3. 데이터를 화면에 렌더링

📌 전체적인 흐름 (한눈에 보기)

[1] React (Axios로 GET 요청)
    axios.get("/users/1")

[2] Spring Boot Controller가 요청 처리
    @GetMapping("/{userId}")

[3] Service가 Repository 호출하여 DB 조회
    userRepository.findById(userId)

[4] Repository가 MySQL에서 데이터 조회
    SELECT * FROM users WHERE id = ?

[5] Service에서 Entity → DTO 변환

[6] Controller에서 JSON 응답 반환
    return ResponseEntity.ok(userDTO);

[7] React에서 응답 받아 UI 업데이트

🚀 결론

1️⃣ React → Axios GET 요청 → Spring Boot Controller
2️⃣ Controller → Service → Repository → MySQL에서 데이터 조회
3️⃣ MySQL → Repository → Service → DTO 변환 후 Controller로 반환
4️⃣ Controller가 JSON 응답 반환 → React에서 UI 업데이트

🚀 POST 요청의 전체 흐름: Front → Back → Front (React + Spring Boot + MySQL + Axios 사용)

📌 기본 개념

  • Frontend (React + Axios) → 사용자가 데이터를 입력하고 POST 요청
  • Backend (Spring Boot + JPA) → 데이터를 처리하여 DB에 저장
  • Database (MySQL) → 데이터를 저장 및 관리

🔄 전체 흐름 (POST 요청)

1️⃣ React (사용자가 폼 입력 후 저장 요청)
   ⬇️ Axios POST 요청 (JSON 데이터 포함)
2️⃣ Spring Boot Controller (요청 수신)
   ⬇️ Service 계층으로 데이터 전달
3️⃣ Spring Boot Service (비즈니스 로직 실행)
   ⬇️ Repository에서 데이터 저장
4️⃣ Spring Boot Repository (DB에 데이터 저장)
   ⬆️ 저장된 데이터를 Service로 반환
5️⃣ Service (Entity → DTO 변환 후 반환)
   ⬆️ Controller로 반환
6️⃣ Controller (프론트엔드로 JSON 응답 반환)
   ⬆️ HTTP 응답 (저장된 데이터 반환)
7️⃣ React (Axios 응답 받아 UI 업데이트)

1️⃣ Frontend → Backend (POST 요청 보내기)

📌 React에서 사용자가 데이터를 입력하고 버튼을 클릭하면 Axios를 통해 백엔드에 POST 요청을 보냄

📌 Axios를 사용한 API 호출 (React)

import { useState } from "react";
import axios from "axios";

function CreateUser() {
    const [name, setName] = useState("");
    const [email, setEmail] = useState("");

    const handleSubmit = async (e) => {
        e.preventDefault();
        const userData = { name, email };

        try {
            const response = await axios.post("http://localhost:8080/users", userData);
            console.log("User Created:", response.data); // 백엔드에서 반환된 데이터
        } catch (error) {
            console.error("Error creating user:", error);
        }
    };

    return (
        <form onSubmit={handleSubmit}>
            <input type="text" placeholder="Name" onChange={(e) => setName(e.target.value)} />
            <input type="email" placeholder="Email" onChange={(e) => setEmail(e.target.value)} />
            <button type="submit">Create User</button>
        </form>
    );
}

export default CreateUser;

📌 요청 흐름

  1. 사용자가 이름과 이메일을 입력 후 버튼 클릭
  2. handleSubmit()이 실행되면서 axios.post()POST 요청 전송
  3. 요청 본문(Body)에 { name, email } 데이터를 포함

2️⃣ Backend Controller (요청을 받아 처리)

📌 Spring Boot의 @PostMapping을 사용하여 요청을 처리
📌 프론트엔드에서 보낸 데이터를 받아 Service로 전달

@RestController
@RequestMapping("/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @PostMapping
    public ResponseEntity<UserDTO> createUser(@RequestBody UserDTO userDTO) {
        UserDTO savedUser = userService.createUser(userDTO);  // Service에 요청 전달
        return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);  // JSON 응답 반환
    }
}

📌 흐름

  1. @PostMapping이 HTTP POST 요청을 처리
  2. @RequestBody를 사용해 JSON 데이터를 userDTO 객체로 변환
  3. userService.createUser(userDTO)를 호출하여 서비스 계층으로 전달

3️⃣ Backend Service (비즈니스 로직 처리)

📌 비즈니스 로직을 수행하고, 데이터 검증 후 Repository로 전달

@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Transactional
    public UserDTO createUser(UserDTO userDTO) {
        User user = new User(userDTO.getName(), userDTO.getEmail());  // DTO → Entity 변환
        User savedUser = userRepository.save(user);  // DB에 저장
        return new UserDTO(savedUser);  // Entity → DTO 변환 후 Controller로 반환
    }
}

📌 흐름

  1. DTOEntity로 변환 (UserDTO → User)
  2. userRepository.save(user)를 호출하여 DB에 저장
  3. 저장된 User(Entity)UserDTO로 변환 후 Controller에 반환

4️⃣ Backend Repository (DB에 데이터 저장)

📌 MySQL에서 데이터를 저장하는 역할

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

📌 흐름

  1. JpaRepositoryINSERT INTO users (...) VALUES (...) 실행
  2. 저장된 데이터를 User(Entity) 객체로 반환

5️⃣ Entity vs DTO 변환 (프론트엔드에 맞게 데이터 가공)

📌 Entity: DB와 1:1 매핑되는 객체
📌 DTO: 프론트엔드로 전달할 데이터만 포함하는 객체

// Entity (DB 테이블과 매핑됨)
@Entity
@Table(name = "users")
public class User {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

    public User() {}

    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // Getter & Setter
}

// DTO (클라이언트에 반환할 데이터만 포함)
public class UserDTO {
    private String name;
    private String email;

    public UserDTO(User user) {
        this.name = user.getName();
        this.email = user.getEmail();
    }
}

📌 흐름

  1. Entity는 DB의 users 테이블과 1:1 매핑
  2. UserService에서 User(Entity)UserDTO 변환
  3. UserDTOJSON으로 변환 후 프론트엔드로 전달

6️⃣ Backend → Frontend (JSON 응답 반환)

📌 Controller에서 저장된 데이터를 JSON으로 변환 후 반환

return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);

📌 응답 데이터 예시

{
  "name": "John Doe",
  "email": "john@example.com"
}

7️⃣ Frontend에서 응답을 받아 UI 업데이트

📌 React에서 데이터를 받아 화면을 업데이트

axios.post("http://localhost:8080/users", { name: "John Doe", email: "john@example.com" })
    .then(response => console.log("Created User:", response.data));

📌 전체적인 흐름 (한눈에 보기)

[1] React (Axios로 POST 요청)
    axios.post("/users", { name, email })

[2] Spring Boot Controller가 요청 처리
    @PostMapping + @RequestBody

[3] Service가 Repository 호출하여 DB 저장
    userRepository.save(user)

[4] Repository가 MySQL에 데이터 저장
    INSERT INTO users (name, email) VALUES (?, ?)

[5] Service에서 Entity → DTO 변환

[6] Controller에서 JSON 응답 반환
    return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);

[7] React에서 응답 받아 UI 업데이트

🚀 결론

1️⃣ React → Axios POST 요청 → Spring Boot Controller
2️⃣ Controller → Service → Repository → MySQL에 데이터 저장
3️⃣ MySQL → Repository → Service → DTO 변환 후 Controller로 반환
4️⃣ Controller가 JSON 응답 반환 → React에서 UI 업데이트

🚀 PUT 요청의 전체 흐름: Front → Back → Front (React + Spring Boot + MySQL + Axios 사용)

📌 기본 개념

  • Frontend (React + Axios) → 사용자가 데이터를 수정하고 PUT 요청
  • Backend (Spring Boot + JPA) → 데이터를 업데이트 후 DB 반영
  • Database (MySQL) → 기존 데이터를 수정 및 저장

🔄 전체 흐름 (PUT 요청)

1️⃣ React (사용자가 수정 요청)
   ⬇️ Axios PUT 요청 (JSON 데이터 포함)
2️⃣ Spring Boot Controller (요청 수신)
   ⬇️ Service 계층으로 데이터 전달
3️⃣ Spring Boot Service (비즈니스 로직 실행)
   ⬇️ Repository에서 기존 데이터 조회 후 수정
4️⃣ Spring Boot Repository (DB에 데이터 업데이트)
   ⬆️ 수정된 데이터를 Service로 반환
5️⃣ Service (Entity → DTO 변환 후 반환)
   ⬆️ Controller로 반환
6️⃣ Controller (프론트엔드로 JSON 응답 반환)
   ⬆️ HTTP 응답 (수정된 데이터 반환)
7️⃣ React (Axios 응답 받아 UI 업데이트)

1️⃣ Frontend → Backend (PUT 요청 보내기)

📌 React에서 사용자가 데이터를 수정하고, Axios를 통해 백엔드에 PUT 요청을 보냄

📌 Axios를 사용한 API 호출 (React)

import { useState } from "react";
import axios from "axios";

function UpdateUser({ userId }) {
    const [name, setName] = useState("");
    const [email, setEmail] = useState("");

    const handleUpdate = async (e) => {
        e.preventDefault();
        const userData = { name, email };

        try {
            const response = await axios.put(`http://localhost:8080/users/${userId}`, userData);
            console.log("User Updated:", response.data); // 백엔드에서 반환된 데이터
        } catch (error) {
            console.error("Error updating user:", error);
        }
    };

    return (
        <form onSubmit={handleUpdate}>
            <input type="text" placeholder="New Name" onChange={(e) => setName(e.target.value)} />
            <input type="email" placeholder="New Email" onChange={(e) => setEmail(e.target.value)} />
            <button type="submit">Update User</button>
        </form>
    );
}

export default UpdateUser;

📌 요청 흐름

  1. 사용자가 이름과 이메일을 입력 후 업데이트 버튼 클릭
  2. handleUpdate() 실행 → axios.put()PUT 요청 전송
  3. 요청 본문(Body)에 { name, email } 데이터를 포함

2️⃣ Backend Controller (요청을 받아 처리)

📌 Spring Boot의 @PutMapping을 사용하여 요청을 처리
📌 Service에 데이터를 요청하고, 결과를 JSON으로 반환

@RestController
@RequestMapping("/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @PutMapping("/{userId}")
    public ResponseEntity<UserDTO> updateUser(
            @PathVariable Long userId, 
            @RequestBody UserDTO userDTO) {
        UserDTO updatedUser = userService.updateUser(userId, userDTO);
        return ResponseEntity.ok(updatedUser);  // JSON 응답 반환
    }
}

📌 흐름

  1. @PutMapping("/{userId}")가 HTTP PUT 요청을 처리
  2. @RequestBody를 사용해 JSON 데이터를 userDTO 객체로 변환
  3. userService.updateUser(userId, userDTO)를 호출하여 서비스 계층으로 전달

3️⃣ Backend Service (비즈니스 로직 처리)

📌 비즈니스 로직을 수행하고, 기존 데이터를 조회한 후 수정하여 저장

@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Transactional
    public UserDTO updateUser(Long userId, UserDTO userDTO) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("User not found"));

        user.setName(userDTO.getName());  // 기존 값 수정
        user.setEmail(userDTO.getEmail());

        User updatedUser = userRepository.save(user);  // 변경된 데이터 저장
        return new UserDTO(updatedUser);  // Entity → DTO 변환 후 Controller로 반환
    }
}

📌 흐름

  1. Repository.findById(userId)를 호출하여 기존 데이터 조회
  2. 조회된 User(Entity)이름과 이메일을 수정
  3. userRepository.save(user)를 호출하여 변경된 데이터 DB에 저장
  4. 수정된 User(Entity)UserDTO로 변환 후 Controller에 반환

4️⃣ Backend Repository (DB에 데이터 수정)

📌 JPA를 이용해 DB에서 데이터를 조회 후 업데이트

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

📌 흐름

  1. JpaRepositorySELECT * FROM users WHERE id = ? 실행하여 기존 데이터 조회
  2. 엔티티의 데이터를 수정 후 UPDATE users SET name = ?, email = ? WHERE id = ? 실행
  3. 수정된 데이터를 User(Entity) 객체로 반환

5️⃣ Entity vs DTO 변환 (프론트엔드에 맞게 데이터 가공)

📌 Entity: DB와 1:1 매핑되는 객체
📌 DTO: 프론트엔드로 전달할 데이터만 포함하는 객체

// Entity (DB 테이블과 매핑됨)
@Entity
@Table(name = "users")
public class User {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

    public User() {}

    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // Getter & Setter
}

// DTO (클라이언트에 반환할 데이터만 포함)
public class UserDTO {
    private String name;
    private String email;

    public UserDTO(User user) {
        this.name = user.getName();
        this.email = user.getEmail();
    }
}

📌 흐름

  1. Entity는 DB의 users 테이블과 1:1 매핑
  2. UserService에서 User(Entity)UserDTO 변환
  3. UserDTOJSON으로 변환 후 프론트엔드로 전달

6️⃣ Backend → Frontend (JSON 응답 반환)

📌 Controller에서 수정된 데이터를 JSON으로 변환 후 반환

return ResponseEntity.ok(updatedUser);

📌 응답 데이터 예시

{
  "name": "John Doe",
  "email": "john@example.com"
}

7️⃣ Frontend에서 응답을 받아 UI 업데이트

📌 React에서 데이터를 받아 화면을 업데이트

axios.put(`http://localhost:8080/users/1`, { name: "John Doe", email: "john@example.com" })
    .then(response => console.log("Updated User:", response.data));

📌 전체적인 흐름 (한눈에 보기)

[1] React (Axios로 PUT 요청)
    axios.put("/users/1", { name, email })

[2] Spring Boot Controller가 요청 처리
    @PutMapping("/{userId}") + @RequestBody

[3] Service가 Repository 호출하여 기존 데이터 조회 및 수정
    userRepository.findById(userId)
    user.setName(newName)
    userRepository.save(user)

[4] Repository가 MySQL에서 데이터 수정
    UPDATE users SET name = ?, email = ? WHERE id = ?

[5] Service에서 Entity → DTO 변환

[6] Controller에서 JSON 응답 반환
    return ResponseEntity.ok(updatedUser);

[7] React에서 응답 받아 UI 업데이트

🚀 결론

1️⃣ React → Axios PUT 요청 → Spring Boot Controller
2️⃣ Controller → Service → Repository → MySQL에서 기존 데이터 조회 및 수정
3️⃣ MySQL → Repository → Service → DTO 변환 후 Controller로 반환
4️⃣ Controller가 JSON 응답 반환 → React에서 UI 업데이트

🚀 PATCH 요청의 전체 흐름: Front → Back → Front (React + Spring Boot + MySQL + Axios 사용)

📌 PATCH 요청의 특징

  • PUT과 차이점:
    • PUT전체 데이터를 수정 (모든 필드 필요)
    • PATCH일부 필드만 수정 가능 (변경된 필드만 보냄)
  • 프론트엔드(React + Axios) → 사용자가 데이터를 수정하고 PATCH 요청 전송
  • 백엔드(Spring Boot + JPA) → 변경된 데이터만 업데이트 후 DB 반영
  • 데이터베이스(MySQL) → 기존 데이터에서 일부 필드만 수정 및 저장

🔄 전체 흐름 (PATCH 요청)

1️⃣ React (사용자가 특정 필드 수정 요청)
   ⬇️ Axios PATCH 요청 (변경된 JSON 데이터만 포함)
2️⃣ Spring Boot Controller (요청 수신)
   ⬇️ Service 계층으로 데이터 전달
3️⃣ Spring Boot Service (비즈니스 로직 실행)
   ⬇️ Repository에서 기존 데이터 조회 후 부분 수정
4️⃣ Spring Boot Repository (DB에 변경된 데이터만 업데이트)
   ⬆️ 수정된 데이터를 Service로 반환
5️⃣ Service (Entity → DTO 변환 후 반환)
   ⬆️ Controller로 반환
6️⃣ Controller (프론트엔드로 JSON 응답 반환)
   ⬆️ HTTP 응답 (수정된 데이터 반환)
7️⃣ React (Axios 응답 받아 UI 업데이트)

1️⃣ Frontend → Backend (PATCH 요청 보내기)

📌 React에서 사용자가 일부 데이터만 수정하고, Axios를 통해 백엔드에 PATCH 요청을 보냄

📌 Axios를 사용한 API 호출 (React)

import { useState } from "react";
import axios from "axios";

function UpdateUserEmail({ userId }) {
    const [email, setEmail] = useState("");

    const handleUpdate = async (e) => {
        e.preventDefault();
        const updatedData = { email };  // name은 변경하지 않음

        try {
            const response = await axios.patch(`http://localhost:8080/users/${userId}`, updatedData);
            console.log("User Updated:", response.data); // 백엔드에서 반환된 데이터
        } catch (error) {
            console.error("Error updating user:", error);
        }
    };

    return (
        <form onSubmit={handleUpdate}>
            <input type="email" placeholder="New Email" onChange={(e) => setEmail(e.target.value)} />
            <button type="submit">Update Email</button>
        </form>
    );
}

export default UpdateUserEmail;

📌 요청 흐름

  1. 사용자가 이메일만 입력 후 업데이트 버튼 클릭
  2. handleUpdate() 실행 → axios.patch()PATCH 요청 전송
  3. 요청 본문(Body)에 { email } 변경된 필드만 포함

2️⃣ Backend Controller (요청을 받아 처리)

📌 Spring Boot의 @PatchMapping을 사용하여 요청을 처리
📌 Service에 데이터를 요청하고, 결과를 JSON으로 반환

@RestController
@RequestMapping("/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @PatchMapping("/{userId}")
    public ResponseEntity<UserDTO> updateUserPartially(
            @PathVariable Long userId, 
            @RequestBody Map<String, Object> updates) {
        UserDTO updatedUser = userService.updateUserPartially(userId, updates);
        return ResponseEntity.ok(updatedUser);  // JSON 응답 반환
    }
}

📌 흐름

  1. @PatchMapping("/{userId}")가 HTTP PATCH 요청을 처리
  2. @RequestBodyMap<String, Object> 형태로 받아 변경된 필드만 처리
  3. userService.updateUserPartially(userId, updates)를 호출하여 서비스 계층으로 전달

3️⃣ Backend Service (비즈니스 로직 처리)

📌 비즈니스 로직을 수행하고, 기존 데이터를 조회한 후 일부 필드만 수정하여 저장

@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Transactional
    public UserDTO updateUserPartially(Long userId, Map<String, Object> updates) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("User not found"));

        updates.forEach((key, value) -> {
            switch (key) {
                case "name": user.setName((String) value); break;
                case "email": user.setEmail((String) value); break;
                default: throw new IllegalArgumentException("Invalid field: " + key);
            }
        });

        User updatedUser = userRepository.save(user);  // 변경된 데이터 저장
        return new UserDTO(updatedUser);  // Entity → DTO 변환 후 Controller로 반환
    }
}

📌 흐름

  1. Repository.findById(userId)를 호출하여 기존 데이터 조회
  2. updates.forEach()를 사용하여 변경된 필드만 수정
  3. userRepository.save(user)를 호출하여 변경된 데이터 DB에 저장
  4. 수정된 User(Entity)UserDTO로 변환 후 Controller에 반환

4️⃣ Backend Repository (DB에 데이터 수정)

📌 JPA를 이용해 DB에서 데이터를 조회 후 업데이트

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

📌 흐름

  1. JpaRepositorySELECT * FROM users WHERE id = ? 실행하여 기존 데이터 조회
  2. 엔티티의 일부 데이터를 수정 후 UPDATE users SET 필드명 = ? WHERE id = ? 실행
  3. 수정된 데이터를 User(Entity) 객체로 반환

5️⃣ Entity vs DTO 변환 (프론트엔드에 맞게 데이터 가공)

// Entity (DB 테이블과 매핑됨)
@Entity
@Table(name = "users")
public class User {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

    public User() {}

    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // Getter & Setter
}

// DTO (클라이언트에 반환할 데이터만 포함)
public class UserDTO {
    private String name;
    private String email;

    public UserDTO(User user) {
        this.name = user.getName();
        this.email = user.getEmail();
    }
}

📌 흐름

  1. Entity는 DB의 users 테이블과 1:1 매핑
  2. UserService에서 User(Entity)UserDTO 변환
  3. UserDTOJSON으로 변환 후 프론트엔드로 전달

6️⃣ Backend → Frontend (JSON 응답 반환)

📌 Controller에서 수정된 데이터를 JSON으로 변환 후 반환

return ResponseEntity.ok(updatedUser);

📌 응답 데이터 예시

{
  "name": "John Doe",
  "email": "updated@example.com"
}

7️⃣ Frontend에서 응답을 받아 UI 업데이트

📌 React에서 데이터를 받아 화면을 업데이트

axios.patch(`http://localhost:8080/users/1`, { email: "updated@example.com" })
    .then(response => console.log("Updated User:", response.data));

📌 전체적인 흐름 (한눈에 보기)

[1] React (Axios로 PATCH 요청)
    axios.patch("/users/1", { email })

[2] Spring Boot Controller가 요청 처리
    @PatchMapping("/{userId}") + @RequestBody Map<String, Object>

[3] Service가 Repository 호출하여 기존 데이터 조회 및 수정
    userRepository.findById(userId)
    updates.forEach()로 변경된 필드만 수정
    userRepository.save(user)

[4] Repository가 MySQL에서 변경된 필드만 업데이트
    UPDATE users SET email = ? WHERE id = ?

[5] Service에서 Entity → DTO 변환

[6] Controller에서 JSON 응답 반환
    return ResponseEntity.ok(updatedUser);

[7] React에서 응답 받아 UI 업데이트

🚀 결론

1️⃣ React → Axios PATCH 요청 → Spring Boot Controller
2️⃣ Controller → Service → Repository → MySQL에서 기존 데이터 조회 및 일부 수정
3️⃣ Controller가 JSON 응답 반환 → React에서 UI 업데이트

🚀 DELETE 요청의 전체 흐름: Front → Back → Front (React + Spring Boot + MySQL + Axios 사용)

📌 DELETE 요청의 특징

  • 데이터를 삭제하는 요청
  • 프론트엔드(React + Axios) → 사용자가 삭제 버튼 클릭 시 DELETE 요청 전송
  • 백엔드(Spring Boot + JPA) → 데이터를 삭제 후 DB 반영
  • 데이터베이스(MySQL) → 해당 데이터 삭제 처리

🔄 전체 흐름 (DELETE 요청)

1️⃣ React (사용자가 삭제 요청)
   ⬇️ Axios DELETE 요청 (경로에 ID 포함)
2️⃣ Spring Boot Controller (요청 수신)
   ⬇️ Service 계층으로 데이터 전달
3️⃣ Spring Boot Service (비즈니스 로직 실행)
   ⬇️ Repository에서 데이터 삭제
4️⃣ Spring Boot Repository (DB에서 데이터 삭제)
   ⬆️ 삭제 완료 후 Service로 반환
5️⃣ Service (삭제 완료 후 반환)
   ⬆️ Controller로 반환
6️⃣ Controller (프론트엔드로 JSON 응답 반환)
   ⬆️ HTTP 응답 (삭제 성공 메시지 반환)
7️⃣ React (Axios 응답 받아 UI 업데이트)

1️⃣ Frontend → Backend (DELETE 요청 보내기)

📌 React에서 사용자가 삭제 버튼을 클릭하면 Axios를 통해 백엔드에 DELETE 요청을 보냄

📌 Axios를 사용한 API 호출 (React)

import axios from "axios";

function DeleteUser({ userId, onDelete }) {
    const handleDelete = async () => {
        try {
            await axios.delete(`http://localhost:8080/users/${userId}`);
            console.log("User Deleted");
            onDelete(userId); // UI에서 삭제 처리
        } catch (error) {
            console.error("Error deleting user:", error);
        }
    };

    return <button onClick={handleDelete}>Delete User</button>;
}

export default DeleteUser;

📌 요청 흐름

  1. 사용자가 삭제 버튼 클릭
  2. handleDelete() 실행 → axios.delete()DELETE 요청 전송
  3. 서버에서 사용자 ID에 해당하는 데이터 삭제

2️⃣ Backend Controller (요청을 받아 처리)

📌 Spring Boot의 @DeleteMapping을 사용하여 요청을 처리
📌 Service에 삭제 요청을 전달하고, 결과를 JSON으로 반환

@RestController
@RequestMapping("/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @DeleteMapping("/{userId}")
    public ResponseEntity<String> deleteUser(@PathVariable Long userId) {
        userService.deleteUser(userId);
        return ResponseEntity.ok("User deleted successfully");
    }
}

📌 흐름

  1. @DeleteMapping("/{userId}")가 HTTP DELETE 요청을 처리
  2. @PathVariable을 사용해 URL의 {userId} 값을 가져옴
  3. userService.deleteUser(userId)를 호출하여 서비스 계층으로 전달
  4. 삭제 성공 후 "User deleted successfully" 메시지를 반환

3️⃣ Backend Service (비즈니스 로직 처리)

📌 비즈니스 로직을 수행하고, 삭제할 데이터를 조회한 후 삭제

@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Transactional
    public void deleteUser(Long userId) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("User not found"));

        userRepository.delete(user);  // 데이터 삭제
    }
}

📌 흐름

  1. Repository.findById(userId)를 호출하여 삭제할 데이터 조회
  2. 데이터가 존재하면 userRepository.delete(user)를 호출하여 삭제
  3. 삭제 후 Controller에 성공 응답 반환

4️⃣ Backend Repository (DB에서 데이터 삭제)

📌 JPA를 이용해 DB에서 데이터를 삭제

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

📌 흐름

  1. JpaRepositoryDELETE FROM users WHERE id = ? 실행
  2. 삭제 성공 후 Service에 반환

5️⃣ Backend → Frontend (JSON 응답 반환)

📌 Controller에서 삭제 성공 메시지를 JSON으로 변환 후 반환

return ResponseEntity.ok("User deleted successfully");

📌 응답 데이터 예시

"User deleted successfully"

6️⃣ Frontend에서 응답을 받아 UI 업데이트

📌 React에서 데이터를 받아 화면을 업데이트

axios.delete(`http://localhost:8080/users/1`)
    .then(() => console.log("User Deleted"));

📌 React 컴포넌트에서 UI 업데이트

function UserList() {
    const [users, setUsers] = useState([
        { id: 1, name: "John Doe" },
        { id: 2, name: "Jane Doe" }
    ]);

    const handleDelete = (userId) => {
        setUsers(users.filter(user => user.id !== userId)); // 삭제된 데이터 UI에서 제거
    };

    return (
        <div>
            {users.map(user => (
                <div key={user.id}>
                    <span>{user.name}</span>
                    <DeleteUser userId={user.id} onDelete={handleDelete} />
                </div>
            ))}
        </div>
    );
}

📌 흐름

  1. 사용자 목록에서 삭제 버튼 클릭
  2. axios.delete() 요청 후 서버에서 삭제 처리
  3. 응답을 받은 후 setUsers()를 사용해 삭제된 데이터 UI에서 제거

📌 전체적인 흐름 (한눈에 보기)

[1] React (Axios로 DELETE 요청)
    axios.delete("/users/1")

[2] Spring Boot Controller가 요청 처리
    @DeleteMapping("/{userId}")

[3] Service가 Repository 호출하여 기존 데이터 조회 및 삭제
    userRepository.findById(userId)
    userRepository.delete(user)

[4] Repository가 MySQL에서 데이터 삭제
    DELETE FROM users WHERE id = ?

[5] Service에서 삭제 완료 후 Controller로 반환

[6] Controller에서 JSON 응답 반환
    return ResponseEntity.ok("User deleted successfully");

[7] React에서 응답 받아 UI 업데이트
    setUsers(users.filter(user => user.id !== userId));

🚀 결론

1️⃣ React → Axios DELETE 요청 → Spring Boot Controller
2️⃣ Controller → Service → Repository → MySQL에서 데이터 삭제
3️⃣ 삭제 성공 후 Controller가 JSON 응답 반환 → React에서 UI 업데이트