해결한 지금 상황에서 봤을 땐, 되게 별거 아닌데 해결하기 전까지는 답을 모르겠어서 프론트 하는 분과 같이 너무 많이 헤맸다🥹🥹
그리고 이제와 떠오른건 EC2를 왜 안썼을까 ... 라는 생각..
- 클라이언트측 요청: 여러가지 문자열 데이터값+ 이미지 파일 (multipart/form-data)
-> 데이터 값(string):userId
,petName
, 이미지(file):petImg
- 서버측 행위: 요청값들을 DB에 저장
- 서버측 응답:
status
값 전송 (success
orfalse
)
우선 이미지를 받으려면, 아래와 같이 upload.single('~')
을 이용해야한다. 여기서 petImg
는 클라이언트 측에서 이미지를 받을 때 통일시켜야 하는 변수의 값이다. 이 변수명을 img
로 지정한다면, 클라이언트에서도 img
라는 이름으로 이미지 파일을 보내줘야한다.
petRouter.post('/register', upload.single('petImg'), petController.petRegister)
userId
와 petName
값을 클라이언트 측에서 받는건 굉장히 단순하다.
var userId = req.body.userId;
var petName = req.body.petName;
파일도 마찬가지로, 문자열 형식인 데이터를 받는 것과 동일하다.
const file = req.file;
- 클라이언트측 요청:
userId
값에 따른petName
과 해당 pet의 이미지(petImg
)- 서버측 응답: 요청받은
userId
를 통해 DB 조회하여 해당 값 전달
여기서 내가 헤맸던 이유는 두가지다.
- json형식의 데이터값과 file 형식의 이미지값을 같이 어떻게 보내야할지
- 이미지 값을 어떤식으로 DB에 넣어야 조회했을 때 온전히 이미지 값을 확인할 수 있을지
- 결과적으로 이 2번 문제를 해결하는게 핵심이다
처음에 시도했던 방법은, json형식의 문자열 데이터와 file형식의 이미지 데이터를 같이 보내려고 했다. 하지만, 기본적으로 res.json
과 res.send
는 같이 진행될 수 없도록 되어있다. 반환하는 것이 두 개로 이루어지기 때문이다.
원래 api
가 달랐다면, 문자열 데이터는 아래와 같이 단순히 res.json
을 이용하고,
res.json({
userId: userId,
petName: petName
})
이미지 데이터는 res.send
를 이용하여 전송하면 된다.
res.send(file)
근데 이 두 가지가 한꺼번에 진행될 수 없으므로, 다른 방법을 이용하였다.
2번 문제를 해결하는 방법은 다음과 같다.
- 우선, 받은 이미지 값을 base64로 인코딩한다.
- 인코딩된 이미지 값(문자열)을 다른 데이터 값들과 같이 DB에 저장한다.
- 프론트측에서는 이 인코딩된 이미지 값을 받으면, 디코딩하여 UI에 띄울 수 있도록 한다.
내가 헤맸던 이유는, 인코딩된 이미지를 프론트측에서 풀어서 볼 수 있다는걸 몰랐기 때문이다. 그래서 아예 이 생각을 하지 못했는데.. 이제라도 알았으니 오히려 다행이다.
정리하면 아래와 같이 진행되며 처리 과정이 두 가지로 나뉜다.
클라이언트에서 전송한 값 (문자열+이미지)을 DB에 저장
exports.petRegister = (req, res) => {
// 클라이언트측에서 보내는 데이터 받기
var userId = req.body.userId;
var petName = req.body.petName;
var file = req.file; //이미지
var imgName = file.filename;
// 이미지 저장할 위치 지정
var filePath = path.join(__dirname, '..', 'main', 'uploads', imgName);
var imageBuffer = fs.readFileSync(filePath);
// base64로 이미지 인코딩
var encode = Buffer.from(imageBuffer).toString('base64');
// DB table에 userId, petName, petImg(인코딩된 값)을 Insert
db.query('INSERT INTO pet (petIdx, userId, petName, petImg) VALUES (?,?,?)', [null, userId, petName, encode], function (error, data) {
// 오류 발생
if (error) {
return res.status(500).json({ error: error.message });
}
// 정상적으로 등록 성공
res.json({
status: "success"
})
})
}
DB에 저장된 값을 조회
exports.petMain = (req, res) => {
var userId = req.body.userId;
// userId 값에 따른 데이터 조회
db.query('SELECT userId, petName, CONVERT(petImg USING utf8) as petImg FROM pet WHERE userId = ?', [userId], function (error, result) {
if (error) {
return res.status(500).json({ error: error.message });
}
res.json({
status: "success",
result: result
})
})
}
postman 결과
프론트측에서 받고 처리하는 부분은 내가 하는 부분이 아니라 잘 모르겠지만, Nodejs는 이런식으로 값을 받고 전달한다.
(프론트 맡은 분이 작성하신 글은 아래에 첨부해두었다)