docs: resolve pathing, legacy modules, external link remnants, and unclosed fences in grpcentity README

This commit is contained in:
2026-07-12 23:36:36 +09:00
parent fc3a0d6b61
commit 989529e8ba
2 changed files with 74 additions and 12 deletions
-4
View File
@@ -1,4 +0,0 @@
# 역할
- 영어로 작성된 파일을 한국어로 번역
- 번역된 표현에서 어색한 한국어 표현 수정 및 내용을 더욱 쉽게 이해할 수 있도록 내용 추가
- 내용의 흐름은 바꾸지 말 것!
+74 -8
View File
@@ -8,7 +8,7 @@
- 서버는 클라이언트에게 주어진 길이의 무작위로 생성된 비밀번호를 반환해야 합니다.
- 서버는 클라이언트에게 무작위 정수를 반환해야 합니다.
gRPC 클라이언트와 서버 개발을 시작하기 전에, IDL 파일을 먼저 정의해야 합니다. IDL 파일과 관련된 파일들을 관리하기 위해 별도의 GitHub 저장소가 필요하며, 여기서는 https://github.com/Educative-Content/protoapi 를 사용합니다.
gRPC 클라이언트와 서버 개발을 시작하기 전에, IDL 파일을 먼저 정의해야 합니다. IDL 정의는 이 저장소 루트에 위치한 `protoapi.proto` 파일을 사용합니다.
## IDL 파일의 구조
@@ -23,10 +23,10 @@ syntax = "proto3";
```proto
syntax = "proto3";
option go_package = "./;protoapi";
option go_package = "./protoapi/;protoapi";
```
gRPC 도구들은 이 `.proto` 파일로부터 Go 코드를 생성할 것입니다. 위 라인은 생성될 Go 패키지의 이름이 `protoapi`임을 명시합니다. `./`를 사용했기 때문에 출력 파일은 `protoapi.proto`와 동일한 현재 디렉토리에 생성됩니다.
gRPC 도구들은 이 `.proto` 파일로부터 Go 코드를 생성할 것입니다. 위 라인은 생성될 Go 패키지의 이름이 `protoapi`임을 명시합니다. `./protoapi/`를 사용했기 때문에 출력 파일은 `protoapi/` 하위 디렉토리에 생성됩니다.
```proto
service Random {
@@ -75,6 +75,8 @@ message RequestDateTime {
위 두 메시지는 `GetDate` 메서드의 동작을 지원하기 위한 것입니다. `RequestDateTime` 메시지는 실질적인 데이터를 담고 있지 않은 더미 메시지입니다. 단지 클라이언트가 서버로 보내는 메시지가 필요할 뿐이며, `Value` 필드에는 어떤 종류의 정보든 저장할 수 있습니다. 서버가 반환하는 정보는 `DateTime` 메시지에 `string` 값으로 저장됩니다.
> **참고**: `RequestDateTime`의 `Value` 필드 번호가 `2`로 지정되어 있습니다. 프로토콜 버퍼에서 필드 번호는 태그 번호로 사용되며 고유한 번호라면 임의의 값을 가질 수 있지만, 일반적으로는 첫 필드에 `1`을 사용하는 것이 관례입니다.
```proto
// For random password
message RequestPass {
@@ -100,7 +102,7 @@ message RandomPass {
다음 중요한 단계는 이 파일을 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 github.com/golang/protobuf/protoc-gen-go@latest` 명령을 사용하여 `protoc-gen-go`를 설치해야 합니다. 마찬가지로, `go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest`를 실행하여 `protoc-gen-go-grpc` 실행 파일을 설치해야 합니다.
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`를 추가하는 것을 잊지 마세요.
@@ -115,7 +117,7 @@ protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. \
--go-grpc_opt=paths=source_relative protoapi.proto
```
이 명령을 실행하면, GitHub 저장소의 루트 디렉토리에 `protoapi_grpc.pb.go``protoapi.pb.go`라는 두 개의 파일이 생성됩니다. `protoapi.pb.go` 소스 코드 파일에는 메시지가 포함되어 있고, `protoapi_grpc.pb.go`에는 서비스가 포함되어 있습니다.
이 명령을 실행하면, 리포지토리 루트 하위의 `protoapi` 디렉토리에 `protoapi_grpc.pb.go``protoapi.pb.go`라는 두 개의 파일이 생성됩니다. `protoapi.pb.go` 소스 코드 파일에는 메시지가 포함되어 있고, `protoapi_grpc.pb.go`에는 서비스가 포함되어 있습니다.
`protoapi_grpc.pb.go`의 첫 열 줄은 다음과 같습니다:
@@ -144,8 +146,8 @@ codes "google.golang.org/grpc/codes"
```go
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.17.3
// protoc-gen-go v1.33.0
// protoc v3.21.12
// source: protoapi.proto
package protoapi
@@ -153,4 +155,68 @@ 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)
}
```
---
## gRPC 클라이언트 개발
서버로 RPC 요청을 전송하고 결과를 출력하는 gRPC 클라이언트([client.go](./client.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`)으로 출력해 줍니다.