REST API 서버 구축 단계별 튜토리얼 – 완성까지 한번에!
1. 프로젝트 소개 및 목표
🔗 관련 에러 해결 가이드
이 REST API 서버 구축 단계별 튜토리얼은 Node.js와 Express를 활용하여 실무에서 사용할 수 있는 RESTful API 서버를 처음부터 끝까지 만드는 과정을 다룹니다. 데이터베이스 연동, 인증 시스템, CRUD 작업, 에러 핸들링, 그리고 배포까지 전체 개발 사이클을 경험할 수 있습니다. 이 튜토리얼을 완료하면 실제 프로덕션 환경에서 동작하는 API 서버를 구축할 수 있는 능력을 갖추게 됩니다. 백엔드 개발의 핵심 개념을 이해하고, 포트폴리오에 추가할 수 있는 실전 프로젝트를 완성하는 것이 목표입니다.
2. 필요한 기술 스택
이 프로젝트를 진행하기 위해 필요한 기술 스택은 다음과 같습니다:
- Node.js (v18 이상): 서버 사이드 JavaScript 런타임
- Express.js: 웹 애플리케이션 프레임워크
- MongoDB & Mongoose: NoSQL 데이터베이스 및 ODM
- JWT (jsonwebtoken): 사용자 인증 토큰 생성
- bcrypt: 비밀번호 암호화
- dotenv: 환경 변수 관리
- express-validator: 입력 데이터 검증
- Jest & Supertest: 테스트 프레임워크
3. 프로젝트 셋업
먼저 프로젝트 디렉토리를 생성하고 필요한 패키지를 설치합니다.
# 프로젝트 디렉토리 생성
mkdir rest-api-tutorial
cd rest-api-tutorial
# package.json 초기화
npm init -y
# 필수 패키지 설치
npm install express mongoose dotenv bcrypt jsonwebtoken cors helmet express-validator
# 개발 의존성 패키지 설치
npm install --save-dev nodemon jest supertest
프로젝트 구조를 다음과 같이 설정합니다:
rest-api-tutorial/
├── src/
│ ├── config/
│ │ └── database.js
│ ├── models/
│ │ └── User.js
│ ├── routes/
│ │ ├── auth.js
│ │ └── users.js
│ ├── middleware/
│ │ ├── auth.js
│ │ └── errorHandler.js
│ ├── controllers/
│ │ ├── authController.js
│ │ └── userController.js
│ └── app.js
├── tests/
├── .env
├── .gitignore
├── server.js
└── package.json
4. 단계별 구현 과정
Step 1: 데이터베이스 연결 설정
MongoDB 연결을 위한 설정 파일을 작성합니다.
// src/config/database.js
const mongoose = require('mongoose');
const connectDB = async () => {
try {
await mongoose.connect(process.env.MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
console.log('MongoDB 연결 성공');
} catch (error) {
console.error('MongoDB 연결 실패:', error.message);
process.exit(1);
}
};
module.exports = connectDB;
Step 2: User 모델 생성
사용자 정보를 저장할 Mongoose 스키마를 정의합니다.
// src/models/User.js
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const userSchema = new mongoose.Schema({
username: {
type: String,
required: [true, '사용자명은 필수입니다'],
unique: true,
trim: true,
minlength: 3
},
email: {
type: String,
required: [true, '이메일은 필수입니다'],
unique: true,
lowercase: true,
match: [/^\S+@\S+\.\S+$/, '유효한 이메일을 입력해주세요']
},
password: {
type: String,
required: [true, '비밀번호는 필수입니다'],
minlength: 6
},
createdAt: {
type: Date,
default: Date.now
}
});
// 비밀번호 암호화 미들웨어
userSchema.pre('save', async function(next) {
if (!this.isModified('password')) return next();
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
next();
});
// 비밀번호 검증 메서드
userSchema.methods.comparePassword = async function(candidatePassword) {
return await bcrypt.compare(candidatePassword, this.password);
};
module.exports = mongoose.model('User', userSchema);
Step 3: 인증 미들웨어 구현
JWT 토큰을 검증하는 미들웨어를 작성합니다.
// src/middleware/auth.js
const jwt = require('jsonwebtoken');
const auth = async (req, res, next) => {
try {
const token = req.header('Authorization')?.replace('Bearer ', '');
if (!token) {
throw new Error();
}
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.userId = decoded.userId;
next();
} catch (error) {
res.status(401).json({ error: '인증이 필요합니다' });
}
};
module.exports = auth;
Step 4: 인증 컨트롤러 구현
회원가입과 로그인 로직을 처리하는 컨트롤러입니다.
// src/controllers/authController.js
const User = require('../models/User');
const jwt = require('jsonwebtoken');
exports.register = async (req, res) => {
try {
const { username, email, password } = req.body;
// 중복 체크
const existingUser = await User.findOne({ $or: [{ email }, { username }] });
if (existingUser) {
return res.status(400).json({ error: '이미 존재하는 사용자입니다' });
}
// 사용자 생성
const user = new User({ username, email, password });
await user.save();
// JWT 토큰 생성
const token = jwt.sign(
{ userId: user._id },
process.env.JWT_SECRET,
{ expiresIn: '7d' }
);
res.status(201).json({
message: '회원가입 성공',
token,
user: {
id: user._id,
username: user.username,
email: user.email
}
});
} catch (error) {
res.status(500).json({ error: error.message });
}
};
exports.login = async (req, res) => {
try {
const { email, password } = req.body;
// 사용자 찾기
const user = await User.findOne({ email });
if (!user) {
return res.status(401).json({ error: '이메일 또는 비밀번호가 올바르지 않습니다' });
}
// 비밀번호 검증
const isMatch = await user.comparePassword(password);
if (!isMatch) {
return res.status(401).json({ error: '이메일 또는 비밀번호가 올바르지 않습니다' });
}
// JWT 토큰 생성
const token = jwt.sign(
{ userId: user._id },
process.env.JWT_SECRET,
{ expiresIn: '7d' }
);
res.json({
message: '로그인 성공',
token,
user: {
id: user._id,
username: user.username,
email: user.email
}
});
} catch (error) {
res.status(500).json({ error: error.message });
}
};
Step 5: 라우트 설정
API 엔드포인트를 정의합니다.
// src/routes/auth.js
const express = require('express');
const router = express.Router();
const { body } = require('express-validator');
const authController = require('../controllers/authController');
router.post('/register',
[
body('username').trim().isLength({ min: 3 }).withMessage('사용자명은 3자 이상이어야 합니다'),
body('email').isEmail().withMessage('유효한 이메일을 입력해주세요'),
body('password').isLength({ min: 6 }).withMessage('비밀번호는 6자 이상이어야 합니다')
],
authController.register
);
router.post('/login',
[
body('email').isEmail().withMessage('유효한 이메일을 입력해주세요'),
body('password').notEmpty().withMessage('비밀번호를 입력해주세요')
],
authController.login
);
module.exports = router;
Step 6: Express 애플리케이션 설정
미들웨어와 라우트를 통합합니다.
// src/app.js
const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const authRoutes = require('./routes/auth');
const app = express();
// 보안 미들웨어
app.use(helmet());
app.use(cors());
// 요청 본문 파싱
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// 라우트
app.use('/api/auth', authRoutes);
// 404 핸들러
app.use((req, res) => {
res.status(404).json({ error: '요청한 리소스를 찾을 수 없습니다' });
});
// 에러 핸들러
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(err.status || 500).json({
error: err.message || '서버 오류가 발생했습니다'
});
});
module.exports = app;
Step 7: 서버 시작 파일
// server.js
require('dotenv').config();
const app = require('./src/app');
const connectDB = require('./src/config/database');
const PORT = process.env.PORT || 5000;
// 데이터베이스 연결
connectDB();
// 서버 시작
app.listen(PORT, () => {
console.log(`서버가 포트 ${PORT}에서 실행 중입니다`);
});
Step 8: 환경 변수 설정
# .env
MONGODB_URI=mongodb://localhost:27017/rest-api-tutorial
JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
PORT=5000
NODE_ENV=development
5. 테스트 및 배포
API 테스트 작성
Jest와 Supertest를 사용하여 API 엔드포인트를 테스트합니다.
// tests/auth.test.js
const request = require('supertest');
const app = require('../src/app');
const mongoose = require('mongoose');
const User = require('../src/models/User');
beforeAll(async () => {
await mongoose.connect(process.env.MONGODB_TEST_URI);
});
afterAll(async () => {
await User.deleteMany({});
await mongoose.connection.close();
});
describe('Auth API', () => {
it('POST /api/auth/register - 회원가입 성공', async () => {
const response = await request(app)
.post('/api/auth/register')
.send({
username: 'testuser',
email: '[email protected]',
password: 'password123'
});
expect(response.status).toBe(201);
expect(response.body).toHaveProperty('token');
expect(response.body.user.email).toBe('[email protected]');
});
it('POST /api/auth/login - 로그인 성공', async () => {
const response = await request(app)
.post('/api/auth/login')
.send({
email: '[email protected]',
password: 'password123'
});
expect(response.status).toBe(200);
expect(response.body).toHaveProperty('token');
});
});
배포 준비
프로덕션 환경에 배포하기 위한 설정을 추가합니다.
// package.json scripts
{
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js",
"test": "jest --watchAll --verbose"
}
}
배포 옵션:
- Heroku: 간단한 git push로 배포 가능
- AWS EC2: 더 많은 제어와 확장성 제공
- DigitalOcean: 비용 효율적인 VPS 옵션
- Vercel/Railway: 무료 티어와 자동 배포 지원
6. 마무리 및 확장 아이디어
이 REST API 서버 구축 단계별 튜토리얼을 통해 기본적인 인증 시스템을 갖춘 RESTful API 서버를 완성했습니다. 이제 프로젝트를 확장할 수 있는 아이디어를 소개합니다:
- 역할 기반 접근 제어(RBAC): 관리자, 일반 사용자 등 역할별 권한 관리
- 파일 업로드: Multer를 사용한 프로필 이미지 업로드
- 이메일 인증: Nodemailer로 회원가입 시 이메일 확인
- 비밀번호 재설정: 토큰 기반 비밀번호 복구 시스템
- Rate Limiting: express-rate-limit으로 API 호출 제한
- 로깅 시스템: Winston 또는 Morgan으로 상세한 로그 관리
- API 문서화: Swagger/OpenAPI로 자동 문서 생성
- Redis 캐싱: 자주 조회되는 데이터 캐싱으로 성능 향상
- 소셜 로그인: Passport.js로 Google, GitHub 로그인 통합
이 REST API 서버 구축 단계별 튜토리얼을 기반으로 실제 프로덕션 레벨의 API 서버를 개발할 수 있으며, 포트폴리오에 추가하여 백엔드 개발 역량을 증명할 수 있습니다. 계속해서 기능을 추가하고 최적화하면서 실무 경험을 쌓아보세요!
📚 함께 읽으면 좋은 글
REST API 서버 구축 단계별 튜토리얼 – 완성까지 한번에!
📅 2025. 10. 1.
🎯 REST API 서버 구축 단계별 튜토리얼
undefined 완벽 해결법 – 원인부터 예방까지
📅 2025. 9. 29.
🎯 undefined
FastAPI로 REST API 만들기 – 초보자도 쉽게 따라하는 완벽 가이드
📅 2025. 10. 1.
🎯 FastAPI로 REST API 만들기
React Context API 마스터하기 – 초보자도 쉽게 따라하는 완벽 가이드
📅 2025. 10. 1.
🎯 React Context API 마스터하기
Python 자동화 스크립트 작성하기 – 초보자도 쉽게 따라하는 완벽 가이드
📅 2025. 9. 30.
🎯 Python 자동화 스크립트 작성하기
💡 위 글들을 통해 더 깊이 있는 정보를 얻어보세요!
📢 이 글이 도움되셨나요? 공유해주세요!
여러분의 공유 한 번이 더 많은 사람들에게 도움이 됩니다 ✨
🔥 공유할 때마다 블로그 성장에 큰 힘이 됩니다! 감사합니다 🙏
💬 여러분의 소중한 의견을 들려주세요!
이 글을 읽고 새롭게 알게 된 정보가 있다면 공유해주세요!
⭐ 모든 댓글은 24시간 내에 답변드리며, 여러분의 의견이 다른 독자들에게 큰 도움이 됩니다!
🎯 건설적인 의견과 경험 공유를 환영합니다 ✨
🔔 블로그 구독하고 최신 글을 받아보세요!
🌟 프로젝트 아이디어부터 다양한 실생활 정보까지!
매일 새로운 유용한 콘텐츠를 만나보세요 ✨
📧 RSS 구독 | 🔖 북마크 추가 | 📱 모바일 앱 알림 설정
지금 구독하고 놓치는 정보 없이 업데이트 받아보세요!