MSA(Microservices Architecture) 이해하기: HTTP와 gRPC를 통한 통신 방식

2024. 11. 18. 00:25 개발 이야기/아키텍처

현대 소프트웨어 개발에서는 시스템을 작은 서비스 단위로 나누는 MSA(Microservices Architecture)가 점점 더 인기를 끌고 있습니다. 이를 통해 개발팀은 독립적으로 배포 가능한 서비스들을 구축하고, 각각의 서비스가 독립적으로 발전할 수 있게 합니다. 이번 포스팅에서는 MSA의 통신 방식, HTTP와 gRPC에 대해 살펴보고, 코드 레벨에서 어떻게 구현되는지에 대해 설명하겠습니다. 또한, 모놀리식 아키텍처와 비교하여 MSA의 장점도 살펴보겠습니다.

모놀리식 vs MSA

모놀리식 아키텍처는 애플리케이션의 모든 기능이 하나의 큰 코드베이스에 통합된 형태입니다. 이 방식은 초기 개발 및 관리가 비교적 단순하다는 장점이 있지만, 프로젝트가 커질수록 유지보수와 배포에서 문제점이 발생할 수 있습니다. 하나의 모듈에서 에러가 나면, 전체 애플리케이션이 영향을 받을 수 있기 때문입니다.

반면, MSA는 애플리케이션을 여러 개의 독립적인 서비스로 분할하여 운영합니다. 각 서비스는 자신만의 데이터베이스와 기능을 가지고 있으며, 네트워크를 통해 서로 통신합니다. 이 방식은 서비스 간의 의존성을 줄여, 특정 기능의 변경이나 장애가 다른 서비스에 영향을 미치지 않도록 해줍니다. 또한, 각 서비스를 다른 프로그래밍 언어로 개발하거나, 서비스의 필요에 맞는 기술을 유연하게 선택할 수 있는 장점이 있습니다.

MSA에서의 통신 방식: HTTP vs gRPC

MSA에서는 서비스 간의 통신을 위해 주로 HTTP 기반 REST API나 gRPC 같은 RPC(Remote Procedure Call) 방식을 사용합니다. 두 가지 방식은 각각의 장점과 단점을 가지고 있으며, 특정 상황에 적합한 방식을 선택하는 것이 중요합니다.

HTTP 기반의 REST API

HTTP는 가장 많이 사용되는 통신 방식 중 하나로, REST API는 이 HTTP를 사용하여 서비스 간 데이터를 주고받는 구조를 제공합니다. REST는 URL을 통해 자원을 명확히 식별하고, HTTP 메소드(GET, POST, PUT, DELETE 등)를 사용해 데이터를 조작합니다. 간단한 예시는 다음과 같습니다:

# Python Flask를 사용한 간단한 REST API 서버 예제
from flask import Flask, jsonify, request

app = Flask(__name__)

@app.route('/add', methods=['POST'])
def add_numbers():
    data = request.get_json()
    result = data['num1'] + data['num2']
    return jsonify({'result': result})

if __name__ == '__main__':
    app.run(port=5000)

위 코드에서는 Flask 프레임워크를 사용하여 간단한 더하기 기능을 가진 API를 작성하였습니다. 클라이언트는 이 API를 호출하여 두 수의 합을 얻을 수 있습니다.

gRPC

gRPC는 구글에서 개발한 오픈 소스 RPC 프레임워크로, Protocol Buffers(proto 파일)를 사용하여 데이터를 직렬화합니다. HTTP/2를 기반으로 하여 빠르고 효율적인 통신을 가능하게 합니다. gRPC는 특히 양방향 스트리밍을 지원하며, 대용량 데이터 전송이나 낮은 지연 시간이 요구되는 시스템에 적합합니다.

간단한 gRPC 서버 예시는 다음과 같습니다:

# gRPC를 사용한 간단한 서버 예제
import grpc
from concurrent import futures
import time

import add_pb2
import add_pb2_grpc

class AddService(add_pb2_grpc.AddServiceServicer):
    def AddNumbers(self, request, context):
        result = request.num1 + request.num2
        return add_pb2.AddResponse(result=result)

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    add_pb2_grpc.add_AddServiceServicer_to_server(AddService(), server)
    server.add_insecure_port('[::]:50051')
    server.start()
    server.wait_for_termination()

if __name__ == '__main__':
    serve()

