-
Notifications
You must be signed in to change notification settings - Fork 5
NCP Object Storage를 이용하여 이미지 업로드하기
→ 네이버 클라우드 플랫폼 서비스 중 하나
→ 사용자가 언제 어디서나 원하는 데이터를 저장하고 탐색할 수 있도록 파일 저장 공간을 제공하는 서비스
→ AWS S3 compatible API를 제공하므로, S3를 활용한 툴을 Object Storage에서도 사용할 수 있음
Object Storage를 사용해서 이미지를 선택하면 서버에 업로드되고, 저장된 이미지 주소를 마크다운 형식으로 작성해보기
- NCP(https://www.ncloud.com/) 사이트에서 Object 생성
- FE에서 선택한 이미지 파일을 서버에 요청보내는 코드 작성
- BE에서 요청받은 객체를 NCP에 업로드 후, 응답으로 주소값 반환
- FE에서 응답받은 주소값으로 마크다운 형식으로 작성
https://www.ncloud.com/product/storage/objectStorage 접속 후 이용 신청
- 아래와 같은 화면에서 버킷 생성 버튼 클릭
- 권한은 공개 권한으로 설정
먼저 file을 입력받기 위한 간단한 jsx코드를 작성합니다
import React, { useState } from 'react';
function TestPage() {
let [imgPath, setImgPath] = useState('');
return (
<div>
<input type="file" accept="image/png" onChange={submitHandler}></input>
</div>
)
}
export default TestPage;
이후, 선택된 파일을 서버에 보내주는 이벤트 코드를 작성합니다
서버와의 비동기 통신을 사용하기 위해 axios를 설치해줍니다
서버로 이미지를 보낼때에는 FormData라는 객체에 담아서 보내야하며 'filename' 이라는 이름으로 추가해줍니다
npm install axios
import axios from 'axios';
const submitHandler = (event) => {
if (event.target.files !== null) {
//FormData 생성
const fd = new FormData();
//FormData에 key, value 추가하기
fd.append('filename', event.target.files[0]);
// axios 사용해서 백엔드에게 파일 보내기
axios
.post(`/api/test`, fd, {
headers: { 'Content-Type': 'multipart/form-data;charset=utf-8;' },
})
.then((res) => {
//응답으로 받은 url 저장하기 (응답 내용의 표시나 방법은 백엔드와 결정해야한다.)
setImgPath(res.data);
})
//에러가 날 경우 처리
.catch((error) => {
console.log(error.response);
});
}
};
npm install multer multer-s3 aws-sdk
multer : 프론트로부터 받은 파일에 대한 처리를 도와주는 라이브러리
multer-s3 : 업로드된 파일을 NCP에 바로 업로드할 수 있도록 도와주는 라이브러리
aws-sdk : AWS S3에서 제공하는 Javascript SDK를 이용할 때 필요한 라이브러리
아래의 코드는 네이버에서 제공해주는 예제 코드입니다
우선 ACCESS_KEY와 SECRET_KEY는 네이버 클라우드 홈페이지에서 얻을 수 있습니다.
마이페이지 > 계정관리 > 인증키 관리에 접속 후, API 인증키가 없다면 신규 API 인증키 생성을 통해 키를 생성합니다.
이후, 얻어온 키는 환경변수 설정을 통해 ⭐Private⭐하게 보관해줍니다
const AWS = require('aws-sdk');
const multer = require('multer');
const multerS3 = require('multer-s3');
const path = require('path');
const endpoint = new AWS.Endpoint('https://kr.object.ncloudstorage.com');
const region = 'kr-standard';
const access_key = process.env.ACCESS_KEY;
const secret_key = process.env.SECRET_KEY;
const S3 = new AWS.S3({
endpoint,
region,
credentials: {
accessKeyId: access_key,
secretAccessKey: secret_key,
},
});
우선 '/test'로 post 요청을 처리하기 위해 다음과 같이 router를 작성해 줍니다
이후 multer storage를 multer-s3 라이브러리를 이용하여 작성해줍니다.
이때 저장되는 파일의 이름을 중복방지를 위해 현재시간으로 설정해줍니다
등록한 upload 변수는 파일이 하나이므로 upload.single로 작성하며, FormData의 key값을 적어주어 미들웨어로 등록해줍니다
const router = require('express').Router();
const multer = require('multer');
const multerS3 = require('multer-s3');
const path = require('path');
const upload = multer({
storage: multerS3({
s3: S3, // 위에서 정의한 S3 Object
bucket: 'issue', // 버킷 이름
contentType: multerS3.AUTO_CONTENT_TYPE, // 자동을 콘텐츠 타입 세팅
acl: 'public-read', // 클라이언트에서 자유롭게 가용하기 위함
key: (req, file, cb) => {
cb(null, new Date().valueOf() + path.extname(file.originalname));
},
}),
limits: { fileSize: 5 * 1024 * 1024 }, // 용량 제한
});
router.post('/test', upload.single('filename'), (req, res) => {
res.send(req.file.location);
};
module.exports = router;
multer를 등록해주면 라우터에서 다음과 같이 사용할 수 있습니다
const file = req.file
console.log(req.file)
프론트는 NCP에 올라가게 될 파일의 위치가 필요하니 req.file.location변수를 보내줍니다
const router = require('express').Router();
const AWS = require('aws-sdk');
const multer = require('multer');
const multerS3 = require('multer-s3');
const path = require('path');
const endpoint = new AWS.Endpoint('https://kr.object.ncloudstorage.com');
const region = 'kr-standard';
const access_key = process.env.ACCESS_KEY;
const secret_key = process.env.SECRET_KEY;
const S3 = new AWS.S3({
endpoint,
region,
credentials: {
accessKeyId: access_key,
secretAccessKey: secret_key,
},
});
const upload = multer({
storage: multerS3({
s3: S3,
bucket: 'issue', // 버킷 이름
contentType: multerS3.AUTO_CONTENT_TYPE, // 자동을 콘텐츠 타입 세팅
acl: 'public-read', // 클라이언트에서 자유롭게 가용하기 위함
key: (req, file, cb) => {
cb(null, new Date().valueOf() + path.extname(file.originalname));
},
}),
limits: { fileSize: 5 * 1024 * 1024 }, // 용량 제한
});
router.post('/test', upload.single('filename'), (req, res) => {
res.send(req.file.location);
};
module.exports = router;
→ 서버로부터 반환받은 파일이름과 object 주소를 이용하여 state를 업데이트 시켜줍니다
import React, { useState } from 'react';
import axios from 'axios';
function TestPage() {
const submitHandler = (event) => {
if (event.target.files !== null) {
const fd = new FormData();
fd.append('filename', event.target.files[0]);
axios
.post(`/api/test`, fd, {
headers: { 'Content-Type': 'multipart/form-data;charset=utf-8;' },
})
.then((res) => {
setImgPath(`https://kr.object.ncloudstorage.com/issue/` + res.data);
})
.catch((error) => {
console.log(error.response);
});
}
};
let [imgPath, setImgPath] = useState('');
if (imgPath == '') {
return (
<div>
<input type="file" accept="image/png" onChange={submitHandler}></input>
</div>
);
} else {
return <a href={imgPath}>마크다운 형식 : {imgPath}</a>;
}
}
export default TestPage;
💡파일을 업로드할 때, 다음과 같이 옵션을 추가해주어 해결
ACL: 'public-read' ContentType: 'image/png'
(async () => {
await S3.upload(
{
Bucket: bucket_name,
Key: object_name,
Body: fs.createReadStream(local_file_name),
ACL: 'public-read',
ContentType: 'image/png',
},
options
).promise();
})();
참고자료
https://docs.ncloud.com/ko/storage/storage-8-4.html
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property
https://krpeppermint100.medium.com/js-react에서-express로-이미지-파일-올리기-multer-f398adf6dbdd