본문 바로가기
Dart/Dart Server

[고급] Dart 서버 마이크로서비스 아키텍처 / gRPC와 같은 RPC 프레임워크를 사용한 서비스 간 통신

by Maccrey Coding 2024. 9. 14.
728x90
반응형

 

마이크로서비스 아키텍처에서는 서로 독립적인 서비스들이 서로 통신하여 하나의 시스템을 구성합니다.

이때 서비스 간의 통신을 효율적으로 처리하기 위해 gRPC와 같은 RPC(원격 프로시저 호출) 프레임워크가 사용됩니다.

이 블로그에서는 gRPC의 기본 개념과 Dart에서 gRPC를 사용하는 방법을 초보자도 쉽게 이해할 수 있도록 설명합니다.

1. gRPC란?

gRPCGoogle이 개발한 오픈 소스 원격 프로시저 호출(RPC) 프레임워크입니다.

gRPC는 효율적이고, 고성능의 통신을 지원하며, 다양한 프로그래밍 언어를 지원합니다. 주요 특징은 다음과 같습니다:

  • 고성능: HTTP/2를 기반으로 하여 빠르고, 효율적인 통신을 제공합니다.
  • 다양한 언어 지원: Java, C++, Python, Dart 등 여러 프로그래밍 언어에서 사용할 수 있습니다.
  • IDL(인터페이스 정의 언어): 서비스의 메서드와 메시지를 정의하는 .proto 파일을 사용하여 서비스와 클라이언트 간의 계약을 명확하게 설정합니다.
  • 양방향 스트리밍: 클라이언트와 서버가 동시에 데이터를 스트리밍할 수 있습니다.

2. Dart에서 gRPC 사용하기

Dart에서 gRPC를 사용하려면, grpc 패키지를 사용하여 서버와 클라이언트를 구현할 수 있습니다. 이 과정에서 .proto 파일을 작성하여 서비스와 메시지의 형식을 정의하고, 이를 Dart 코드로 변환해야 합니다.

2.1 환경 설정

1. pubspec.yaml 설정

Dart 프로젝트의 pubspec.yaml 파일에 grpc 패키지를 추가합니다.

dependencies:
  grpc: ^3.0.0
  protobuf: ^2.0.0

 

2. protobuf 패키지 설치

gRPC에서 사용하는 프로토콜 버퍼 파일을 Dart 코드로 변환하기 위해 protobuf 패키지를 설치합니다.

dart pub get

 

2.2 .proto 파일 작성

gRPC 서비스와 메시지를 정의하는 .proto 파일을 작성합니다. 이 파일은 서비스 메서드와 메시지 형식을 설명합니다.

lib/helloworld.proto

syntax = "proto3";

package helloworld;

// 요청과 응답 메시지 정의
message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

// 서비스 정의
service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

위 .proto 파일에서는 Greeter라는 서비스를 정의하고, SayHello라는 RPC 메서드를 설정합니다.

SayHello 메서드는 HelloRequest 메시지를 받아 HelloReply 메시지를 반환합니다.

2.3 Dart 코드 생성

.proto 파일을 Dart 코드로 변환하기 위해 protoc 컴파일러를 사용합니다. Dart용 gRPC 플러그인을 사용하여 코드 생성을 자동화합니다.

1. protoc 설치

brew install protobuf  # macOS
sudo apt-get install protobuf-compiler  # Ubuntu

 

2. Dart 플러그인 설치

pub global activate protoc_plugin

 

3. Dart 코드 생성

protoc --dart_out=grpc:lib/src/generated -Iprotos protos/helloworld.proto

위 명령어는 helloworld.proto 파일을 lib/src/generated 디렉토리에 Dart 코드로 변환합니다.

2.4 서버 구현

lib/server.dart

import 'package:grpc/grpc.dart';
import 'generated/helloworld.pbgrpc.dart';

// Greeter 서비스의 구현
class GreeterService extends GreeterServiceBase {
  @override
  Future<HelloReply> sayHello(ServiceCall call, HelloRequest request) async {
    return HelloReply()..message = '안녕하세요, ${request.name}!';
  }
}

