API도 다 작성되어 이제 프론트와 연결하는 작업을 시작했다. 나 혼자서 짠 코드는 내가 구조와 원리를 파악하고 있어 어렵지 않지만, 정말 어려운 것은 남이 짠 코드를 이해하고 분석해서 오류를 수정하고 맞춰가는 과정임을 깨닫고 있다. 서로가 생각하는 목적과 그 목적을 이루는 방식은 다르기 때문에, 그 차이를 빠르게 인지하고 괴리를 좁히는게 중요하다.
예를 들어, 산책로를 추가하는 페이지에서 DB에 추가하길 요청하는 정보는 5개의 좌표들, 포스트의 제목, 후기를 포함하고, 이미지 파일을 업로드할지 선택할 수 있다. 이런 것들을 고려하여 POST /trails
를 수정하여 내부에서 이미지 업로드를 하는 작업을 포함시키기로 하였다.
그러기위해 먼저 ./routes/trails
에서 이미지 파일 업로드를 도와주는 multer
모듈을 사용하고, /uploads
를 추가해주었다.
const express = require('express');
//multer 추가
const multer = require('multer');
const path = require('path');
const router = express.Router();
const upload = multer({
storage: multer.diskStorage({
// set a localstorage destination
destination: (req, file, cb) => {
cb(null, 'uploads/');
},
// convert a file name
filename: (req, file, cb) => {
cb(null, new Date().valueOf() + path.extname(file.originalname));
},
}),
});
const trailsController = require('../controllers/trails/trails');
const tagController = require('../controllers/trails/tag');
const trailIdController = require('../controllers/trails/trailId');
const commentController = require('../controllers/trails/comment');
// const imageController = require('../controllers/trails/image'); -> 변경 전
router.get('/', trailsController.get);
// router.post('/', trailsController.post); -> 변경 전
router.post('/', upload.single('img'), trailsController.post); // 변경 후
router.get('/:tag', tagController);
router.get('/:tag/:trailId', trailIdController);
router.post('/:tag/:trailId/comment', commentController);
// router.post('/:tag/:trailId/image', upload.single('img'), imageController); -> 변경 전
module.exports = router;
그리고 아래는 변경한 POST /trails
이다.
post: (req, res) => {
// console.log('req.file is ??? ', req.file);
// console.log('req.body is ??? ', req.body);
const token = req.cookies.user;
// verify token -> 없으면 401
jwt.verify(token, secretObj.secret, async (err, decoded) => {
// 토큰이 존재한다면,
if (decoded) {
const {
tag, title, review, adminDistrict, newLocations,
} = req.body;
// 이미지 파일을 추가했는지 확인
let createImageResult;
// 요청에서 이미지 파일이 추가되었다면 DB에 추가.
if (req.file !== undefined) {
createImageResult = await images.create({
fileName: req.file.filename,
filePath: req.file.path,
});
}
// locations 테이블에 좌표들 추가. 이 때 들어온 값이 JSON이므로 parse하여 각 요소별로 나누어 다시 stringify 한다.
const createLocation = await locations
.create({
location1: JSON.stringify(JSON.parse(newLocations)[0]),
location2: JSON.stringify(JSON.parse(newLocations)[1]),
location3: JSON.stringify(JSON.parse(newLocations)[2]),
location4: JSON.stringify(JSON.parse(newLocations)[3]),
location5: JSON.stringify(JSON.parse(newLocations)[4]),
})
.catch((error) => {
console.log(error);
res.sendStatus(500);
});
// categories 테이블에 tag를 찾거나 없으면 추가.
const [createCategory, created] = await categories
.findOrCreate({
where: {
tag: tag,
},
})
.catch((error) => {
console.log(error);
res.sendStatus(500);
});
// trails에 위 테이블들에서 추가한 값들의 id를 Foreign Key로 가져와 추가.
const createTrail = await trails
.create({
userId: decoded.userId,
locationId: createLocation.dataValues.id,
categoryId: createCategory.dataValues.id || created.dataValues.id, // 태그를 검색하거나 추가했는지에 따른 값들
imageId: createImageResult !== undefined ? createImageResult.dataValues.id : null, // 이미지 파일의 유무에 따른 값들
title: title,
review: review,
adminDistrict: adminDistrict,
})
.catch((error) => {
console.log(error);
res.sendStatus(500);
});
// send trails
res.status(200).json({ trails: createTrail.dataValues });
} else {
res.sendStatus(401);
}
});
}
코드를 수정하고 나서 좌표들을 포함한 여러 정보들을 성공적으로 불러올 수 있었다. 내일은 프론트에서 일어나는 화면 render문제와 각 산책로 포스트에 속하는 댓글들을 추가하고 나타내는 작업을 하게 된다. 시간이 많지 않지만 하나하나 해결해나가는게 재미있다. 내일을 위해 오늘 포스트를 마친다.