[SeSACx코딩온] 동적 폼 전송 (Multer)
Node.js와 Multer를 이용한 동적 파일 업로드 구현
1. 동적 파일 업로드를 위한 기본 설정
- 동적 파일 업로드를 구현하기 위해 필요한 모듈들을 설정합니다.
- 기존 설정에 이어,
public디렉토리와 정적 파일에 관련된 것을 설정합니다.
const express = require('express');
const app = express();
const multer = require('multer'); // 파일 업로드를 위한 Multer 모듈 불러오기
const path = require('path'); // 파일 및 디렉토리 경로 작업을 위한 Path 모듈 불러오기
const PORT = 8080;
app.set('views', './views'); // 뷰 템플릿 디렉토리 설정
app.set('view engine', 'ejs'); // EJS를 템플릿 엔진으로 설정
app.use(express.urlencoded({ extended: true })); // URL-encoded 데이터 파싱 미들웨어
app.use(express.json()); // JSON 데이터 파싱 미들웨어
// 정적 파일 제공 설정
app.use('/static', express.static(__dirname + '/public')); // 추가
app.use('/uploads', express.static(__dirname + '/uploads'));
- 정적 파일을 제공하기 위해
/static과/uploads경로를 설정합니다.
2. Multer 설정 및 동적 파일 업로드 라우터 추가
(1) Multer 설정
const uploadDetail = multer({
storage: multer.diskStorage({
destination(req, file, done) {
done(null, 'uploads/'); // 파일 저장할 경로
},
filename(req, file, done) {
const ext = path.extname(file.originalname); // 파일 확장자 추출
done(null, path.basename(file.originalname, ext) + Date.now() + ext); // 저장할 파일명
}
}),
limits: { fileSize: 5 * 1024 * 1024 } // 업로드 파일 크기 제한 (5MB)
});
multer.diskStorage를 사용하여 파일의 저장 경로와 파일명을 설정합니다.destination함수는 파일이 저장될 경로를 설정합니다. 여기서는uploads/디렉토리에 파일이 저장됩니다.filename함수는 저장될 파일명을 설정합니다. 파일명은 원래 파일명에 현재 시간을 추가하여 고유한 이름으로 저장됩니다.path.extname을 사용하여 파일의 확장자를 추출하고,path.basename을 사용하여 확장자를 제외한 파일명을 가져옵니다.limits옵션을 사용하여 업로드 파일의 최대 크기를 5MB로 제한합니다.
(2) 동적 파일 업로드 라우터
app.post('/dynamicFile', uploadDetail.single('thumbnail'), (req, res) => { // ejs의 input의 name과 같아야 정상적으로 불러옴.
res.send(req.file); // 업로드된 파일 정보를 클라이언트에 응답
});
uploadDetail.single('thumbnail')은 단일 파일 업로드를 처리하는 Multer 미들웨어입니다.- 업로드된 파일의 정보를 클라이언트에 응답으로 보냅니다.
3. 업로드된 동적 파일을 보여주는 템플릿 및 코드
(1) views/index.ejs 템플릿
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>동적 파일 업로드</title>
<!-- Axios CDN -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<link rel="stylesheet" href="/static/css/thumbnail.css">
</head>
<body>
<h1><%= title %></h1>
<h2>동적 파일 업로드</h2>
<input type="file" name="thumbnail" id="thumbnail">
<button type="button" onclick="uploadThumbnail();">업로드</button>
<br>
<!-- 이미지 업로드 시 위치할 태그 -->
<img src="" alt=""><br>
<script src="static/js/thumbnail.js"></script>
</body>
</html>
- 사용자는 파일을 선택하고 “업로드” 버튼을 클릭하여 파일을 업로드할 수 있습니다.
- 업로드된 파일은
<img>태그를 통해 즉시 확인할 수 있습니다.
(2) public/js/thumbnail.js 파일
function uploadThumbnail() {
// FormData 객체 생성
const formData = new FormData();
// 파일 입력 요소 선택 (name="thumbnail")
const fileInput = document.querySelector('#thumbnail');
// FormData에 업로드한 파일 추가
formData.append('thumbnail', fileInput.files[0]);
// formData.append('thumbnail', fileInput.files[0]); 는 파일 입력 요소에서
// 첫 번째 파일 객체를 'thumbnail'이라는 이름으로 FormData에 추가합니다.
// FormData 객체는 HTML 폼의 필드와 그 값을 키-값 쌍으로 저장합니다.
// 'thumbnail'은 서버로 전송될 때의 필드 이름이고, fileInput.files[0]는 사용자가 업로드한 파일입니다.
// Axios를 사용하여 서버에 비동기적으로 파일 업로드 요청 보내기
axios({
method: 'POST',
url: '/dynamicFile',
data: formData,
headers: {
'Content-Type': 'multipart/form-data',
}
}).then((res) => {
// 서버 응답 데이터에서 파일 경로 추출하여 img 태그에 설정
document.querySelector('img').src = `/${res.data.path}`;
// img 태그에 썸네일 스타일 클래스 추가
document.querySelector('img').classList.add('thumbnail');
}).catch((err) => {
console.error(err);
});
}
formData.append('thumbnail', fileInput.files[0]);는 파일 입력 요소에서 첫 번째 파일 객체를thumbnail이라는 이름으로FormData에 추가합니다. 이 코드는FormData객체를 사용하여 사용자가 업로드한 파일을 서버로 전송할 수 있도록 준비합니다.FormData객체는 HTML 폼의 필드와 그 값을 키-값 쌍으로 저장하며,thumbnail은 서버로 전송될 때의 필드 이름이고,fileInput.files[0]는 사용자가 선택한 파일입니다. 이를 통해 서버는thumbnail이라는 이름의 파일 데이터를 받을 수 있게 됩니다.axios를 사용하여 비동기적으로 파일 업로드 요청을 보냅니다.- 업로드가 성공하면, 응답으로 받은 파일 경로를
<img>태그의src속성에 설정하여 이미지를 표시합니다. - 파일 업로드 요청이 실패하면 에러를 콘솔에 출력합니다.
(3) public/css/thumbnail.css 파일
.thumbnail {
width: 200px;
height: 200px;
border-radius: 50%;
box-shadow: 0 0 20px #0002;
}
- 업로드된 이미지에
thumbnail클래스를 적용하여 스타일을 지정합니다. - 이미지를 원형으로 만들고, 그림자를 추가합니다.