쇼핑몰 프로젝트

쇼핑몰 프로젝트 # 4 상품등록 기능

Sunho314 2024. 3. 21. 15:02

상품등록을 위한 페이지는 아래와 같이 구성되어 있습니다.

현재는 기입사항이 4가지 밖에 없지만 프로젝트를 진행하며 업데이트 할 예정입니다.

 

백엔드(스프링)에

ProductController 입니다

상품을 저장하는 saveProduct 메소드에 이미지, 이름, 정보, 가격을 받아서 saveProduct() 를 실행시킵니다.

@RestController
@CrossOrigin(origins = "http://localhost:3000")
public class ProductController {

    @Autowired
    private ProductService productService;

    @CrossOrigin(origins = "http://localhost:3000")
    @PostMapping("/saveProduct")
    public ResponseEntity<String> saveProduct(@RequestParam("productImage") MultipartFile productImage,
                                              @RequestParam("productName") String productName,
                                              @RequestParam("infomation") String infomation,
                                              @RequestParam("productPrice") int productPrice) {
        try {
            byte[] imageBytes = productImage.getBytes();
            productService.saveProduct(imageBytes, productName, infomation, productPrice);
            return new ResponseEntity<>("상품 등록 성공", HttpStatus.OK);
        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseEntity<>("상품 등록에 실패했습니다 다시 시도해주세요.", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @GetMapping("/getProductImage/{productCode}")
    public ResponseEntity<byte[]> getProductImage(@PathVariable("productCode") Long productCode) {
        try {
            byte[] imageBytes = productService.getProductImage(productCode);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.IMAGE_JPEG); // 이미지 타입에 따라 변경
            return new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

 

ProductService 는 매개변수로 받은 이미지, 상품명, 설명, 가격을 Product 객체에 저장한 후

JPA를 이용해 productRepository.save로 DB에 저장합니다.

@Autowired
    private ProductRepository productRepository;

    @Transactional
    public void saveProduct(byte[] productImage, String productName, String infomation, int productPrice) {
        try {
            Product product = new Product();
            product.setProductName(productName);
            product.setInfomation(infomation);
            product.setProductPrice(productPrice);

            // Product 엔터티에 이미지 파일 저장
            product.setProductImage(productImage);

            // Product 엔터티를 저장
            productRepository.save(product);
        } catch (Exception e) {
            // 예외 처리
            e.printStackTrace();
            throw new RuntimeException("이미지 저장 실패");
        }
    }

 

그럼 리액트에서 saveProduct 를 이용해 입력받은 값을 저장해보도록 하겠습니다.

 

입력하는 칸을 만들어주었고 값이 변할때마다 handleInputChange 를 실행시킵니다.

<div id="property-form">
        <form encType="multipart/form-data">
          <label htmlFor="productName">상품명:</label>
          <input
            type="text"
            id="productName"
            name="productName" // 수정: 프로퍼티 이름을 name으로 변경
            value={productData.productName} // 수정: 프로퍼티 이름을 name으로 변경
            onChange={handleInputChange}
          />

          <label htmlFor="infomation">설명:</label>
          <input
            type="text"
            id="infomation"
            name="infomation" // 수정: 프로퍼티 이름을 address로 변경
            value={productData.infomation} // 수정: 프로퍼티 이름을 address로 변경
            onChange={handleInputChange}
          />

          <label htmlFor="productPrice">가격:</label>
          <input
            type="text"
            id="productPrice"
            name="productPrice" // 수정: 프로퍼티 이름을 price로 변경
            value={productData.productPrice} // 수정: 프로퍼티 이름을 price로 변경
            onChange={handleInputChange}
          />

          <button type="button" onClick={handleSubmit}>
            상품 등록
          </button>

          <div id="property-details">
            <label htmlFor="productImage">사진 업로드:</label>
            <input
              type="file"
              id="productImage"
              name="productImage"
              accept="image/*"
              onChange={handleFileChange}
            />
            <img id="property-image-preview" src="#" alt="미리보기" />
          </div>
        </form>
      </div>

 

값이 변경될 때마다 value의 값을 해당하는 name의 productData에 저장합니다.

유효성 검사도 진행하여 하나의 값이라도 존재하지 않으면 알람을 띄워줍니다.

const [productData, setProductData] = useState({
    productName: '',
    infomation: '',
    productPrice: '',
  });

  const [productImage, setProductImage] = useState(null);

  const handleInputChange = (e) => {
    const { name, value } = e.target;
    setProductData({ ...productData, [name]: value });
    console.log(value);
  };

  const handleFileChange = (e) => {
    setProductImage(e.target.files[0]);
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      if (
        !productData.productName ||
        !productData.infomation ||
        !productData.productPrice ||
        !productImage
      ) {
        alert('상품명, 위치, 가격, 그리고 사진을 모두 입력해주세요.');
        return;
      }

      const formData = new FormData();
      formData.append('productName', productData.productName);
      formData.append('infomation', productData.infomation);
      formData.append('productPrice', productData.productPrice);
      formData.append('productImage', productImage);

      const response = await axios.post(
        'http://localhost:8000/saveProduct',
        formData,
        {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
        },
      );

      console.log(response.data);
      alert('상품 등록성공');
    } catch (error) {
      alert('실패');
      console.error('상품 저장 오류:', error);
    }
  };

 

모두입력하고 상품등록을 누르면

성공했다는 알림이 뜨고 메인페이지에

원래 추가했었던 상품들의 맨 뒤에 "니트"가 추가되었습니다 !