Node.js에서 마이크로서비스 구현을 위한 단계별 튜토리얼

마이크로서비스 아키텍처는 애플리케이션을 작은 독립적인 서비스로 나누어 개발 및 배포하는 방식입니다. Node.js는 비동기 I/O와 경량화된 이벤트 기반 아키텍처 덕분에 마이크로서비스를 구축하는 데 적합한 플랫폼입니다. 이번 포스팅에서는 Node.js를 이용해 마이크로서비스를 구현하는 방법을 단계별로 설명하겠습니다.

1단계: 프로젝트 설정

먼저, Node.js가 설치되어 있는지 확인하세요. 그런 다음, 새로운 프로젝트를 시작합니다. 아래 명령어를 사용해 새로운 디렉토리를 만들고 초기화합니다.

mkdir my-microservice
cd my-microservice
npm init -y

이제 Express.js를 설치합니다. Express는 간단하게 RESTful API를 구축하기에 적합한 웹 프레임워크입니다.

npm install express

2단계: 기본 서버 구현

이제 기본적인 웹 서버를 설정합니다. index.js라는 파일을 만들고 다음 코드를 추가하세요.

const express = require('express');
const app = express();
const PORT = 3000;

app.use(express.json());

app.get('/', (req, res) => {
    res.send('Hello, Microservices!');
});

app.listen(PORT, () => {
    console.log(Server is running on http://localhost:${PORT});
});

이제 서버를 실행해보세요.

node index.js

브라우저에서 http://localhost:3000에 접속하면 "Hello, Microservices!"라는 메시지를 볼 수 있습니다.

3단계: 서비스 분리

마이크로서비스 아키텍처의 핵심은 각 서비스를 독립적으로 관리하는 것입니다. 예를 들어, 사용자 관리 서비스와 주문 관리 서비스를 분리해보겠습니다. 다음과 같은 디렉토리 구조를 만들어 주세요.

my-microservice/
│
├── user-service/
│   └── index.js
│
└── order-service/
    └── index.js
user-service/index.js 파일을 다음과 같이 작성합니다.
const express = require('express');
const app = express();
const PORT = 3001;

app.use(express.json());

app.get('/users', (req, res) => {
    res.json([{ id: 1, name: 'John Doe' }]);
});

app.listen(PORT, () => {
    console.log(User Service is running on http://localhost:${PORT});
});
order-service/index.js 파일도 다음과 같이 작성합니다.
const express = require('express');
const app = express();
const PORT = 3002;

app.use(express.json());

app.get('/orders', (req, res) => {
    res.json([{ id: 1, item: 'Laptop', quantity: 1 }]);
});

app.listen(PORT, () => {
    console.log(Order Service is running on http://localhost:${PORT});
});

이제 각 서비스를 실행해보세요.

node user-service/index.js
node order-service/index.js

각 서비스에 접근하기 위해 브라우저에서 http://localhost:3001/users와 http://localhost:3002/orders에 접속합니다.

4단계: 서비스 간 통신

마이크로서비스 간의 통신은 REST API 호출을 통해 이루어집니다. 예를 들어, 주문 서비스에서 사용자 정보를 조회해야 할 경우, 사용자 서비스의 API를 호출해야 합니다.

order-service/index.js 파일에 Axios를 추가하여 사용자 서비스에 요청하는 API를 작성해봅니다. 먼저 Axios를 설치합니다.
npm install axios

이제 order-service/index.js를 수정합니다.

const express = require('express');
const axios = require('axios');
const app = express();
const PORT = 3002;

app.use(express.json());

app.get('/orders', async (req, res) => {
    try {
        const userResponse = await axios.get('http://localhost:3001/users');
        res.json({
            order: { id: 1, item: 'Laptop', quantity: 1 },
            user: userResponse.data[0],
        });
    } catch (error) {
        res.status(500).send('Error retrieving user data');
    }
});

app.listen(PORT, () => {
    console.log(Order Service is running on http://localhost:${PORT});
});

이제 http://localhost:3002/orders에 접속하면 주문 데이터와 함께 사용자 데이터도 포함된 JSON 응답을 받을 수 있습니다.

5단계: 도커를 통한 배포

마이크로서비스를 배포하기 위해 도커를 사용할 수 있습니다. 먼저 도커가 설치되어 있어야 하며, 각 서비스에 대한 Dockerfile을 생성합니다.

user-service/Dockerfile:
FROM node:14

WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["node", "index.js"]
EXPOSE 3001
order-service/Dockerfile:
FROM node:14

WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["node", "index.js"]
EXPOSE 3002

이제 각 서비스의 디렉토리에서 도커 이미지를 빌드하고 실행합니다.

cd user-service
docker build -t user-service .
docker run -p 3001:3001 user-service

# 주문 서비스
cd ../order-service
docker build -t order-service .
docker run -p 3002:3002 order-service

이제 도커를 통해 각 서비스가 실행되고 있습니다. 마이크로서비스 아키텍처의 장점을 최대한 활용할 수 있습니다.

마무리

Node.js에서 마이크로서비스를 구현하는 것은 매우 직관적이며 유연합니다. 이번 튜토리얼을 통해 기본적인 마이크로서비스 구조를 이해하고, 각 서비스 간의 통신을 구현해보았습니다. 마이크로서비스 아키텍처는 확장성과 유지보수성을 높여주는 좋은 방법이지만, 서비스 간의 통신 및 데이터 관리에 대한 고민도 필요합니다. 지속적으로 발전하는 마이크로서비스 아키텍처에 대해 더 많은 정보를 탐구해보시기 바랍니다.