https://soohyun6879.tistory.com/174
이전 포스팅에서는 로그인을 구현해보았는데 이번 포스팅에서는 이미지 업로드, 게시물 업로드, 팔로잉, 해시태그 검색 기능을 만들어보겠습니다!
1. 이미지 업로드, 게시글 업로드
게시물을 작성할 때 이미지도 같이 업로드할 수 있습니다. 이미지를 업로드 하기 위해 multer 모듈을 사용하겠습니다. 먼저 multer 를 설치합니다.
npm install multer
posts 라우터를 작성하겠습니다. routes 폴더 안에 post.js 파일을 만듭니다. POST /post/img 는 이미지 업로드 라우터입니다. 이미지를 어디에 어떤 이름으로 저장할지 설정한 multer 객체를 만든 후 이미지를 업로드합니다. POST /post 는 게시글 업로드를 처리하는 라우터입니다. 이미지를 업로드하면 req.body.url 로 이미지 주소가 전송됩니다. 게시글을 저장한 후에 해시태그를 정규표현식으로 추출합니다. 추출한 해시태그를 저장하는데 해시태그가 이미 존재하면 가져오고 해시태그가 존재하지 않으면 해시태그를 생성한 후 가져옵니다. 해시태그를 가져오면 결과값이 [모델, 생성여부] 로 반환됩니다.
// routes/post.js
const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const { Post, Hashtag } = require('../models');
const { isLoggedIn } = require('./middlewares');
const router = express.Router();
// uploads 폴더 없으면 생성
try {
fs.readdirSync('uploads');
} catch (error) {
console.error('uploads 폴더가 없어 uploads 폴더를 생성합니다.');
fs.mkdirSync('uploads');
}
const upload = multer({
storage: multer.diskStorage({ // 어디에 저장할지
destination(req, file, cb) {
cb(null, 'uploads/');
},
filename(req, file, cb) { // 어떤 이름으로 저장할지
const ext = path.extname(file.originalname);
cb(null, path.basename(file.originalname, ext) + Date.now() + ext);
},
}),
limits: { fileSize: 5 * 1024 * 1024 }, // 파일 크기 제한
});
// 이미지 업로드
router.post('/img', isLoggedIn, upload.single('img'), (req, res) => {
console.log(req.file);
res.json({ url: `/img/${req.file.filename}` });
});
// 게시글 업로드
const upload2 = multer();
router.post('/', isLoggedIn, upload2.none(), async (req, res, next) => {
try {
console.log(req.user);
const post = await Post.create({ // 게시글 저장
content: req.body.content,
img: req.body.url, // 업로드한 이미지 주소
UserId: req.user.id,
});
const hashtags = req.body.content.match(/#[^\s#]*/g); // 해시태그 추출
if (hashtags) { // 해시태그가 있다면
const result = await Promise.all( // [모델, 생성여부] 로 반환
hashtags.map(tag => {
return Hashtag.findOrCreate({ // 해시태그가 존재하면 가져오고 존재하지 않으면 생성한 후 가져옴
where: { title: tag.slice(1).toLowerCase() }, // 앞에 #을 떼고 소문자로 바꿈
})
}),
);
await post.addHashtags(result.map(r => r[0])); // 해시태그 모델들을 게시글과 연결
}
res.redirect('/');
} catch (error) {
console.error(error);
next(error);
}
});
module.exports = router;
routes 폴더의 page.js 파일을 수정합니다. 게시글 작성 기능이 추가되었으므로 메인 페이지 로딩 시 게시글을 함께 로딩하도록 하겠습니다.
const express = require('express');
const { isLoggedIn, isNotLoggedIn } = require('./middlewares');
const { Post, User, Hashtag } = require('../models');
const router = express.Router();
// .. 생략
// 게시글 조회
router.get('/', async (req, res, next) => {
try {
const posts = await Post.findAll({ // 모든 게시글을 최신순으로 조회
include: {
model: User,
attributes: ['id', 'nick'],
},
order: [['createdAt', 'DESC']],
});
res.render('main', {
title: 'NodeBird',
twits: posts,
});
} catch (err) {
console.error(err);
next(err);
}
});
module.exports = router;
2. 팔로잉
팔로잉 기능을 만들겠습니다. routes 폴더 안에 user.js 파일을 만듭니다. 주소의 :id 부분이 req.params.id 가 됩니다. 팔로우할 사용자를 조회한 후 사용자가 있다면 현재 로그인한 사용자와 관계를 지정합니다.
// routes/user.js
const express = require('express');
const { isLoggedIn } = require('./middlewares');
const User = require('../models/user');
const router = express.Router();
// 팔로잉
router.post('/:id/follow', isLoggedIn, async (req, res, next) => {
try {
const user = await User.findOne({ where: { id: req.user.id } }); // 팔로우할 사용자
if (user) { // 팔로우할 사용자가 있다면
await user.addFollowing(parseInt(req.params.id, 10)); // 현재 로그인한 사용자와 팔로우할 사용자 관계 지정
res.send('success');
} else {
res.status(404).send('no user');
}
} catch (error) {
console.error(error);
next(error);
}
});
module.exports = router;
3. 해시태그 검색
해시태그 검색 기능을 만들어보겠습니다. 메인페이지에서 검색할 수 있으므로 메인페이지인 page.js 를 수정하겠습니다. 입력된 해시태그 값이 있다면 그 해시태그가 DB에 저장되어 있는지 확인합니다. 저장된 해시태그가 있다면 해시태그와 연결된 모든 게시물을 조회한 후 게시글을 페이지에 렌더링합니다.
const express = require('express');
const { isLoggedIn, isNotLoggedIn } = require('./middlewares');
const { Post, User, Hashtag } = require('../models');
const router = express.Router();
// .. 생략
// 해시태그 검색
router.get('/hashtag', async (req, res, next) => {
const query = req.query.hashtag; // 해시태그 이름
if (!query) { // 입력된 해시태그 값이 없으면
return res.redirect('/');
}
try {
const hashtag = await Hashtag.findOne({ where: { title: query } }); // 해시태그 조회
let posts = [];
if (hashtag) { // 저장된 해시태그가 있다면
posts = await hashtag.getPosts({ include: [{ model: User }] }); // 해시태그와 연결된 모든 게시물 조회
}
return res.render('main', {
title: `${query} | NodeBird`,
twits: posts, // 게시글 렌더링
});
} catch (error) {
console.error(error);
return next(error);
}
});
module.exports = router;
콘솔에 npm start 를 입력한 후 웹페이지에서 로그인하면 다음과 같은 화면을 볼 수 있습니다!
'Back-end > Node.js' 카테고리의 다른 글
[Node.js] 웹 API 서버 만들기 (2) (0) | 2021.08.01 |
---|---|
[Node.js] 웹 API 서버 만들기 (1) (0) | 2021.07.30 |
[Node.js] 익스프레스로 SNS 서비스 만들기 (2) (0) | 2021.07.27 |
[Node.js] 익스프레스로 SNS 서비스 만들기 (1) (0) | 2021.07.25 |
[Node.js+MongoDB] 몽구스 (2) (Mongoose) (0) | 2021.07.23 |