티스토리 뷰
모놀리식(Monolithic)에서 마이크로서비스(Microservices) 로이 전환 배경과 방법을 간단한 예제를 통해 알아보겠습니다.
1. 변화 배경
- 모놀리식 아키텍처
하나의 코드베이스로 모든 기능(사용자 관리, 결제, 주문 등)을 구현하는 방식. 배포 및 유지보수가 단순하지만, 규모가 커질수록 코드 복잡성 증가와 확장성 문제 발생. - 마이크로서비스 아키텍처
각 기능(서비스)을 독립된 작은 서비스로 나누는 방식. 서비스 간 느슨한 결합과 독립적 배포가 가능하며, 클라우드 환경에서 확장성과 신뢰성을 높일 수 있음.
2. 비교
항목 | 모놀리식 | 마이크로서비스 |
배포 | 전체 애플리케이션 한 번에 배포 | 각 서비스 독립적으로 배포 가능 |
확장성 | 전체 시스템을 확장해야 함 | 필요한 서비스만 개별 확장 가능 |
기술 스택 | 단일 기술 사용 | 각 서비스별 다양한 기술 스택 사용 가능 |
장애 영향 | 전체 시스템 다운 | 개별 서비스만 다운 |
개발/운영 팀 구조 | 단일 팀 중심 | 서비스별 독립 팀 |
3. 모놀리식 예제
하나의 애플리케이션에서 사용자 관리와 주문 기능을 처리
# 설치 확인
node -v
npm -v
# 디렉토리 이동 후, Express 설치
npm init -y
npm install express
npm install express-http-proxy
# 실행 방법
node app.js
# 프로젝트 구조
ChangeMSA.
├─Microservies
│ gateway.js
│ order-service.js
│ user-service.js
├─Monolithic
│ app.js
│
└─node_modules
└─package-lock.json
└─package.json
- 예제는 Node.js 로 작성하였으므로 nodejs 가 설치되어 있어야 합니다.
3.1. 소스 작성
- Monolithic/app.js
// app.js
const express = require('express');
const app = express();
app.use(express.json());
// 사용자 관리 API
// 모든 사용자 조회 (optional: 쿼리 파라미터 사용)
app.get('/users', (req, res) => {
const { name, age } = req.query;
if (name || age) {
res.send(`Filter users by name: ${name || 'N/A'}, age: ${age || 'N/A'}`);
} else {
res.send('Get all users');
}
});
// 특정 사용자 조회 (경로 파라미터 사용)
app.get('/users/:id', (req, res) => {
const { id } = req.params;
res.send(`Get user with ID: ${id}`);
});
// 사용자 생성 (JSON Body 사용)
app.post('/users', (req, res) => {
const { name, age } = req.body;
res.send(`Create a user with name: ${name}, age: ${age}`);
});
// 주문 관리 API
// 모든 주문 조회
app.get('/orders', (req, res) => {
const { status } = req.query;
if (status) {
res.send(`Filter orders by status: ${status}`);
} else {
res.send('Get all orders');
}
});
// 특정 주문 조회
app.get('/orders/:id', (req, res) => {
const { id } = req.params;
res.send(`Get order with ID: ${id}`);
});
// 주문 생성
app.post('/orders', (req, res) => {
const { product, quantity } = req.body;
res.send(`Create an order for product: ${product}, quantity: ${quantity}`);
});
app.listen(3000, () => console.log('Monolithic app running on port 3000'));
3.2. 실행
node Monolithic/app.js
1. 모든 사용자 조회
curl "http://localhost:3000/users"
- 결과 : Get all users
2. 특정 사용자 조회
curl "http://localhost:3000/users/123"
- 결과 : Get user with ID: 123
3. 사용자 필터링 조회
curl "http://localhost:3000/users?name=Cha&age=31"
- 결과 : Filter users by name: Cha, age: 31
4. 새 사용자 생성
curl -X POST "http://localhost:3000/users" -H "Content-Type: application/json" -d "{\"name\":\"CYB\",\"age\":29}"
- 결과 : Create a user with name: CYB, age: 29
5. 주문 상태 필터링
curl "http://localhost:3000/orders?status=shipped"
- 결과 : Filter orders by status: shipped
6. 새 주문 생성
curl -X POST "http://localhost:3000/orders" -H "Content-Type: application/json" -d "{\"product\":\"Laptop\",\"quantity\":1}"
- 결과 : Create an order for product: Laptop, quantity: 1
4. MSA 예제
사용자 관리와 주문 관리를 각각 별도의 서비스로 분리하고, API Gateway 역할을 하는 서버를 추가로 구현합니다.
4.1. 사용자 서비스
- Microservices/user-service.js
const express = require('express');
const app = express();
app.use(express.json());
const users = [
{ id: 1, name: 'Alice', age: 28 },
{ id: 2, name: 'Bob', age: 32 },
];
app.get('/users', (req, res) => res.json(users)); // 모든 사용자 조회
app.post('/users', (req, res) => {
const user = { id: users.length + 1, ...req.body };
users.push(user);
res.status(201).json(user);
}); // 사용자 생성
app.listen(3001, () => console.log('User service running on port 3001'));
# 실행
node Microservices/user-service.js
4.2. 주문 서비스
- Microservices/order-service.js
const express = require('express');
const app = express();
app.use(express.json());
const orders = [
{ id: 1, userId: 1, item: 'Book', quantity: 2 },
{ id: 2, userId: 2, item: 'Laptop', quantity: 1 },
];
app.get('/orders', (req, res) => res.json(orders)); // 모든 주문 조회
app.post('/orders', (req, res) => {
const order = { id: orders.length + 1, ...req.body };
orders.push(order);
res.status(201).json(order);
}); // 주문 생성
app.listen(3002, () => console.log('Order service running on port 3002'));
# 실행
node Microservices/order-service.js
4.3. API Gateway
- Microservice/gateway.js
const express = require('express');
const httpProxy = require('express-http-proxy');
const app = express();
const userServiceProxy = httpProxy('http://localhost:3001', {
proxyReqPathResolver: (req) => {
return `/users${req.url}`; // 대상 서비스에 `/users`를 추가
}
});
const orderServiceProxy = httpProxy('http://localhost:3002', {
proxyReqPathResolver: (req) => {
return `/orders${req.url}`; // 대상 서비스에 `/orders`를 추가
}
});
// JSON 요청 본문 처리 미들웨어 추가
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// 사용자 서비스 라우팅
app.use('/users', (req, res, next) => {
userServiceProxy(req, res, next);
});
// 주문 서비스 라우팅
app.use('/orders', (req, res, next) => {
orderServiceProxy(req, res, next);
});
app.listen(3000, () => console.log('API Gateway running on port 3000'));
# 실행
node Microservices/gateway.js
4.4. 실행
1. 사용자 조회
curl http://localhost:3000/users
- 결과 : [{"id":1,"name":"Alice","age":28},{"id":2,"name":"Bob","age":32}]
2. 사용자 생성
curl -X POST http://localhost:3000/users -H "Content-Type: application/json" -d "{\"name\":\"Charlie\",\"age\":25}"
- 결과 : {"id":3,"name":"Charlie","age":25}
3. 주문 조회
curl http://localhost:3000/orders
- 결과 : [{"id":1,"userId":1,"item":"Book","quantity":2},{"id":2,"userId":2,"item":"Laptop","quantity":1}]
4. 주문 생성
curl -X POST http://localhost:3000/orders -H "Content-Type: application/json" -d "{\"userId\":1,\"item\":\"Phone\",\"quantity\":1}"
- 결과 : {"id":3,"userId":1,"item":"Phone","quantity":1}
5. 요약
- 모놀리식: 단일 애플리케이션 구조로 간단하지만 확장성에 한계.
- 마이크로서비스: 독립된 서비스를 구성하여 유연하고 확장 가능.
- 마이크로서비스의 도전 과제: 네트워크 통신, 데이터 분산, 서비스 간 조율 문제 등.
이를 해결하기 위해 API Gateway, 서비스 디스커버리, 컨테이너 오케스트레이션(Kubernetes) 등을 활용.
전체 소스는 Guthub 를 참고해 주세요.
감사합니다.
'프로그래밍 언어 > Node.js' 카테고리의 다른 글
[Node.js] 공휴일 데이터 DB 입력하기 (0) | 2024.05.13 |
---|
최근에 올라온 글
- Total
- Today
- Yesterday