Golang gRPC 예제

yebeen·2023년 3월 28일
0

Go

목록 보기
1/1

gRPC란

gRPC는 Google에서 개발한 고성능, 오픈소스, 원격 프로시저 호출(RPC) 프레임워크입니다.

gRPC는 클라이언트와 서버 간의 통신을 처리하기 위한 간단한 인터페이스를 제공하며 이를 통해 클라이언트는 서버에서 제공하는 메소드를 마치 로컬 객체를 사용하는 것과 같이 호출할 수 있습니다.

  • Protocol Buffers와 HTTP/2 프로토콜을 사용하여 빠른 성능과 낮은 대기 시간을 제공합니다.
  • C++, Java, Python, Go, Ruby, C#, Node.js, Android Java, Objective-C, PHP 등 다양한 언어를 지원합니다.
  • Linux, Windows, Mac OS, Android, iOS 등 다양한 플랫폼에서 사용할 수 있습니다.
  • gRPC는 다른 RPC 시스템과 상호 운용이 가능합니다.
  • Protocol Buffers를 사용하여 코드를 자동으로 생성할 수 있으므로, 개발 생산성을 향상시킬 수 있습니다.
  • 마이크로서비스 아키텍처에서 일반적으로 사용되며, 분산 시스템에서의 통신을 단순화합니다.
  • SSL/TLS를 사용하여 데이터 보안을 제공합니다.

즉, 성능이 중요한 분산 시스템, 마이크로서비스 아키텍처, 다양한 플랫폼에서의 웹 서비스 및 애플리케이션, 게임 서버 등에서 사용되어 많은 이점을 제공합니다.

gRPC 시작하기

패키지 설치(go)

$ go install google.golang.org/protobuf/cmd/protoc-gen-go
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
  • PATH 설정
$ export PATH="$PATH:$(go env GOPATH)/bin"
// or
$ vi ~/.zshrc

Protocol Buffers 정의(.proto 파일을 작성)

syntax = "proto3";

package helloworld;

service Greeter {
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
    string name = 1;
}

message HelloReply {
    string message = 1;
}

Server 구현: 클라이언트 요청 처리

package main

import (
    "context"
    "log"
    "net"

    "google.golang.org/grpc"
    pb "your/module/pkg/api/v1"
)

const (
    port = ":50051"
)

type server struct{}

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    log.Printf("Received: %v", in.GetName())
    return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

func main() {
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

Client 구현: 서버에서 제공하는 메서드 호출 및 서버 응답 처리

package main

import (
    "context"
    "log"
    "os"
    "time"

    "google.golang.org/grpc"
    pb "your/module/pkg/api/v1"
)

const (
    address     = "localhost:50051"
    defaultName = "world"
)

func main() {
    conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    c := pb.NewGreeterClient(conn)

    name := defaultName
    if len(os.Args) > 1 {
        name = os.Args[1]
    }

    // Contact the server and print out its response.
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()
    r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", r.GetMessage())
}

Build 및 실행

  • Makefile 작성
# Go 프로그램 빌드를 위한 Makefile

# 설정
PROTO_DIR := protos
GO_OUT := go_out
GO_PROTO_PACKAGE := protos

# Protocol Buffers 정의 파일 경로
PROTO_FILES := $(wildcard $(PROTO_DIR)/*.proto)

# Protocol Buffers를 사용하여 Go 코드 생성
generate:
	protoc -I=$(PROTO_DIR) --go_out=$(GO_OUT) --go-grpc_out=$(GO_OUT) --go_opt=paths=source_relative --go-grpc_opt=paths=source_relative $(PROTO_FILES)

# 빌드
build:
	go build -o bin/server cmd/server/main.go
	go build -o bin/client cmd/client/main.go

# 실행
run-server:
	bin/server

run-client:
	bin/client
  • build
# 코드 생성
$ make generate

# 빌드
$ make build

# 실행 (서버)
$ make run-server

# 실행 (클라이언트)
$ make run-client

프로젝트 구조

- cmd/
    - server/
        - main.go
    - client/
        - main.go
- pkg/
    - api/
        - v1/
            - helloworld.pb.go
            - helloworld.proto
- Makefile
  • cmd/: Go 프로그램의 실행 파일이 저장되는 폴더입니다. cmd/ 폴더에는 서버(server/)와 클라이언트(client/)의 실행 파일이 저장됩니다.
  • pkg/: Go 프로그램의 패키지 파일이 저장되는 폴더입니다. pkg/ 폴더에는 api/ 폴더와 같은 서브 패키지가 있을 수 있습니다.
  • api/: gRPC API 파일이 저장되는 폴더입니다. api/ 폴더에는 다음과 같은 파일이 있습니다.
    - api.proto: gRPC API 정의 파일입니다. Protocol Buffers를 사용하여 작성됩니다.
    - api.pb.go: api.proto 파일을 사용하여 생성된 Go 코드 파일입니다. 이 파일을 사용하여 서버와 클라이언트에서 gRPC API를 사용할 수 있습니다.
  • Makefile: 프로그램 빌드를 자동화하기 위한 Makefile 파일입니다.

profile
🐣🐥

0개의 댓글