개인공부/Node.js

nodejs로 SNS 만들기 #4

psys 2022. 8. 15. 16:35
728x90

https://yeon960.tistory.com/272

 

nodejs로 SNS 만들기 #3

https://yeon960.tistory.com/271 nodejs로 SNS 만들기 #2 https://yeon960.tistory.com/270 nodejs로 SNS 만들기 #1 1. 프로젝트 세팅 시작 1. package.json 생성하기 $npm init 2. package.json 작성하기 { "nam..

yeon960.tistory.com

이전편(로그인 구현)은 요기👆


Multer 모듈로 이미지 업로드 구현하기

 

이미지는 보통 input[type=file] 태그와 함께 form태그를 통해 업로드 한다.

이때 form의 인코딩 타입은 multipart/form-data인 경우가 많다.

이런 형식의 데이터는 직접 처리가 힘들어 multipart처리용 모듈을 사용하는 것이 좋다.

 

대표적인 것은 Multer로 우리가 사용할 모듈이다.

 

현재 nodeInsta도 게시글 작성 폼의 enctype이 multipart-form이다.

 

그러므로 multer모듈을 설치해준다.

 

1. 모듈 설치하기

npm i multer

2. post라우터 작성

nodeInsta는 input 태그를 통해 이미지 업로드를 진행하고,

업로드 된 사진 주소를 다시 클라이언트에 알려줄 것이다.

 

게시글 저장 시, 이미지 데이터 대신 이미지 주소를 저장한다.

 

// routes/post.js

const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');

const { Post, Hashtag, User } = require('../models');
const { isLoggedIn } = require('./middlewares');

const router = express.Router();

fs.readdir('uploads', (error) => {
  if (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) + new Date().valueOf() + 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 {
    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 => 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;

현재 multer 모듈은 이미지를 서버 디스크에 저장한다.

이 방식으로 저장하면 간단하지만, 서버에 문제 발생 시 이미지가 날아가 버릴 수 있다.

따라서 aws s3나 cloud storage같은 정적 파일 제공 서비스를 사용해 이미지를 따로 저장하고 제공하는 것이 좋다.

 

3. 이미지 업로드 기능

//routes/page.js
const express = require('express');
const { isLoggedIn, isNotLoggedIn } = require('./middlewares');
const { Post, User } = require('../models');

const router = express.Router();

router.get('/profile', isLoggedIn, (req, res) => {
  res.render('profile', { title: '내 정보 - NodeBird', user: req.user });
});

router.get('/join', isNotLoggedIn, (req, res) => {
  res.render('join', {
    title: '회원가입 - NodeBird',
    user: req.user,
    joinError: req.flash('joinError'),
  });
});

router.get('/', (req, res, next) => {
  Post.findAll({
    include: {
      model: User,
      attributes: ['id', 'nick'],
    },
    order: [['createdAt', 'DESC']],
  })
    .then((posts) => {
      res.render('main', {
        title: 'NodeBird',
        twits: posts,
        user: req.user,
        loginError: req.flash('loginError'),
      });
    })
    .catch((error) => {
      console.error(error);
      next(error);
    });
});

module.exports = router;


다음편(검색과 팔로잉 기능)은 요기👇