운영배포설정

broccoli·2021년 5월 12일
1

deployment

목록 보기
2/3
post-thumbnail

next.jsexpress.js의 운영배포설정 및 과정을 정리해보자.

next.js

package.json에 빌드 스크립트를 작성하고 빌드를 해보자.

 "prestart": "NODE_ENV=production next build",
 "start": "NODE_ENV=production next start"

빌드를 하면 .next 폴더가 생성되는데 이쪽에 생성된 파일들을 next start시에 읽는다.

.next 폴더는 .gitignore에 포함시킨다.

1.redux사용시 redux상태 가리기

만약 redux를 사용시에는 운영환경일때 redux상태가 보이지 않도록 하는 부분을 추가해준다.

아래 예는 saga를 같이 사용한 경우의 예이다.

import { createStore, applyMiddleware, compose } from 'redux'
import { createWrapper } from 'next-redux-wrapper'
import { composeWithDevTools } from 'redux-devtools-extension'
import createSagaMiddleware from 'redux-saga'
import rootReducer from '../reducers/rootReducer'
import rootSaga from '../sagas'

const makeStore = () => {
  const sagaMiddleWare = createSagaMiddleware()
  const middlewares = [sagaMiddleWare]
  const enhancer =
    process.env.NODE_ENV === 'production'
      ? compose(applyMiddleware(...middlewares))
      : composeWithDevTools(applyMiddleware(...middlewares))
  const store = createStore(rootReducer, enhancer)
  store.sagaTask = sagaMiddleWare.run(rootSaga)
  return store
}

const wrapper = createWrapper(makeStore, {
  debug: process.env.NODE_ENV !== 'production'
})

export default wrapper

2. source-map 가리기

next.config.js는 내부적으로 webpack설정이 디폴트로 되어있는데 커스텀도 가능하다.

운영모드일때는 webpack devtool 모드를 hidden-source-map을 해줘야지 소스를 숨길수 있다.

module.exports = {
  compress: true,
  ...
  webpack(config, { webpack }) {
    const prod = process.env.NODE_ENV === 'production'
    return {
      ...config,
      mode: prod ? 'production' : 'development',
      devtool: prod ? 'hidden-source-map' : 'eval',
      plugins: [...config.plugins]
    }
  }
}

express.js

  1. morgan
  2. sessionOption
  3. .env값 설정
  4. winston 사용하기
  5. pm2 사용하기
  6. redis 사용하기
  7. etc

1. morgan

logger middleware for node.js 다른 logger 모듈을 사용해도 무방하다.

const morgan = require('morgan')
app.use(morgan(<format>, <option>))

✅ production

confined : production환경에 적합한 format

✅ development

dev : development환경에 적합한 format

2. sessionOption

express-session사용시 설정을 환경에 따라 달리하자

const session = require('express-session')
app.use(session(<sessionOption>))

✅ production

const sessionProdOpt = {
  resave: false,
  saveUninitialized: false,
  secret: process.env.SECRET,
  cookie: {
    httpOnly: true,
    secure: true
  }
  proxy: true,
}

✅ development

const sessionDevOpt = {
  resave: false,
  saveUninitialized: false,
  secret: process.env.SECRET,
  cookie: {
    httpOnly: true,
    secure: false
  }
}

ℹ️ session옵션과 쿠키옵션의 대한 설명 링크

3. .env 설정값 변경

✅ DB CONNECTION

sequelize를 기준으로 DB설정 값을 변경한다고 하자
config.jsusername, password, database, host를 환경별로 .env에 설정해준다.

require('dotenv').config()

