Jun's Blog

홈페이지 만들어보기[상품 수정](with SpringBoot) - (10) 본문

WEB/React

홈페이지 만들어보기[상품 수정](with SpringBoot) - (10)

luckydadit 2025. 2. 21. 17:13

1. 상품 정보 수정 이벤트 처리하기

기존 상품 등록 기능과 상품 정보 수정 기능의 구현 차이점
1. 기본 키인 상품 번호를 가지고 처리합니다.
2. 상품 번호를 이용하여 기존에 기입했던 정보를 읽어 와야 합니다. (useEffect hook 사용)

 

1.1 상품 정보 수정 화면 생성 및 기존 상품 정보 가져오기

ProductUpdateForm.js파일 추가(with. VS Code)
기존 ProductInsertForm.js 파일을 복사하여 이름만 바꿔서 작업하는 걸 추천합니다.
import axios from "axios";
import { useEffect, useState } from "react";
import { Button, Container, Form } from "react-bootstrap";
import { useNavigate, useParams } from "react-router-dom";

function App(){
    const {id} = useParams();
    console.log('수정할 상품 번호 : ' + id);

    const [product, setProduct] = useState({
        name:'',
        price:'',
        category:'',
        stock:'',
        image:'',
        description:''
    });


    useEffect(() => {
        const url = `http://localhost:9000/product/update/${id}`;
        axios.get(url)
            .then((response) => {
                setProduct(response.data);
           
            }).catch((error) => {
                console.log(id + '번 상품 오류 발생 : ' + error);
                alert('상품 정보 가져 오기를 실했습니다.');
            });
    }, [id]);

    const handleChange = (event) => {
        // event는 change 이벤트를 발생시킨 폼 양식
        const {name, value} = event.target;
       
        // 전개 연사자(...)를 사용하여 다른 폼 양식들의 이전 값도 보존하도록 합니다.
        setProduct({
            ...product,
            [name]:value}
        );

    };

    const handleFileChange = (event) => {
        const {name, files} = event.target;
        const file = files[0]; // type="file"인 요소의 0번째 요소

        // FileReader는 JavaScript에서 파일을 읽고 데이터 처리시 사용합니다.
        // Base64 인코딩으로 이미지를 문자열 형태로 변환합니다.
        // 해당 이미지는 자바에서 접두사 "data:image"으로 체크하면 됩니다.
        // 주로 <input type="file" />에서 파일을 읽는 데 사용됩니다.
        const reader = new FileReader();

        reader.readAsDataURL(file);

        reader.onloadend = () => {
            //console.log(reader.result);

            // Base64 인코딩으로 이미지를 저장합니다.
            setProduct({
                ...product,
                [name]:reader.result}
            );
        };

    };

    const navigate = useNavigate();

    const handleSubmit = async (event) => {
        event.preventDefault();

        // 수정할 상품 정보
        const productData = {
            name:product.name,
            price:product.price,
            category:product.category,
            stock:product.stock,
            image:product.image,
            description:product.description
        };

        try{
            const url = `http://localhost:9000/product/update/${id}`;
            const data = productData;
           
            // Http 헤더에 이 문서의 타입(Content-Type)이 json이라고 알려 줍니다.
            // ex) text/html, text/css, image/jpeg
            const config = {headers : {'Content-Type':'application/json'}};

            const response = await axios.post(url, data, config);

            console.log(`상품 수정 : [${response.data}]`);
            alert('상품 수정에 성공하였습니다.');

            // 상품 수정된 이후의 처리
            setProduct({
                name:'',
                price:'',
                category:'',
                stock:'',
                image:'',
                description:''
            });

            navigate('/product/list'); // 수정 후 목록 페이지로 이동

        }catch(error){
            console.log('error :', error);
            alert('상품 수정에 실패하였습니다.');
        };

    };

    return(
        <Container className="my-4">
            <h1>상품 수정</h1>
            <Form onSubmit={handleSubmit}>
                <Form.Group className="mb-3" controlId="name">
                    <Form.Label>상품명</Form.Label>
                    <Form.Control
                        type="text"
                        placeholder="상품명을 입력해주세요."
                        name="name"
                        value={product.name}
                        onChange={handleChange}
                        required
                    />
                </Form.Group>
                <Form.Group className="mb-3" controlId="price">
                    <Form.Label>가격</Form.Label>
                    <Form.Control
                        type="text"
                        placeholder="가격을 입력해주세요."
                        name="price"
                        value={product.price}
                        onChange={handleChange}
                        required
                    />
                </Form.Group>
                <Form.Group className="mb-3" controlId="category">
                    <Form.Label>카테고리</Form.Label>
                    <Form.Select
                        name="category"
                        value={product.category}
                        onChange={handleChange}
                        required>
                        {/* JAVA(SpringBoot)의 Enum 타입에 대문자로 작성했으면, 여기서도 대문자로 작성할 것 */}
                        <option value="">카테고리를 선택하세요</option>
                        <option value="BREAD"></option>
                        <option value="BEVERAGE">음료수</option>
                        <option value="CAKE">케익</option>
                    </Form.Select>
                </Form.Group>
                <Form.Group className="mb-3" controlId="stock">
                    <Form.Label>재고</Form.Label>
                    <Form.Control
                        type="text"
                        placeholder="재고를 입력해주세요."
                        name="stock"
                        value={product.stock}
                        onChange={handleChange}
                        required
                    />
                </Form.Group>
                <Form.Group className="mb-3" controlId="image">
                    <Form.Label>이미지</Form.Label>
                    {/* 이미지는 type="file"이어야 하고 이벤트 핸들러를 별로도 해야합니다.(handleFileChange) */}
                    <Form.Control
                        type="file"
                        placeholder="이미지를 첨부해주세요."
                        name="image"
                        onChange={handleFileChange}
                        required
                    />
                </Form.Group>
                <Form.Group className="mb-3" controlId="description">
                    <Form.Label>상품 설명</Form.Label>
                    <Form.Control
                        type="text"
                        placeholder="상품 설명을 입력해주세요."
                        name="description"
                        value={product.description}
                        onChange={handleChange}
                        required
                    />
                </Form.Group>

                <Button  variant="primary" type="submit">
                    상품 수정
                </Button>
            </Form>
        </Container>
    );
}

export default App;
App.js 추가 및 수정 내용 (with. VS Code)
import ProductUpdateForm from './pages/ProductUpdateForm';
            <Routes>
                {/* path에는 요청 url 정보, element에는 컴포넌트 이름 */}
                <Route path='/' element={<HomePage/>}/>
                <Route path='/member/login'  element={<LoginPage setUser={handleLoginSuccess} />}/>
                <Route path='/member/signup' element={<SignupPage/>}/>
                <Route path='/product/list' element={<ProductList/>}/>
                <Route path='/product/detail/:id' element={<ProductDetail/>}/>
                <Route path='/product/insert' element={<ProductInsertForm/>}/>
                <Route path='/product/update/:id' element={<ProductUpdateForm/>}/>
            </Routes>

 

ProductController.java에 추가 및 수정 부분 (with. IntelliJ)
@GetMapping("/update/{id}")
public ResponseEntity<Product> update(@PathVariable Long id){
    Product product = this.productService.getProductById(id);

    if(product != null){
        return ResponseEntity.ok(product); // 200 Ok 응답
    }else{ // 404 응답
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
    }
}

 

<적용 결과>

 

상품 목록 페이지에서 꽈배기를 클릭 시


1.2 수정한 상품 정보 이벤트 처리하기 (진행예정)