[JS]React에서 Express로 이미지 파일 올리기(multer)

peppermint100
6 min readMar 6, 2020

--

서론

페이스북과 인스타그램과 같은 SNS는 물론 지금 사용하는 블로그부터 왠만한 웹 서비스는 이미지 업로드를 지원합니다. front-end에서 React를 사용하여 Express 서버로 이미지를 전송하는 방법에 대해 알아봅시다.

Front

yarn add axios 

먼저 Client(React가 설치된 루트 디렉토리)폴더에서 ajax 통신을 위해 axios 라이브러리를 다운 받습니다.

import React, { useState } from "react";
import axios from "axios";
const BASE_URL = "http://localhost:4000";export default function App() {
const [content, setContent] = useState("");
const [uploadedImg, setUploadedImg] = useState({
fileName: "",
fillPath: ""
});

기본적인 state 구조입니다. content는 리액트(또는 프론트 단)에서 이미지 데이터를 받아서 저장하고 백엔드로 보낼 State입니다.

uploadedImg State는 백엔드에서 받은 Response를 저장할 State입니다.

return (
<>
<form onSubmit={onSubmit}>
{uploadedImg ? (
<>
<img src={uploadedImg.filePath} alt="" />
<h3>{uploadedImg.fileName}</h3>
</>
) : (
""
)}
<input type="file" onChange={onChange} />
<button type="submit">Upload</button>
</form>
</>
);

위와 같이 JSX 코드를 작성합니다. uploadedImg 즉 서버로부터 반응을 받았는지 확인하고 받았다면 이미지 자체와 이미지를 보여줍니다.

const onChange = e => {
setContent(e.target.files[0]);
};
const onSubmit = e => {
e.preventDefault();
const formData = new FormData();
formData.append("img", content);
axios
.post("/upload", formData)
.then(res => {
const { fileName } = res.data;
console.log(fileName);
setUploadedImg({ fileName, filePath: `${BASE_URL}/img/${fileName}` });
alert("The file is successfully uploaded");
})
.catch(err => {
console.error(err);
});
};

이제 이벤트 코드들을 작성해줍니다. 프론트 단에서 서버로 이미지를 보낼 때에는 폼 데이터라는 객체에 담아서 보내야합니다. new FormData를 선언하고 “img” 라는 이름으로 onChange에 의해 담긴 content를 보내줍니다.

그리고 axios를 통해 받은 response는 fileName을 받아올 수 있도록 서버 코드를 잠시 후 작성하게 될 것입니다.

Back

먼저 필요한 라이브러리를 다운 받습니다.

yarn add express multer

multer 라이브러리는 프론트로부터 받은 파일에 대한 처리를 할 수 있도록 도와줍니다.

const path = require("path");
const express = require("express");
const app = express();
const multer = require("multer");
const PORT = 4000;
app.use(express.static("public"));const storage = multer.diskStorage({
destination: "./public/img/",
filename: function(req, file, cb) {
cb(null, "imgfile" + Date.now() + path.extname(file.originalname));
}
});

먼저 Storage를 작성합니다. destination 옵션은 받아온 이미지를 어디에 저장할 것인지 정합니다. 만약 이러한 폴더가 없다면 multer가 이미지를 받아올때 자동으로 생성합니다.

cb는 콜백의 줄임말인데 이 부분을 통하여 이미지의 이름을 정해줍니다. 타임스탬프와 파일의 확장자명을 정해서 저장할 수 있도록 해줍니다. 이렇게 하지 않으면 같은 이름의 파일이 저장되는 경우 버그가 생깁니다.

이 방법은 로컬 서버 폴더에 이미지를 저장하게 되는데 AWS S3 Bucket 등으로 이미지 데이터를 클라우드 서버에 보관할 수 있습니다. 그 경우 이 Storage 코드를 다르게 작성해줍니다.

const upload = multer({
storage: storage,
limits: { fileSize: 1000000 }
});

다음은 업로드 옵션입니다. 어떤 storage를 사용할 것인지(로컬 또는 클라우드) 그리고 파일의 사이즈를 정합니다. 단위는 byte입니다.

app.post("/upload", upload.single("img"), function(req, res, next) {
res.send({
fileName: req.file.filename
});
});

이제 프론트의 axios로부터 post 요청을 받을 코드를 작성합니다. 프론트에서 formData에서 정해주었던 이름으로 img를 받습니다. 그리고 Storage 옵션에서 정해준 fileName을 다시 프론트로 보내줍니다.

여기서

console.log(req.file)

을 통해 여러가지 요청 결과를 확인할 수 있습니다.

--

--

peppermint100

기억하기 위해 또는 잊어버리기 위해 작성하는 블로그입니다.