[Node.js-05] Router, Middleware, AWS 배포

Comely·2025년 3월 12일

Node.js

목록 보기
5/14

API 라우팅 (Router 분리)

왜 분리하는가?

  • app.get(), app.post() 코드가 몇백개 쌓일 때 관리가 어려움
  • 관련 있는 API들을 파일별로 그룹화하여 가독성 향상

1. 라우터 파일 생성

디렉토리 구조:

routes/
  └── shop.js
server.js

2. 라우터 파일 작성

// routes/shop.js
const router = require('express').Router()

router.get('/shop/shirts', (요청, 응답) => {
   응답.send('셔츠 파는 페이지입니다')
})

router.get('/shop/pants', (요청, 응답) => {
   응답.send('바지 파는 페이지입니다')
})

module.exports = router

3. 메인 파일에서 연결

// server.js
app.use('/', require('./routes/shop.js'))

4. 공통 URL 단축

// routes/shop.js - URL에서 /shop 제거
router.get('/shirts', (요청, 응답) => {
   응답.send('셔츠 파는 페이지입니다')
})

// server.js - 공통 경로 지정
app.use('/shop', require('./routes/shop.js'))

DB 연결 분리

문제상황

라우터 파일에서 db 변수를 사용할 수 없음

해결방법: database.js 분리

// database.js
const { MongoClient } = require('mongodb')
const url = 'DB연결URL~~'
let connectDB = new MongoClient(url).connect()

module.exports = connectDB

각 파일에서 사용

// server.js
let connectDB = require('./database.js')

let db
connectDB.then((client) => {
  console.log('DB연결성공')
  db = client.db('forum')
  app.listen(process.env.PORT, () => {
    console.log('서버 실행중')
  })
}).catch((err) => {
  console.log(err)
})
// routes/shop.js
let connectDB = require('./../database.js')

let db
connectDB.then((client) => {
  console.log('DB연결성공')
  db = client.db('forum')
}).catch((err) => {
  console.log(err)
})

환경변수 (.env 파일)

설치 및 설정

npm install dotenv
// server.js 상단
require('dotenv').config()

.env 파일 생성

PORT=8080
DB_URL="mongodb+srv://codingapple1@저쩌구"
SECRET_KEY="암호화키"

사용법

// 코드에서 사용
app.listen(process.env.PORT)
const dbUrl = process.env.DB_URL

⚠️ 주의사항: .env 파일은 GitHub에 업로드하면 안됨!


미들웨어 (Middleware)

기본 개념

요청과 응답 사이에 실행되는 함수

기본 문법

function checkLogin(요청, 응답, next) {
  if (요청.user) {
    next() // 다음 단계로 진행
  } else {
    응답.send('로그인안했는데요?')
  }
}

// 특정 API에 적용
app.get('/protected', checkLogin, (요청, 응답) => {
  응답.send('보호된 페이지')
})

app.use()로 일괄 적용

// 모든 API에 적용
app.use(checkLogin)

// 특정 URL로 시작하는 API에만 적용
app.use('/admin', checkLogin)

// 여러 미들웨어 적용
app.get('/api', [middleware1, middleware2], (요청, 응답) => {
  // API 로직
})

라우터별 미들웨어

// routes/admin.js
router.use(checkLogin) // 이 라우터의 모든 API에 적용

실용 예제

// 로그 출력 미들웨어
app.use('/list', (요청, 응답, next) => {
  console.log(new Date())
  next()
})

// 입력값 검증 미들웨어
function validateInput(요청, 응답, next) {
  if (요청.body.username == '' || 요청.body.password == '') {
    응답.send('입력값이 비어있습니다')
  } else {
    next()
  }
}

AWS Elastic Beanstalk 배포

사전 준비

1. MongoDB 설정

  • Network Access에서 접속 가능 IP를 0.0.0.0으로 설정 (모든 IP 허용)

2. 프로젝트 압축

  • node_modules 폴더 제외하고 프로젝트를 .zip으로 압축

3. AWS 계정 준비

  • 카드 등록 (1년 무료 서비스 이용)
  • 지역을 '서울'로 설정

