본문으로 바로가기
 

ORM 말고 SQL로 AWS RDS DB와 Express 웹 서버 연결

AWS RDS RDS(Relational Database Servide) 관계형 데이터베이스(RDBMS)를 생성하고 확장할 수 있는 서비스 DB 인스턴스를 손 쉽게 생성하고 관리하며 성능 확장도 할 수 있고 여러모로 편리하다. 장애에 대비한 F..

darrengwon.tistory.com

위 포스트와 연계하여 작성했습니다.

 

 

React의 경우 Container와 Presenter를 이용하여 Container에서 axios를 통해 정보를 백엔드로부터 가져온 뒤, Presenter에게 props로 전달하는 방식이 좋습니다. Hook을 써서 한 js 파일에 다 담아도 되구요.

 

https://darrengwon.tistory.com/156

 

Container + Presenter Pattern 디자인 패턴

container presenter pattern 코딩 패턴이다. express에서 MVC design pattern에 근거해서 코딩 했듯이 React.js에서 사용하는 코딩 패턴이다. container 컴포넌트와 presenter 컴포넌트를 분리하는 것이 포인트이..

darrengwon.tistory.com


 

 

Hooks를 이용해 프론트를 다음과 같이 코딩했습니다.

 

여기서 눈여겨볼 점은

 

🧷 form에 onSubmit input에 onChange (필요하다면 button에 onClick)

🧷 axios의 post를 이용했으며 FormData 인스턴스를 사용했고 전송 시 헤더에 multipart/form-data를 적어준다는 점

 

 

FormData

The FormData interface provides a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the XMLHttpRequest.send() method. It uses the same format a form would use if the encoding typ

developer.mozilla.org

import React, { useState } from "react";
import { post } from "axios";
import styled from "styled-components";

const CustomerAdd = (props) => {
  const [file, setFile] = useState(null);
  const [userName, setUserName] = useState("");
  const [birthday, setBirthday] = useState("");
  const [gender, setGender] = useState("");
  const [job, setJob] = useState("");
  const [fileName, setFileName] = useState("");

  // submit를 누르면 실행할 함수입니다.
  // axios의 post를 이용했습니다.
  const addCustomer = () => {
    const url = `/api/customers`;
    const formData = new FormData();
    formData.append("image", file);
    formData.append("name", userName);
    formData.append("birthday", birthday);
    formData.append("gender", gender);
    formData.append("job", job);
    const config = {
      headers: {
        "content-type": "multipart/form-data",
      },
    };
    return post(url, formData, config);
  };

  // submit를 누르면 실행됩니다.
  const handleForSubmit = (e) => {
    e.preventDefault();
    addCustomer().then((res) => console.log(res));
    // 초기화.
    // 편의상 이렇게 한 것이며 부모 컴포넌트가 자식 컴포넌트에게 props의 형태로
    // 물려주는 방식이 더 일반적입니다. (Presenter, Container 게시물을 참고합시다)
    setFile(null);
    setUserName("");
    setBirthday("");
    setGender("");
    setJob("");
    setFileName("");
    // 페이지 새로고침
    window.location.reload();
  };

  const handleFileChange = (e) => {
    // 여러 파일을 업로드 했을 때 하나만 가져와야 합니다.
    setFile(e.target.files[0]);
    setFileName(e.target.value);
  };

  const handleValueChange = (e) => {
    e.preventDefault();
    if (e.target.name === "userName") {
      setUserName(e.target.value);
    } else if (e.target.name === "birthday") {
      setBirthday(e.target.value);
    } else if (e.target.name === "gender") {
      setGender(e.target.value);
    } else if (e.target.name === "job") {
      setJob(e.target.value);
    }
  };

  return (
    <>
      <form onSubmit={handleForSubmit}>
        <h1>고객추가</h1>
        프로필 이미지 :
        <input
          type="file"
          name="file"
          file={file}
          value={fileName}
          onChange={handleFileChange}
        ></input>
        이름 :
        <input
          tpye="text"
          name="userName"
          value={userName}
          onChange={handleValueChange}
        ></input>
        생년월일:
        <input
          type="text"
          name="birthday"
          value={birthday}
          onChange={handleValueChange}
        ></input>
        성별:
        <input
          tpye="text"
          name="gender"
          value={gender}
          onChange={handleValueChange}
        ></input>
        직업:
        <input
          tpye="text"
          name="job"
          value={job}
          onChange={handleValueChange}
        ></input>
        <button type="submit">제출</button>
      </form>
    </>
  );
};

export default CustomerAdd;

 

아직 DB 서버로 전송하지는 않았지만 Express 까지는 전달이 되는 것을 볼 수 있습니다. Network의 Headers 부분에서 Form Data를 확인해보면 사용자가 입력한 정보들을 볼 수 있습니다.

 

 

express의 app.js에서 post 라우터를 통해 이미지를 업로드하고 DB에 추가하는 쿼리를 날립니다.

여기서 눈 여겨볼 점은

 

🧷 multer를 이용했다는 것

🧷 sql에 ?르로 통해 params를 이용해 넣을 수 있다는 것

// multer import.
const multer = require("multer");

// multer 객체 생성
const upload = multer({ dest: "./upload" });

// 유저가 접근하는 /image 경로는 ./upload 폴더와 매핑.
app.use("/image", express.static("./upload"));

// form 전송시 post를 처리할 코드입니다.
app.post("/api/customers", upload.single("image"), (req, res) => {
  let sql = "INSERT INTO CUSTOMER VALUES (null, ?, ?, ?, ?, ?)";
  let image = "/image/" + req.file.filename;
  let name = req.body.name;
  let birthday = req.body.birthday;
  let gender = req.body.gender;
  let job = req.body.job;
  // 각 물음표가 바인딩 되어서 들어감
  let params = [image, name, birthday, gender, job];
  
  //connection은 mysql 객체입니다. 자세한 사항은 전 포스트를 참고하세요.
  connection.query(sql, params, (err, rows, fiedls) => {
    console.log(err);
    res.send(rows);
  });
});

 

폼을 통해 제출하면 DB에 추가됨을 알 수 있습니다. 쌉꿀!

 

이제 프론트-백엔드-DB 서버간 소통이 가능해집니다. 여러가지 테스트를 해봅시다.

 


 

여담으로, 이러한 방식으로 삭제도 가능합니다. 그러나 delete 명령을 보내 직접 DB의 정보를 삭제하는 것보다, createAt과 isDeleted 컬럼을 주어 삭제가 되었는지 되지 않았는지를 체크하고 삭제 되지 않은 정보만을 화면에 출력하는게 더욱 안전합니다. 

실수로 데이터를 지울 수도 있으며 복구 요청이 들어올 수도 있기 때문입니다. 기억하세요. 직접 데이터를 지우는 것은 위험합니다!!


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체