유저 아바타 변경 기능
multer를 사용해보자
이미지 업로드 버튼 클릭 시 파일을 첨부할 수 있도록 input태그를 사용했다.
<Upload htmlFor='avatar'>
이미지 업로드
<input type='file' id='avatar' name='avatar' onChange={onUploadHandler} />
</Upload>
onUploadHandler 함수 실행 시 유저가 input창에서 선택했던 파일을 FormData를 사용해 avatar라는 키의 값으로 넣어준다.
그리고 post통신으로 서버에 데이터를 보낸다. body에는 formData가 들어간다.
const onUploadHandler = useCallback(
(e) => {
e.preventDefault();
const formData = new FormData();
formData.append('avatar', e.target.files[0]);
fetch(`${process.env.API_SERVER}/api/users/${userId}/avatar/upload`, {
method: 'POST',
body: formData,
})
.then((res) => res.json())
.then(() => refetch())
.catch((error) => console.error(error));
},
[userId, refetch],
);
모든 통신에 axios를 사용했는데 왜 여기는 fetch를 사용했는가?
axios로 파일 통신하면 버전에 따라 문제가 발생할 수 있다고 한다. 그래서 여기서만 fetch를 사용했다.
또, formData에 append를 사용해서 파일을 넣었는데 console.log(formData)를 찍어보면 값을 볼 수 없었다.
[Error] formData의 값을 console.log로 볼 수 없는 원인
WDMA의 드레스 정보에는 각 모델별로 1~3장의 사진이 포함된다. 따라서 새로운 드레스를 추가하거나 수정할 때, 1~3장의 사진을 서버에 업로드할 수 있어야 한다.로직은 Add Dress 페이지를 통해 새로
velog.io
한참을 헤메다가 위 블로그에서 원인을 찾았고, for in문과 for of문을 사용하면 확인이 가능하다는 것을 알았다.
자 이제 그럼 서버로 파일을 넘겼으니 express환경에서 처리해보자.
multer라이브러리를 사용하면 프론트에서 보낸 파일을 서버에서 처리할 수 있다.
npm i multer
import fs from 'fs';
import multer from 'multer';
(function () {
const dir = 'src/assets/avatars';
if (!fs.existsSync(dir)) {
console.log('src 폴더가 없습니다. 폴더를 생성합니다.');
const subDirs = dir.split('/');
let currentDir = '';
for (const subDir of subDirs) {
currentDir += subDir + '/';
if (!fs.existsSync(currentDir)) {
fs.mkdirSync(currentDir);
}
}
}
})();
const storage = multer.diskStorage({
limits: { fileSize: 50 * 1024 }, // 파일크기 500kb 제한
// 파일 저장 경로
destination: (req, file, cb) => {
cb(null, 'src/assets/avatars/');
},
// 파일 이름 변경
filename: (req, file, cb) => {
cb(null, req.params.id + file.originalname);
},
});
const upload = multer({ storage });
multer의 사용법은 인터넷을 찾아보면 다양하게 나와있다.
일단 나는 서버의 하드에 저장하기 위해 diskStorage를 사용하고 아래와 같은 옵션을 지정했다.
- limits : fileSize 50 * 1024 (500kb)
- destination : src/assets/avatars/
- filename : req.params.id + file.originalname (유저id + 파일명)
서버에 src/assets/avatars/ 경로가 없으면 생성하도록 맨 위에는 즉시실행함수를 작성해서 경로를 생성할 수 있도록 했다.
이제 비로소 multer는 미들웨어로 프론트에서 파일을 받으면 서버의 폴더에 저장한다.
저장한 파일 유저의 아바타로 설정하기
router.post('/users/:id/avatar', upload.single('avatar'), async (req, res) => {
const url = `https://www.sentenceu.co.kr/src/assets/avatars/${req.params.id}${req.file.originalname}`;
await User.updateOne({ _id: req.params.id }, { $set: { userAvatar: url } })
.then((user) => {
if (!user) return res.status(403).json({ message: 'User not found.' });
return res.status(200).json({ message: 'Upload Success' });
})
.catch((error) => res.status(500).json({ message: error.message }));
});
post API를 실행하고 multer미들웨어를 통과하면 이제 유저의 아바타를 업로드한 파일로 설정해줘야한다.
서버에 저장한 파일의 경로를 url변수로 저장하고 params로 받은 id로 유저를 검색해 해당 유저의 아바타 이미지 경로를 url로 변경한다.
개발환경에서는 잘 설정 되던게 배포를 하고나면 이미지의 경로를 찾지 못하는 문제가 발생했다.
해결방법은 express의 정적파일 서빙에 있었다.
multer를 통해 upload 폴더 속에 저장한 이미지 접근하기
일단 multer를 통해 이미지를 upload하면 upload folder 속에 이미지가 저장되는 상황이다. 백엔드에 5000번 포트를 할당했다 가정했을 경우 내가 봐왔던 영상들에서 항상 http://localhost:5000/uploads/이미지
dongkyun-jang.tistory.com
홈페이지 접속 시 build/index.html 파일을 서빙해준 것처럼 유저의 이미지에도 접근 할 수 있도록 src폴더를 설정해주면 된다.
app.use('/src', express.static(path.join(__dirname, 'src')));
클라우드타입 배포 자동화
클라우드타입에 배포되어있는 내 서버는 깃허브 레포와 연동되어 Github push 후 서버를 재배포해야하는 번거로움이 있었다.
클라우드타입은 Github Actions로 배포 자동화 기능을 제공하고있다.
Github Actions로 배포 자동화 하기
클라우드타입에서 배포한 서비스를 Github Actions로 배포자동화하는 과정입니다.🧑🏻💻 아래의 가이드 또는 영상에 따라 사용자의 서비스에 CI/CD 파이프라인을 구축해 보세요. 시간은 2-5분 가
help.cloudtype.io
위의 링크에서 알려준 것처럼 설정하면 서버 레포지토리에 push할 때마다 클라우드타입 서버배포가 자동화로 이루어진다.