예, 이번에 배워볼 nulter 모듈은 업로드 된 이미지를 불러오는 모듈입니다.
솔직히 요즘 이미지 업로드는 뭐... 거의 쓰이니까 알아두면 아주 좋겠죠??
npm install multer --save
이렇게 설치 해줄 건데...
'어? --save라는 코드가 추가됬네요?'
네, 이 --save 같은 경우에는 package.json에 dependencies 영역에
'모듈명:버전' 형식의 데이터로 남게 해줍니다. 뭐 굳이 --save를 쓸 필요는 없습니다만, 나중에 많은 모듈을 쓸 때는 내가 뭘 로드했는지 모를 수도 있으니까 미리 예방하기 위해서 --save로 명시적인 데이터를 얻을 수 있도록 합시다.
바로 사용법을 알아봅시다.
const express = require('express'); const app = express(); const path = require('path'); const multer = require('multer'); const upload = multer({ storage: multer.diskStorage({ destination: function (req, file, cb) { cb(null, 'img'); }, filename: function (req, file, cb) { var newFileName = new Date().valueOf() + path.extname(file.originalname) cb(null, newFileName); } }), }); const port = 5000; app.use(express.static('img')); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.set('view engine', 'ejs'); app.set('views', './views'); app.get('/', (req, res) => { res.render('index'); }); app.post('/upload', upload.single('imageFile'), (req, res) => { var file = req.file.filename res.send(` <h1>Image Upload Successfully</h1> <a href="/">Back</a> <p><img src="${file}" alt="image 출력"/></p>` ); console.log(file); }); app.listen(port, () => { console.log(`http://localhost:${port}`); });
제가 짠 코드는 이렇습니다. 그럼 코드를 하나씩 보면서 설명하겠습니다.
const path = require('path'); const multer = require('multer');
'엥? path는 뭐에요?' path는 내장 모듈로서 경로를 쉽게 구하기 위해서 사용합니다.
const upload = multer({ storage: multer.diskStorage({ destination: function (req, file, cb) { cb(null, 'img'); }, filename: function (req, file, cb) { var newFileName = new Date().valueOf() + path.extname(file.originalname) cb(null, newFileName); } }), });
사실 오늘의 핵심은 이 녀석입니다.
upload라는 변수에 multer를 정의 해줄겁니다.
multer에는 storage와 filename이라는 데이터가 들어갈 수 있습니다.
storage는 저장 공간을 할당하는 것입니다. 저는 img 폴더를 만들었습니다~
filename에서는 img의 이름을 바꾸는 역활을 합니다.
대충 뜯어보면 올린 시각과 확장자명을 추출해와서 하나의 문자열로 만듭니다.
(path.extname(file.originalname) 이 코드가 결국 확장자 명을 추출해오는 것.)
app.use(express.static('img'));
이 코드가 무엇이냐? 정적인 파일을 로드하기 위해 필요한 코드입니다. 저는 img 파일을 정적 파일로 선언함으로서 img 안의 것들을 정적인 파일로 불러오겠다는 겁니다.
근데 이게 신기한게 여기서 img를 선언하면 경로를 선언할때 './img'라는 경로를 명시해줄 필요가 없다는 겁니다. 이미 img라는 폴더를 정적폴더로 선언했기에 굳이 명시해줄 필요가 없는 겁니다.
정말 신기하지 않습니까?
그 다음은 본체입니다.
app.post('/upload', upload.single('imageFile'), (req, res) => { var file = '/image/' + req.file.filename res.send(` <h1>Image Upload Successfully</h1> <a href="/">Back</a> <p><img src="${file}" alt="image 출력"/></p>` ); console.log(file); });
잘 보니까 'upload.single('imageFile')' 이 친구가 추가됐네요?
upload는 저희가 방금 설정해준 그 업로드가 맞습니다.
single은 불러오는 타입으로 single과 array가 있습니다.
뭐 당연히 single은 하나의 이미지만 array는 여러 개의 이미지를 불러옵니다.
저는 single만 예제를 들겠습니다. 둘의 차이점은 거의 없습니다.
/upload에 들어가면 이미지가 img 파일에 들어올 겁니다. 그럼 저희는 그 이미지를 들고와서 클라이언트에게 보내주면 그만이죠.
정말 간단하죠?
그리고 예제로 쓰일 html 코드입니다.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Node.js Test</title> </head> <body> <h1>Node.js Test</h1> <div> <form action="/upload" method="post", enctype="multipart/form-data"> <input type="file", id="file", accept="image/*", name="imageFile"> <p><input type="submit", value="제출"></p> </form> <div> </body> </html>
자 여기서 주의깊게 봐야할 부분은 'enctype="multipart/form-data"' 이 코드입니다. 이 코드가 없으면 file을 보낼 수 없다는 점~~ 뭐, html 고수분들은 알거라고 생각합니다.
그리고 file을 보낼 거니까 당연히 input의 type은 file로 선언해주시면 되겠습니다.
참고로 보내진 데이터는 json 형식으로 옵니다.
(출저:https://velog.io/@limsw/NodeJS-multer%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%ED%8C%8C%EC%9D%BC-%EC%97%85%EB%A1%9C%EB%93%9C-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0)
나중에 image 데이터를 파싱해서 걸러내실때 유용하게 쓰일테니 알아두시면 되겠습니다.
오늘 배운 multer 어떠셨나요?
사실 이 multer의 진가는 DB와 결합되었을 때에 나옵니다.
이건 나중에 DB와 node.js의 연결에 들어가면
확인해보는 것으로 합시다.
그럼 여기서 포스팅 마치겠습니다. bye bye.