Future<void> main() async {
  final server = Server([GreeterService()]);
  await server.serve(port: 50051);
  print('서버가 실행 중입니다. 포트: ${server.port}');
}

 

  • import 'package:grpc/grpc.dart';: gRPC 패키지를 가져와서 서버를 구현합니다.
  • import 'generated/helloworld.pbgrpc.dart';: protoc로 생성된 Dart 파일을 가져와서 사용합니다.
  • class GreeterService extends GreeterServiceBase: .proto 파일에서 정의된 Greeter 서비스의 구현 클래스입니다.
  • Future<HelloReply> sayHello(ServiceCall call, HelloRequest request): SayHello 메서드를 구현합니다. 클라이언트의 요청을 받아 응답 메시지를 반환합니다.
  • final server = Server([GreeterService()]);: GreeterService를 포함한 gRPC 서버를 생성합니다.
  • await server.serve(port: 50051);: 서버를 50051 포트에서 실행합니다.

2.5 클라이언트 구현

lib/client.dart

import 'package:grpc/grpc.dart';
import 'generated/helloworld.pbgrpc.dart';

Future<void> main() async {
  final channel = ClientChannel(
    'localhost',
    port: 50051,
    options: const ChannelOptions(credentials: ChannelCredentials.insecure()),
  );

  final stub = GreeterClient(channel);

  try {
    final response = await stub.sayHello(HelloRequest()..name = 'Dart');
    print('서버 응답: ${response.message}');
  } catch (e) {
    print('예외 발생: $e');
  } finally {
    await channel.shutdown();
  }
}
  • import 'package:grpc/grpc.dart';: gRPC 패키지를 가져와서 클라이언트를 구현합니다.
  • import 'generated/helloworld.pbgrpc.dart';: protoc로 생성된 Dart 파일을 가져와서 사용합니다.
  • final channel = ClientChannel('localhost', port: 50051, options: const ChannelOptions(credentials: ChannelCredentials.insecure()),);: 서버와 통신할 ClientChannel을 생성합니다. localhost와 50051 포트에서 서버에 연결합니다.
  • final stub = GreeterClient(channel);: gRPC 클라이언트의 스텁을 생성하여 서버 메서드를 호출할 수 있게 합니다.
  • final response = await stub.sayHello(HelloRequest()..name = 'Dart');: sayHello 메서드를 호출하여 서버로부터 응답을 받습니다.
  • print('서버 응답: ${response.message}');: 서버에서 반환된 메시지를 출력합니다.

3. gRPC의 장점과 사용 사례

gRPC는 성능이 뛰어나고, 여러 프로그래밍 언어를 지원하며, 다양한 통신 패턴(단방향, 양방향 스트리밍)을 지원합니다.

이러한 특징 덕분에 대규모 분산 시스템에서 효과적으로 사용할 수 있습니다.

사용 사례

  • 마이크로서비스 간 통신: 빠르고 효율적인 데이터 전송을 필요로 하는 서비스 간 통신.
  • 실시간 데이터 처리: 양방향 스트리밍을 통한 실시간 데이터 처리.
  • 크로스 플랫폼 통신: 다양한 언어로 작성된 서비스 간의 호환성을 제공.

 

gRPC는 고성능의 효율적인 RPC 프레임워크로, 마이크로서비스 아키텍처에서 서비스 간의 통신을 원활하게 처리하는 데 매우 유용합니다.

Dart를 사용하여 gRPC 서버와 클라이언트를 구현함으로써, 분산 시스템에서 빠르고 안정적인 데이터 전송을 구현할 수 있습니다.

이 블로그에서 소개한 gRPC의 기본 개념과 Dart 구현 예제를 통해, 마이크로서비스 아키텍처를 보다 효과적으로 구축하고 관리할 수 있기를 바랍니다.

 

구독!! 공감과 댓글은 저에게 큰 힘이 됩니다.

Starting Google Play App Distribution! "Tester Share" for Recruiting 20 Testers for a Closed Test.

 

Tester Share [테스터쉐어] - Google Play 앱

Tester Share로 Google Play 앱 등록을 단순화하세요.

play.google.com

 

 

728x90
반응형