티스토리 뷰

모놀리식(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