배포 과정

1. IAM 역할 생성

AWS 콘솔 → IAM → 역할 생성

2. Elastic Beanstalk 설정

  1. 애플리케이션 설정

    • 애플리케이션 이름: 자유 작명
    • 플랫폼: Node.js 18 (사용 중인 버전)
    • 프리셋: 단일 인스턴스
  2. 코드 업로드

    • 소스코드 zip 파일 업로드
    • 버전 레이블 설정
  3. 인스턴스 설정

    • 루트볼륨: gp3 또는 범용3
    • 인스턴스 타입: t2.micro 또는 t3.micro (프리티어)

3. 환경변수 설정

배포 후 구성 메뉴에서 환경변수 추가 가능

주요 메뉴 설명

  • 구성: 환경 설정 변경
  • 로그: 터미널 로그 확인 (에러 디버깅용)
  • 상태: 인스턴스 관리 (재부팅, 중지)
  • 모니터링: 자동 모니터링 (400, 500 에러 알림)

업데이트 방법

"업로드 및 배포" 버튼으로 새 코드 zip 파일 업로드


이미지 업로드 (S3 연동)

1. 프론트엔드 설정

<form action="/add" method="POST" enctype="multipart/form-data">
  <input type="file" name="img1" accept="image/*">
  <input name="title">
  <input name="content">
  <button type="submit">전송</button>
</form>

2. 라이브러리 설치

npm install multer multer-s3 @aws-sdk/client-s3

3. S3 설정

const { S3Client } = require('@aws-sdk/client-s3')
const multer = require('multer')
const multerS3 = require('multer-s3')

const s3 = new S3Client({
  region: 'ap-northeast-2',
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY,
    secretAccessKey: process.env.AWS_SECRET_KEY
  }
})

const upload = multer({
  storage: multerS3({
    s3: s3,
    bucket: '버킷이름',
    key: function (요청, file, cb) {
      cb(null, Date.now().toString()) // 파일명 중복 방지
    }
  })
})

4. API에 적용

app.post('/add', upload.single('img1'), async (요청, 응답) => {
  console.log(요청.file) // 업로드된 파일 정보
  
  await db.collection('post').insertOne({
    title: 요청.body.title,
    content: 요청.body.content,
    img: 요청.file.location // S3 URL
  })
  
  응답.redirect('/list')
})

5. 에러 처리

app.post('/add', (요청, 응답) => {
  upload.single('img1')(요청, 응답, (err) => {
    if (err) return 응답.send('업로드 에러')
    
    // 업로드 성공시 로직
    // DB에 저장 등...
  })
})

6. 여러 이미지 업로드

<input type="file" name="images" multiple>
upload.array('images', 5) // 최대 5개 파일

자주 발생하는 에러와 해결책

배포 에러

  • HTTP 4xx 에러: 메인페이지 접속 불가, DB 연결 확인
  • npm ENOMEM: 메모리 부족, t2.small 이상 사용
  • instance profile 에러: IAM 역할 재생성
  • HTTP 5xx 에러: 로그 메뉴에서 상세 에러 확인

라우터 에러

  • 404 에러: URL 경로 확인, app.use() 순서 확인
  • DB 접속 에러: database.js 경로 확인

보안 팁

  • .env 파일 GitHub 업로드 금지
  • AWS 키는 환경변수로 관리
  • S3 버킷 권한 최소화
  • 프로덕션에서는 특정 IP만 DB 접속 허용

실전 활용 체크리스트

개발 환경 설정

  • 환경변수 파일 생성 (.env)
  • 라우터별 파일 분리
  • 공통 미들웨어 설정
  • DB 연결 분리

배포 준비

  • MongoDB Network Access 설정
  • AWS 계정 및 카드 등록
  • 프로젝트 zip 압축 (node_modules 제외)
  • 환경변수 Production 설정

이미지 업로드

  • S3 버킷 생성
  • IAM 키 발급
  • multer 설정
  • 파일 타입 검증
profile
App, Web Developer

0개의 댓글