위 예제는 gRPC 서버를 구현한 코드입니다. AddService라는 서비스가 두 수를 더하는 기능을 제공하며, 클라이언트는 이를 호출하여 결과를 얻을 수 있습니다. gRPC는 REST API보다 더 빠른 통신 속도를 제공하며, 데이터 직렬화 시 더 효율적입니다.

HTTP와 gRPC의 사용 시나리오

  • HTTP/REST: 간단한 CRUD 작업이나 널리 사용되는 표준 API 설계가 필요할 때 사용됩니다. 클라이언트와 서버가 서로 다른 언어로 개발된 경우에도 HTTP 기반의 REST API는 호환성이 좋습니다.
  • gRPC: 높은 성능이 요구되는 시스템, 양방향 스트리밍이 필요한 경우, 또는 여러 서비스 간의 빈번한 통신이 필요한 경우에 적합합니다. 특히, 데이터 직렬화 포맷인 Protocol Buffers 덕분에 낮은 대역폭으로도 데이터를 효율적으로 전송할 수 있습니다.

MSA의 장점

모놀리식 아키텍처와 비교했을 때, MSA는 다음과 같은 장점이 있습니다:

  1. 확장성: 각각의 마이크로서비스를 독립적으로 배포하고 확장할 수 있어, 필요한 부분만 확장 가능하므로 리소스의 효율적 사용이 가능합니다.
  2. 유지보수성: 서비스가 작게 나누어져 있기 때문에 특정 기능을 변경하거나 수정할 때 전체 시스템에 영향을 미치지 않습니다. 이는 배포의 리스크를 줄이고, 개발 속도를 높입니다.
  3. 기술 다양성: 각 마이크로서비스는 독립적으로 개발되기 때문에, 팀별로 적합한 기술 스택을 선택할 수 있습니다. 예를 들어, 일부 서비스는 Python으로, 다른 서비스는 Java로 개발하는 식으로 기술적인 자유를 누릴 수 있습니다.
  4. 장애 격리: 하나의 서비스에 장애가 발생하더라도 다른 서비스에 영향을 미치지 않기 때문에 시스템 전체의 안정성을 높일 수 있습니다.

MSA의 단점

하지만 MSA에도 단점이 존재합니다:

  1. 복잡성 증가: 여러 개의 마이크로서비스를 관리해야 하기 때문에 아키텍처의 복잡성이 증가합니다. 각 서비스 간의 통신, 데이터 일관성, 배포 관리 등이 복잡해져서 많은 운영 부담이 생길 수 있습니다.
  2. 배포 및 테스트의 어려움: 각 서비스가 독립적으로 배포되기 때문에 종합적인 테스트와 배포 과정이 복잡해질 수 있습니다. 서비스 간의 의존성을 고려하여 순차적으로 배포해야 하는 경우가 많으며, 각 서비스의 업데이트가 다른 서비스에 영향을 미치지 않도록 신중히 테스트해야 합니다.
  3. 네트워크 문제: 서비스 간 통신이 네트워크를 통해 이루어지기 때문에, 네트워크 지연(latency)이나 장애가 전체 시스템에 영향을 미칠 수 있습니다. 또한, 데이터가 여러 서비스에 분산되어 있으면 데이터 일관성을 유지하는 것이 어려울 수 있습니다.
  4. 운영 비용 증가: 많은 수의 마이크로서비스를 운영하기 위해서는 추가적인 인프라가 필요합니다. 각 서비스의 배포, 모니터링, 로깅 등을 위한 도구들이 필요하며, 이는 운영 비용을 높일 수 있습니다.

마무리

MSA는 시스템을 작은 서비스 단위로 나누어 독립적인 배포와 확장을 가능하게 하고, 장애의 영향을 최소화하는 구조적 장점이 있습니다. 하지만 그만큼 관리와 운영의 복잡성이 증가할 수 있으며, 신중한 설계와 도구의 활용이 필요합니다. REST API와 gRPC는 각기 다른 특성과 장점을 지닌 통신 방식으로, 상황에 따라 적합한 방식을 선택해 사용해야 합니다. 서비스 간의 통신 빈도와 성능 요구 사항에 따라 올바른 접근 방식을 선택하는 것이 중요합니다.

여러분은 MSA를 도입하면서 어떤 통신 방식을 사용하고 계신가요? 혹시 아직 결정하지 못했다면, 이번 포스팅을 통해 도움이 되었길 바랍니다.