docs: integrate grpcentity README into unified docs/MANUSCRIPT.md
This commit is contained in:
+120
-3
@@ -63,12 +63,129 @@ gRPC의 주요 장점은 다음과 같습니다:
|
||||
> 이 장점 목록만 보고 gRPC가 모든 문제의 완벽한 해결책이라고 오해해서는 안 됩니다. 항상 현재 작업에 가장 적합한 도구나 기술을 선택하는 것이 중요합니다.
|
||||
|
||||
### 4.2 프로토콜 버퍼 (Protobuf)
|
||||
프로토콜 버퍼(Protobuf)는 구조화된 데이터를 효율적으로 직렬화하는 방법입니다. Protobuf는 IDL(인터페이스 정의 언어)의 일부로, 데이터 교환 시 바이너리 형식을 사용하기 때문에 일반 텍스트 기반 직렬화 형식보다 훨씬 적은 공간을 차지합니다. 하지만 데이터를 기계가 사용하고 사람이 읽을 수 있도록 하려면 각각 인코딩과 디코딩 과정이 필요합니다. Protobuf는 각 프로그래밍 언어에서 기본적으로 지원하는 데이터 타입으로 변환되는 자체 데이터 타입을 제공합니다.
|
||||
프로토콜 버퍼(Protobuf)는 구조화된 데이터를 효율적으로 직렬화하는 방법입니다. IDL(인터페이스 정의 언어) 역할을 하는 `.proto` 파일을 사용해 통신 규약을 명확히 정의합니다.
|
||||
|
||||
일반적으로 IDL 파일은 모든 gRPC 서비스의 핵심입니다. 이는 데이터 교환 형식과 서비스 인터페이스를 정의하기 때문입니다. Protobuf 파일 없이는 gRPC 서비스를 구축할 수 없습니다. 더 정확히 말하면, Protobuf 파일에는 서비스 정의, 서비스 메서드, 그리고 교환될 메시지 형식이 모두 포함됩니다.
|
||||
#### Protobuf의 주요 장단점
|
||||
|
||||
* **장점**
|
||||
* **높은 전송 효율성**: 데이터 교환 시 텍스트 기반이 아닌 바이너리 형식을 사용하므로 JSON에 비해 데이터 크기가 매우 작고 직렬화/역직렬화 속도가 빠릅니다.
|
||||
* **강력한 스키마 계약**: 하나의 정의 파일(`.proto`)로부터 다국어 클라이언트/서버 코드를 자동 생성(Stub 코드)하므로 컴파일 단계에서 타입 불일치 에러를 방지할 수 있습니다.
|
||||
* **하위 호환성 유지**: 필드 번호를 기반으로 직렬화하므로 데이터 스키마가 업데이트되더라도 기존 시스템과의 호환성을 유연하게 보존합니다.
|
||||
|
||||
* **단점**
|
||||
* **사람이 읽기 어려운 가독성 (Binary Format)**: 바이너리 형태로 데이터가 전송되므로, JSON처럼 네트워크 패킷을 사람이 직접 눈으로 확인하거나 텍스트 편집기로 디버깅하기 어렵습니다.
|
||||
* **빌드 복잡성**: 스펙이 바뀔 때마다 `protoc` 컴파일러와 관련 플러그인을 활용하여 코드를 재생성(Stub 컴파일)해야 하는 추가적인 개발 파이프라인 단계가 필요합니다.
|
||||
|
||||
---
|
||||
|
||||
## 5. 참고 자료
|
||||
## 5. 실습: gRPC 기반 서비스 구현 및 컴파일
|
||||
|
||||
이 저장소에 기동되어 실행되는 gRPC 예제(`Random` 서비스)의 구체적인 IDL 명세와 컴파일, 그리고 구현 코드를 상세히 분석합니다.
|
||||
|
||||
### 5.1 인터페이스 정의 언어(IDL) `protoapi.proto` 분석
|
||||
|
||||
우리가 개발할 gRPC 서비스는 다음 기능을 제공합니다:
|
||||
* 서버는 클라이언트에게 현재 날짜와 시간을 반환해야 합니다.
|
||||
* 서버는 클라이언트에게 주어진 길이의 무작위 비밀번호를 반환해야 합니다.
|
||||
* 서버는 클라이언트에게 무작위 정수를 반환해야 합니다.
|
||||
|
||||
이 통신 규약은 루트 디렉토리의 [protoapi.proto](file:///home/godopu16/PuKi/lab/canary_projects/grpccanary/protoapi.proto) 파일에 다음과 같이 기술되어 있습니다.
|
||||
|
||||
```proto
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = "./protoapi/;protoapi";
|
||||
|
||||
service Random {
|
||||
rpc GetDate (RequestDateTime) returns (DateTime);
|
||||
rpc GetRandom (RandomParams) returns (RandomInt);
|
||||
rpc GetRandomPass (RequestPass) returns (RandomPass);
|
||||
}
|
||||
|
||||
message RandomParams {
|
||||
int64 Seed = 1;
|
||||
int64 Place = 2;
|
||||
}
|
||||
|
||||
message RandomInt {
|
||||
int64 Value = 1;
|
||||
}
|
||||
|
||||
message DateTime {
|
||||
string Value = 1;
|
||||
}
|
||||
|
||||
message RequestDateTime {
|
||||
string Value = 2;
|
||||
}
|
||||
|
||||
message RequestPass {
|
||||
int64 Seed = 1;
|
||||
int64 Length = 8;
|
||||
}
|
||||
|
||||
message RandomPass {
|
||||
string Password = 1;
|
||||
}
|
||||
```
|
||||
|
||||
* **`syntax = "proto3"`**: 프로토콜 버퍼 언어의 proto3 버전을 활용합니다. 명시하지 않으면 구버전인 proto2로 인식되므로 파일 최상단에 반드시 기술해야 합니다.
|
||||
* **`option go_package`**: 컴파일 시 Go 코드로 출력될 패키지의 이름을 `protoapi`로 지정하며, 출력 디렉토리를 `./protoapi/`로 명시합니다.
|
||||
* **`service Random`**: 서버와 클라이언트가 사용할 3가지 RPC 메서드명(`GetDate`, `GetRandom`, `GetRandomPass`)과 해당 메서드들이 수용/반환할 메시지 포맷을 상호 정의합니다.
|
||||
* **`message` 필드 및 태그**: 각 메시지 필드마다 데이터 타입(예: `int64`, `string`)과 바이너리 인코딩 시 키값 역할을 하는 고유 태그 번호(예: `= 1`, `= 2`)를 부여합니다.
|
||||
|
||||
### 5.2 Go에서 IDL 파일 컴파일 및 Stub 생성
|
||||
|
||||
`.proto` 정의를 실제 Go 소스 코드로 컴파일하려면 프로토콜 버퍼 컴파일러(`protoc`)와 Go용 플러그인(`protoc-gen-go`, `protoc-gen-go-grpc`)이 로컬 시스템에 설치되어 있어야 합니다.
|
||||
|
||||
#### 도구 설치 방법
|
||||
* **macOS (Homebrew)**:
|
||||
```bash
|
||||
brew install protobuf
|
||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
|
||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
||||
```
|
||||
* **Linux (Ubuntu/Debian)**:
|
||||
```bash
|
||||
sudo apt install -y protobuf-compiler
|
||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
|
||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
||||
```
|
||||
|
||||
#### 컴파일 실행 명령어
|
||||
설치 완료 후 리포지토리 루트에서 다음 컴파일 명령어를 수행합니다:
|
||||
```bash
|
||||
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. \
|
||||
--go-grpc_opt=paths=source_relative protoapi.proto
|
||||
```
|
||||
* 이 실행을 통해 `protoapi/` 디렉토리 밑에 메시지 포맷 정의가 담긴 `protoapi.pb.go`와 gRPC 클라이언트/서버 인터페이스 및 메서드 껍데기가 들어있는 `protoapi_grpc.pb.go` 파일이 자동 생성됩니다.
|
||||
|
||||
### 5.3 gRPC 서버 구현 ([server.go](file:///home/godopu16/PuKi/lab/canary_projects/grpccanary/examples/grpcentity/server.go))
|
||||
|
||||
IDL을 통해 생성된 Go 패키지(`protoapi`)를 가져와 실제 비즈니스 로직을 수행할 gRPC 서버를 구현합니다.
|
||||
|
||||
* **구조체 정의**: `RandomServer` 구조체 타입을 선언하고 `protoapi.UnimplementedRandomServer`를 임베딩하여 gRPC 인터페이스 호환을 확보합니다.
|
||||
* **비즈니스 메서드 구현**:
|
||||
* **`GetDate`**: 현재 시간 문자열을 반환합니다.
|
||||
* **`GetRandom`**: 시드값을 기반으로 지정된 위치에 있는 의사 난수를 반환합니다.
|
||||
* **`GetRandomPass`**: 요청된 시드와 길이 매개변수를 활용해 무작위 비밀번호 문자열을 조립해 반환합니다.
|
||||
* **서버 기동 (`ServerRun`)**:
|
||||
* `grpc.NewServer()`로 서버 인스턴스를 확보하고 서비스를 등록합니다.
|
||||
* 외부 디버깅 도구(예: `grpcurl` 등)가 인터페이스 사양을 동적으로 검색할 수 있도록 `reflection.Register(server)`를 호출해 리플렉션을 활성화합니다.
|
||||
* `net.Listen("tcp", port)`를 통해 네트워크 채널을 열고 대기 상태(`server.Serve`)를 개시합니다.
|
||||
|
||||
### 5.4 gRPC 클라이언트 구현 ([client.go](file:///home/godopu16/PuKi/lab/canary_projects/grpccanary/examples/grpcentity/client.go))
|
||||
|
||||
서버에 원격 호출을 요청하고 응답 데이터를 가공해 출력하는 클라이언트 흐름입니다.
|
||||
|
||||
* **채널 접속**: `grpc.Dial` 함수를 통해 주소로의 연결 통로를 엽니다. 로컬 테스트 및 통신 단순화를 위해 평문(TLS 미적용) 커넥션(`insecure.NewCredentials()`)을 수립합니다.
|
||||
* **클라이언트 인스턴스 생성**: `protoapi.NewRandomClient(conn)`를 통해 원격 서비스 호출 인터페이스 객체를 생성합니다.
|
||||
* **호출 래퍼**: `AskingDateTime`, `AskPass`, `AskRandom` 등의 헬퍼 함수를 통해 실제 RPC 메서드에 요청 파라미터(시드, 길이 등)를 태워 호출합니다.
|
||||
* **콘솔 출력 (`ClientRun`)**: 최종 수신한 시간, 생성된 무작위 비밀번호, 임의의 난수를 받아 콘솔 표준 출력에 정상 표시해 줍니다.
|
||||
|
||||
---
|
||||
|
||||
## 6. 참고 자료
|
||||
|
||||
* [gRPC와 REST의 차이점 (AWS)](https://aws.amazon.com/ko/compare/the-difference-between-grpc-and-rest/)
|
||||
|
||||
|
||||
+17
-213
@@ -1,222 +1,26 @@
|
||||
# 인터페이스 정의 언어(IDL) 파일 정의하기
|
||||
# examples/grpcentity 실습 설명서
|
||||
|
||||
인터페이스 정의 언어(IDL) 파일을 정의하는 방법을 배워보겠습니다.
|
||||
본 디렉토리는 Go 언어를 활용한 gRPC 서버 및 클라이언트 실습 예제를 포함하고 있습니다.
|
||||
|
||||
우리가 개발할 gRPC 서비스는 다음 기능을 지원할 것입니다:
|
||||
## 📖 실습 상세 분석 및 가이드 안내
|
||||
|
||||
- 서버는 클라이언트에게 현재 날짜와 시간을 반환해야 합니다.
|
||||
- 서버는 클라이언트에게 주어진 길이의 무작위로 생성된 비밀번호를 반환해야 합니다.
|
||||
- 서버는 클라이언트에게 무작위 정수를 반환해야 합니다.
|
||||
학습의 일관성을 위해, 이 실습의 상세 분석 및 개념 명세는 통합 교재 문서인 **[docs/MANUSCRIPT.md](file:///home/godopu16/PuKi/lab/canary_projects/grpccanary/docs/MANUSCRIPT.md)**로 통합되었습니다.
|
||||
|
||||
gRPC 클라이언트와 서버 개발을 시작하기 전에, IDL 파일을 먼저 정의해야 합니다. IDL 정의는 이 저장소 루트에 위치한 `protoapi.proto` 파일을 사용합니다.
|
||||
|
||||
## IDL 파일의 구조
|
||||
|
||||
다음은 `protoapi.proto`라는 IDL 파일의 내용입니다:
|
||||
|
||||
```proto
|
||||
syntax = "proto3";
|
||||
```
|
||||
|
||||
이 파일은 프로토콜 버퍼 언어의 **proto3** 버전을 사용합니다. 이전 버전인 **proto2**도 있으며, 약간의 문법적 차이가 있습니다. `proto3`를 명시하지 않으면, 프로토콜 버퍼 컴파일러는 **proto2**를 사용하는 것으로 간주합니다. 버전 정의는 `.proto` 파일의 첫 번째 비어있지 않은, 주석이 아닌 라인에 위치해야 합니다.
|
||||
|
||||
```proto
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = "./protoapi/;protoapi";
|
||||
```
|
||||
|
||||
gRPC 도구들은 이 `.proto` 파일로부터 Go 코드를 생성할 것입니다. 위 라인은 생성될 Go 패키지의 이름이 `protoapi`임을 명시합니다. `./protoapi/`를 사용했기 때문에 출력 파일은 `protoapi/` 하위 디렉토리에 생성됩니다.
|
||||
|
||||
```proto
|
||||
service Random {
|
||||
rpc GetDate (RequestDateTime) returns (DateTime);
|
||||
rpc GetRandom (RandomParams) returns (RandomInt);
|
||||
rpc GetRandomPass (RequestPass) returns (RandomPass);
|
||||
}
|
||||
```
|
||||
|
||||
이 블록은 gRPC 서비스의 이름(`Random`)과 지원하는 메서드들을 명시합니다. 또한, 각 상호작용에 필요한 메시지들을 지정합니다. 예를 들어, `GetDate`의 경우 클라이언트는 `RequestDateTime` 메시지를 보내고 `DateTime` 메시지를 받기를 기대합니다.
|
||||
|
||||
이 메시지들은 동일한 `.proto` 파일에 정의되어 있습니다.
|
||||
|
||||
```proto
|
||||
// For random number
|
||||
```
|
||||
|
||||
모든 `.proto` 파일은 C와 C++ 스타일의 주석을 지원합니다. 즉, `// text`와 `/* text */` 형식의 주석을 사용할 수 있습니다.
|
||||
|
||||
```proto
|
||||
message RandomParams {
|
||||
int64 Seed = 1;
|
||||
int64 Place = 2;
|
||||
}
|
||||
```
|
||||
|
||||
난수 생성기는 시드(seed) 값으로 시작하며, 이 값은 클라이언트가 지정하여 `RandomParams` 메시지를 통해 서버로 전송됩니다. `Place` 필드는 무작위로 생성된 정수 시퀀스에서 반환될 난수의 위치를 지정합니다.
|
||||
|
||||
```proto
|
||||
message RandomInt {
|
||||
int64 Value = 1;
|
||||
}
|
||||
```
|
||||
|
||||
앞선 두 메시지는 `GetRandom` 메서드와 관련이 있습니다. `RandomParams`는 요청의 매개변수를 설정하는 데 사용되고, `RandomInt`는 서버가 생성한 난수를 저장하는 데 사용됩니다. 모든 메시지 필드는 `int64` 데이터 타입을 가집니다.
|
||||
|
||||
```proto
|
||||
message DateTime {
|
||||
string Value = 1;
|
||||
}
|
||||
|
||||
message RequestDateTime {
|
||||
string Value = 2;
|
||||
}
|
||||
```
|
||||
|
||||
위 두 메시지는 `GetDate` 메서드의 동작을 지원하기 위한 것입니다. `RequestDateTime` 메시지는 실질적인 데이터를 담고 있지 않은 더미 메시지입니다. 단지 클라이언트가 서버로 보내는 메시지가 필요할 뿐이며, `Value` 필드에는 어떤 종류의 정보든 저장할 수 있습니다. 서버가 반환하는 정보는 `DateTime` 메시지에 `string` 값으로 저장됩니다.
|
||||
|
||||
> **참고**: `RequestDateTime`의 `Value` 필드 번호가 `2`로 지정되어 있습니다. 프로토콜 버퍼에서 필드 번호는 태그 번호로 사용되며 고유한 번호라면 임의의 값을 가질 수 있지만, 일반적으로는 첫 필드에 `1`을 사용하는 것이 관례입니다.
|
||||
|
||||
```proto
|
||||
// For random password
|
||||
message RequestPass {
|
||||
int64 Seed = 1;
|
||||
int64 Length = 8;
|
||||
}
|
||||
|
||||
message RandomPass {
|
||||
string Password = 1;
|
||||
}
|
||||
```
|
||||
|
||||
마지막으로, 위 두 메시지는 `GetRandomPass`의 동작을 위한 것입니다.
|
||||
|
||||
요약하자면, IDL 파일은 다음을 수행합니다:
|
||||
- `proto3`를 사용함을 명시합니다.
|
||||
- 서비스의 이름이 `Random`임을 정의합니다.
|
||||
- 생성될 Go 패키지의 이름이 `protoapi`임을 명시합니다.
|
||||
- gRPC 서비스가 `GetDate`, `GetRandom`, `GetRandomPass` 세 가지 메서드를 지원함을 정의하고, 이 메서드 호출에서 교환될 메시지들의 이름을 정의합니다.
|
||||
- 데이터 교환에 사용될 여섯 가지 메시지의 형식을 정의합니다.
|
||||
|
||||
## Go에서 IDL 파일 사용하기
|
||||
|
||||
다음 중요한 단계는 이 파일을 Go에서 사용할 수 있는 형식으로 변환하는 것입니다. `protoapi.proto`나 다른 `.proto` 파일을 처리하여 관련된 Go `.pb.go` 파일을 생성하기 위해 몇 가지 추가 도구를 다운로드해야 합니다. 프로토콜 버퍼 컴파일러 바이너리의 이름은 `protoc`입니다. macOS에서는 `brew install protobuf` 명령을 사용하여 `protoc`를 설치해야 합니다. 마찬가지로, Homebrew를 사용하여 `protoc-gen-go-grpc`와 `protoc-gen-go` 패키지도 설치해야 합니다. 이 두 패키지는 Go와 관련이 있습니다.
|
||||
|
||||
Linux에서는 선호하는 패키지 관리자를 사용하여 `protobuf`를 설치하고, `go install google.golang.org/protobuf/cmd/protoc-gen-go@latest` 명령을 사용하여 `protoc-gen-go`를 설치해야 합니다. 마찬가지로, `go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest`를 실행하여 `protoc-gen-go-grpc` 실행 파일을 설치해야 합니다.
|
||||
|
||||
> 참고: Go 1.16부터는 모듈 모드에서 패키지를 빌드하고 설치하는 데 `go install`을 사용하는 것이 권장됩니다. `go get`의 사용은 더 이상 사용되지 않습니다. `go install`을 사용할 때는 최신 버전을 설치하기 위해 패키지 이름 뒤에 `@latest`를 추가하는 것을 잊지 마세요.
|
||||
|
||||
- protoc
|
||||
- protoc-gen-go
|
||||
- protoc-gen-go-grpc
|
||||
|
||||
변환 과정은 다음 단계를 필요로 합니다:
|
||||
|
||||
```bash
|
||||
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. \
|
||||
--go-grpc_opt=paths=source_relative protoapi.proto
|
||||
```
|
||||
|
||||
이 명령을 실행하면, 리포지토리 루트 하위의 `protoapi` 디렉토리에 `protoapi_grpc.pb.go`와 `protoapi.pb.go`라는 두 개의 파일이 생성됩니다. `protoapi.pb.go` 소스 코드 파일에는 메시지가 포함되어 있고, `protoapi_grpc.pb.go`에는 서비스가 포함되어 있습니다.
|
||||
|
||||
`protoapi_grpc.pb.go`의 첫 열 줄은 다음과 같습니다:
|
||||
|
||||
```go
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
|
||||
package protoapi
|
||||
```
|
||||
|
||||
앞서 논의했듯이, 패키지 이름은 `protoapi`입니다.
|
||||
|
||||
```go
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
```
|
||||
|
||||
이것은 `import` 블록입니다. `context "context"`가 있는 이유는 `context`가 예전에는 표준 Go 라이브러리의 일부가 아닌 외부 Go 패키지였기 때문입니다.
|
||||
|
||||
`protoapi.pb.go`의 첫 줄은 다음과 같습니다:
|
||||
|
||||
```go
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v3.21.12
|
||||
// source: protoapi.proto
|
||||
|
||||
package protoapi
|
||||
```
|
||||
|
||||
`protoapi_grpc.pb.go`와 `protoapi.pb.go`는 모두 `protoapi` Go 패키지의 일부이므로, 코드에서 한 번만 포함하면 됩니다.
|
||||
|
||||
## gRPC 서버 개발
|
||||
|
||||
IDL을 통해 생성된 Go 코드를 기반으로, 실제 비즈니스 로직을 수행할 gRPC 서버([server.go](./server.go))를 구현합니다.
|
||||
|
||||
### 1. 서비스 인터페이스 구현
|
||||
우리가 `.proto` 파일에 정의한 `Random` 서비스의 메서드들은 `RandomServer` 구조체 타입을 통해 구현됩니다. 이 구조체는 stub 코드의 `UnimplementedRandomServer`를 임베딩하여 기본 호환성을 확보합니다.
|
||||
|
||||
```go
|
||||
type RandomServer struct {
|
||||
protoapi.UnimplementedRandomServer
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 서비스 메서드 작성
|
||||
서버는 IDL에 기술된 세 가지 RPC 메서드인 `GetDate`, `GetRandom`, `GetRandomPass`를 각각 실제 동작 코드로 구현합니다.
|
||||
|
||||
* **`GetDate`**: 현재 날짜와 시간 정보를 반환합니다.
|
||||
* **`GetRandom`**: 전달받은 시드(`Seed`)와 위치(`Place`) 매개변수를 이용해 의사 난수를 생성하고 반환합니다.
|
||||
* **`GetRandomPass`**: 지정된 길이(`Length`)의 무작위 문자열 비밀번호를 빌드하여 반환합니다.
|
||||
|
||||
### 3. gRPC 서버 시작 (`ServerRun`)
|
||||
네트워크 포트 청취를 개시하고, gRPC 서버 객체를 인스턴스화한 후 서비스를 등록하여 대기 상태에 들어갑니다.
|
||||
|
||||
```go
|
||||
func ServerRun(addr string) {
|
||||
server := grpc.NewServer()
|
||||
var randomServer RandomServer
|
||||
protoapi.RegisterRandomServer(server, randomServer)
|
||||
|
||||
// 외부 CLI 도구(예: grpcurl)의 디버깅을 위해 리플렉션 등록
|
||||
reflection.Register(server)
|
||||
|
||||
listen, err := net.Listen("tcp", port)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("Serving requests...")
|
||||
server.Serve(listen)
|
||||
}
|
||||
```
|
||||
[docs/MANUSCRIPT.md](file:///home/godopu16/PuKi/lab/canary_projects/grpccanary/docs/MANUSCRIPT.md) 문서의 **"5. 실습: gRPC 기반 서비스 구현 및 컴파일"** 절에서 다음 내용을 참고하실 수 있습니다:
|
||||
* **IDL (`protoapi.proto`) 명세 및 필드 분석**
|
||||
* **Go에서의 `protoc` 설치 및 Stub 파일 컴파일 방법**
|
||||
* **gRPC 서버 코드 ([server.go](./server.go)) 구현 상세 분석**
|
||||
* **gRPC 클라이언트 코드 ([client.go](./client.go)) 커넥션 및 호출 흐름 분석**
|
||||
|
||||
---
|
||||
|
||||
## gRPC 클라이언트 개발
|
||||
## 🚀 빠른 실행 방법
|
||||
|
||||
서버로 RPC 요청을 전송하고 결과를 출력하는 gRPC 클라이언트([client.go](./client.go))의 흐름은 다음과 같습니다.
|
||||
이 예제는 리포지토리 루트의 `examples/main.go`를 통해 실행됩니다.
|
||||
|
||||
### 1. 서버 접속 채널 구축
|
||||
클라이언트는 보안 자격 증명 옵션을 지정하여 서버 네트워크 주소로 커넥션을 생성합니다. (본 예제에서는 로컬 테스트용으로 `insecure` 자격 증명을 이용해 평문 채널을 구축합니다.)
|
||||
|
||||
```go
|
||||
conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
```
|
||||
|
||||
### 2. 클라이언트 인스턴스 및 호출 함수 정의
|
||||
채널 연결 완료 후 `protoapi.NewRandomClient(conn)`를 통해 클라이언트 객체를 생성하고, 개별 RPC 메서드들을 호출하는 래퍼 함수들을 정의해 서버에 값을 질의합니다.
|
||||
|
||||
* **`AskingDateTime`** -> `client.GetDate()` 호출
|
||||
* **`AskPass`** -> `client.GetRandomPass()` 호출
|
||||
* **`AskRandom`** -> `client.GetRandom()` 호출
|
||||
|
||||
### 3. 실행 엔트리포인트 (`ClientRun`)
|
||||
각 RPC 메서드를 호출하여 서버로부터 전달받은 시간 값, 난수 비밀번호, 무작위 난수들을 터미널 표준 출력(`fmt.Println`)으로 출력해 줍니다.
|
||||
1. 리포지토리 루트의 `examples/main.go`를 엽니다.
|
||||
2. `main()` 함수 내에서 `grpcSample()`의 주석을 해제합니다.
|
||||
3. 리포지토리 루트에서 다음 명령어를 실행합니다:
|
||||
```bash
|
||||
go run ./examples
|
||||
```
|
||||
Reference in New Issue
Block a user