노드 학습 10일차
안녕하세요 마저 공부해보겠습니다
multer
html의 form 태그의 타입이 multipart/form-data 인 데이터를 파싱하는 모듈 입니다.
express의 json()
, urlencoded()
를 통해 json 데이터와 form 데이터를 받아올 수 있었지만 multipart/form-data
인 데이터는 파싱하지 못하기 때문에 해당 모듈을 사용합니다.
multipart/form-data
인 경우 데이터는 이미지, 동영상 등의 파일 입니다.
설치 방법
npm i multer
세팅 방법
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const express = require('express');
const multer = require('multer');
const app = express();
const upload = multer({
storage:multer.diskStorage({
destination(req,file,done){
// done(null,{업로드경로})
done(null, 'uploads');
},
filename(req,file,done){
// done(null,{파일명})
const ext = path.extname(file.originalname); // 파일 확장자 추출
// '파일명+밀리 초 단위의 시간+확장자' 로 파일명을 저장
done(null, path.basename(file.originalname+Date.now()+ext));
}
}),
limits:{
// filesize : {파일사이즈}
filesize : 5 * 1024 * 1024
}
})
done()
의 첫 번째 인수는 업로드 실패 시 사용될 에러 객체, 두 번째는 파일 업로드가 성공적일 때 반환될 데이터를 의미합니다. 만약 업로드 객체에서 파일의 확장자가 jpg가 아닌 경우에는 파일 업로드를 못하도록 해본다면 다음과 같이 수정할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
//생략
filename(req,file,done){
// done(null,{파일명})
const ext = path.extname(file.originalname); // 파일 확장자 추출
if(ext !== '.jpg'){
return done(new Error('jpg만 가능합니다'))
}
// '파일명+밀리 초 단위의 시간+확장자' 로 파일명을 저장
done(null, path.basename(file.originalname+Date.now()+ext));
}
//생략
여기서는 첫 번째 인수로 에러 객체를 전달하여 파일 업로드가 실패했음을 알려주고 있습니다.
사용 방법
1
2
3
4
//예시) app.post('{URL}',upload.single({file의 name속성 값}),(req,res)=>{
app.post('/upload',upload.single('image'),(req,res)=>{
})
주석에서 설명한 file의 name 속성 값은 html에서 타입이 file인 input 태그의 name 속성을 의미합니다.
예시)
1
<input type="file" name="이거요"/>
업로드 객체의 기능
.single(fieldname)
하나의 파일만을 업로드 받습니다.
예시)
1
2
3
app.post('/upload',upload.single('image'),(req,res)=>{
//작업 생략
})
.array(fieldname[, maxCount])
파일을 배열로 받습니다. maxCount
이상의 파일이 전달되면 에러가 발생할 수 있습니다.
예시)
1
2
3
app.post('/upload',upload.array('image',10),(req,res)=>{
//작업 생략
})
name 속성의 값이 image
이고 10개까지의 파일을 업로드 받는 라우트
.fields(fields)
fields
에 선언된 파일들을 받습니다.
예시)
1
2
3
4
5
6
app.post('/upload',upload.fileds([
{name:'hand',maxCount:5},
{name:'foot',maxCount:10}
]),(req,res)=>{
// 작업 생략
})
name의 속성 값이 hand인 요소에서는 5개를 받고 foot인 요소에서는 10개까지 받는 라우트
.none()
텍스트만 전달 받습니다. 만약 파일이 업로드 될 경우 LIMIT_UNEXPECTED_FILE
에러를 발생시킵니다. 기능적으로는 upload.fields[{}]
와 같은 동작을 합니다.
.any()
전달된 모든 파일을 허용합니다.
하나의 미들웨어에서만 처리하는 이유?
멀티파트 데이터를 처리하는 작업은 대부분의 경우 모든 라우트에서 발생하는 작업이 아니기 때문 입니다.
1
app.use(upload.single('image'));
만약 제가 위와 같이 미들웨어를 사용했다면 모든 라우트에 대해서 동작하게 되기 때문에 비효율 적입니다. 뿐만 아니라 공식 문서에서도 이는 보안적 취약으로 인해 사용하지 말라 하고 있습니다.
그리고 한 가지 더 궁금했던 예시로 다음과 같은 경우가 있었습니다.
1
2
3
4
app.use('/uploads',upload.single('image'));
app.pose('/uploads',(req,res)=>{
// 작업 생략
})
사용 방법 에서 봤던 부분과 기능적으로 어떻게 다른지에 대해 궁금했습니다.
여기서 use()
를 사용해 특정 URL에만 미들웨어로써 동작하도록 한다면 모든 HTTP 메서드가 multer 미들웨어를 거치게 되어서 비효율적입니다.
그렇기 때문에 위의 예시와 같이 한 라우트에서만 사용하는 경우라면 라우트에 바로 연결해서 사용하는 것이 리소스 절약에 좋습니다.
파일 정보 확인하기
requst
객체의 file
속성에서 확인할 수 있습니다.
1
2
3
4
app.post('/upload',upload.single('image'),(req,res)=>{
console.log(req.file);
res.send('OK');
})
dotenv
프로젝트 내의 .env
파일을 소스코드에서 사용할 수 있도록 돕는 모듈입니다.
설치 방법
npm i dotenv
세팅 방법
app.js
파일 내에서 다음의 코드를 통해 사용을 설정합니다. 파일의 최상단에 위치하는 것이 좋습니다. 그래야 .env
파일에 접근하여 사용할 수 있기 때문입니다.
1
2
const dotenv = require('dotenv');
dotenv.config();
다음으로 프로젝트 내에 .env
파일을 생성합니다.
여기서 사용할 정보를 키=값
형태로 입력합니다. 이때 세미콜론은 사용하지 않습니다.
예시)
1
COOKIE_SECRET = SECRET
사용 방법
process.env.{사용할키}
의 방법으로 접근하여 사용합니다.
.env
파일에서 저장한 키와 매핑하여 값을 가져옵니다.
예시)
1
2
3
//생략
app.use(cookieParser(process.env.COOKIE_PARSER));
//생략