module.exports = {
  development: {
    username: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    database: process.env.DB,
    host: process.env.DB_HOST,
    port: process.env.DB_PORT,
    dialect: 'mysql'
  },
  test: {
    username: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    database: process.env.DB,
    host: process.env.DB_HOST,
    port: process.env.DB_PORT,
    dialect: 'mysql'
  },
  production: {
    username: process.env.DB_PROD_USER,
    password: process.env.DB_PROD_PASSWORD,
    database: process.env.DB_PROD,
    host: process.env.DB_PROD_HOST,
    port: process.env.DB_PORT,
    dialect: 'mysql',
    logging: false // sql문이 로깅되지 않는다.
  }
}

✅ PORT 도 .env로 설정하자

app.listen(process.env.PORT, () => {
  logger.info(`server on ${process.env.PORT}`)
})

ℹ️ 백엔드 서비스를 heroku로 테스팅한다고 할 때 참고링크

4. winston 사용하기

앞서 morgan이라는 logger를 사용했는데 winston을 사용하는 이유는 두 모듈에 사용목적이 다르기 때문이다. morganhttp요청과 응답을 format화 하여 http 관련 로깅을 확인하는데 좋다. 하지만 이런 로깅을 파일이나 db에 남겨 놓지 않는다면 문제발생시 에러추적을 하기 어렵다. 이럴때 winston을 사용하여 logging을 저장해 둘 수 있다.

AWS, GCP 같은 클라우드를 사용시에는 보통 console.log를 사용해도 로깅이 파일이나 디비에 저장되지만, 클라우드를 사용하지 않는 경우에는 console.log가 파일이나 디비에 남겨지지 않을 수 있다. 따라서 winston을 사용해서 파일이나 db에 logging을 남길 수 있다.

winston사용예 링크

5. pm2 사용하기

  • 사용하면 좋은 점의 대한 관련링크
  • heroku에서 활용시 관련링크

6. Redis 사용하기

세션store를 사용해야지 서버가 재시작 되더라도 세션이 유지된다. 따라서 운영시에는 메모리스토어를 사용하지 않는데 Redis를 한번 사용해보자.

6-1. Redis DB 사용법

  • https://app.redislabs.com/ 회원가입
  • 1개의 db는 무료로 사용가능함. 1개의 db 만들고, host, port, password를 확인하여 .env추가
  • 아래와 같이 redisClient를 만들고 app.jsstoreclient로 연결해준다.
//redisClient.js
const redis = require('redis')
const Logger = require('./logger')
require('dotenv').config()

const redisClient = redis.createClient({
  host: process.env.REDIS_HOST,
  port: process.env.REDIS_PORT,
  password: process.env.REDIS_PASSWORD
})
redisClient.unref()
redisClient.on('ready', () => {
  Logger.debug('✅ redis is ready')
})
redisClient.on('connect', () => {
  Logger.debug('✅ redis is connected')
})
redisClient.on('reconnecting', () => {
  Logger.debug('✅ redis is reconnecting')
})
redisClient.on('end', () => {
  Logger.debug('✅ redis is end')
})
redisClient.on('error', (error) => {
  Logger.error(error)
})

module.exports = redisClient

//app.js
const redisClient = require('./redisClient')
store: new RedisStore({ client: redisClient })

99. etc

기타사항으로 조치해줄 것들

99-1 vulnerabilities 찾고 고치기

npm audit
//if any
npm audit fix

The audit command submits a description of the dependencies configured in your project to your default registry and asks for a report of known vulnerabilities.

99-2. helmat

Helmet helps you secure your Express apps by setting various HTTP headers. It's not a silver bullet, but it can help!

위에 설명은 helmat 패키지를 소개해주는 말이다. 웹은 보안에 취약하기 때문에 보안에 도움이 될만한 패키지는 운영배포시에 꼭 설치해주자.

99-3. hpp

Express middleware to protect against HTTP Parameter Pollution attacks

위에 설명은 hpp 패키지를 소개해주는 말이다. 웹은 보안에 취약하기 때문에 보안에 도움이 될만한 패키지는 운영배포시에 꼭 설치해주자.

참고링크

profile
🌃브로콜리한 개발자🌟

0개의 댓글