docs: refine explanation and troubleshooting guides in GRPC.md via multi-agent-mux-loop

This commit is contained in:
2026-07-17 19:41:36 +09:00
parent 20a818520c
commit d83fe114d0
+8 -2
View File
@@ -40,6 +40,7 @@ gRPC는 HTTP/2를 기반으로 구축된 구글의 고성능 오픈소스 원격
1. **서버 시간 및 날짜 조회 (`GetDate`)**: 기기가 접속 상태를 확인하며 동기화를 위해 서버의 현재 날짜와 시간 포맷 문자열을 반환받습니다.
2. **센싱 데이터 업데이트 (`UpdateSensingData`)**: 센서 노드가 주기적으로 수집한 물리 데이터(온도, 습도) 및 기기 식별자(Device ID)를 전달하면, 서버는 데이터 정합성을 검증한 후 성공 여부를 반환합니다.
3. **일회성 보안 패스워드 발급 (`GetRandomPass`)**: 기기가 임시 통신 세션 수립을 위해 난수 생성 시드와 보안 문자열 길이를 전달하면, 무작위 ASCII 임시 패스워드를 연산하여 응답받습니다.
(참고: 여기서는 핵심 3종 Unary RPC를 우선 다루며, 대용량 파일 전송과 실시간 알림 기능은 §7에서 스트리밍 RPC 4종으로 이어서 확장합니다.)
### 2.2 학습 목표 및 진행 방법
이 유기적인 IoT 데이터 통신 모듈을 구축하는 실습을 통해 우리는 다음과 같은 gRPC의 핵심 개발 과정을 아주 쉽게 단계별로 마스터하게 됩니다:
@@ -84,6 +85,8 @@ gRPC는 HTTP/2를 기반으로 구축된 구글의 고성능 오픈소스 원격
실습 디렉토리 내에 선언된 [protoapi.proto](../lib/grpcentity/protoapi.proto) 명세서 코드는 앞서 기획한 `IoTService` 통신 구조를 수립하기 위해 다음과 같이 사양을 기재해 둡니다.
※ 이 코드는 기본 Unary RPC 3종만 발췌한 것이며, 전체 스펙(스트리밍 4종 포함)은 §7.1에서 이어집니다.
```proto
syntax = "proto3";
@@ -276,13 +279,14 @@ protoc --go_out=. --go-grpc_out=. protoapi.proto
### 6.1 `bind: address already in use` (네트워크 소켓 포트 충돌)
* **발생 원인**: gRPC 서버 기동 시 설정한 통신 포트 `:8080`이 이미 다른 네트워크 프로세스나 이전 실습 서버의 비정상 종료 등으로 인해 점유되어 바인딩에 실패한 상태입니다.
* **조치 방법**:
- `lib/main.go`의 `port` 변수 및 [server.go](../lib/grpcentity/server.go)의 `port` 전역 변수값을 동시에 다른 유휴 포트(예: `:9090`)로 변경하여 구동을 시도합니다.
- **🚨 소스코드 설계 제약**: `server.go`에 기재된 `ServerRun(addr string)` 함수는 메인 환경으로부터 주입받은 `addr` 인자값을 사용하지 않고, 패키지 내부 전역 변수인 `port` (하드코딩된 값 `:8080`)를 소켓 리슨 파라미터로 직접 참조하도록 되어 있습니다. 따라서 바인딩 충돌 회피를 위해서는 `main.go`뿐만 아니라 반드시 `server.go` 파일 내부의 전역 변수인 `port` 역시 함께 갱신해 주어야 실제 바인딩 포트 변경이 유효하게 처리됩니다.
- `lib/main.go`의 `port` 변수 값을 다른 유휴 포트(예: `:9090`)로 변경한 뒤 다시 실행하십시오. `ServerRun(addr)` 함수가 이 값을 메인 진입점으로부터 인자로 전달받아 TCP 리스너를 생성하므로, `main.go` 한 곳만 수정하면 서버와 클라이언트의 통신 포트가 동시에 성공적으로 변경됩니다.
---
## 7. 대용량 데이터 전송을 위한 스트리밍(Streaming) 구현
쉽게 말해, 지금까지 배운 방식(Unary)이 '궁금한 게 있을 때마다 전화를 걸어 질문 하나씩 하고 바로 끊는 것'이라면, 스트리밍은 **'전화를 한 번 걸어 끊지 않은 상태로, 준비된 데이터 조각(Chunk)들을 긴 띠처럼 끊임없이 흘려보내는 것'**입니다. 큰 파일을 한 번에 통째로 보내면 메모리가 가득 차서 전송하기 어려우므로, 전화선은 그대로 유지한 채 데이터를 작게 나누어 연속으로 전달하는 방법을 배웁니다.
일반적인 단발성 요청/응답(Unary) 통신은 전송할 전체 데이터를 단일 메모리에 전부 올려 적재한 상태에서 동작하므로, 펌웨어나 대형 이미지 같은 대용량 데이터를 다룰 때 메모리 고갈(OOM)이나 네트워크 대역폭 병목을 초래하기 쉽습니다. gRPC는 HTTP/2 프로토콜의 스트림(Stream) 채널을 기본 가용하므로, 데이터를 일정 크기(Chunk) 단위로 쪼개 연속적으로 전송할 수 있는 강력한 **스트리밍(Streaming)** 기법을 지원합니다. 본 예제에서는 클라이언트가 파일을 조각내어 보내는 **클라이언트 스트리밍(Client Streaming)**, 업로드된 파일 메타 정보를 모아 한 번에 내려주는 **단일 조회(Unary RPC)**, 그리고 서버가 데이터를 쪼개어 클라이언트에게 보내는 **서버 스트리밍(Server Streaming)**까지 모두 종합 설계하여 탑재했습니다.
### 7.1 스키마 설계 (`protoapi.proto`)
@@ -431,6 +435,8 @@ func AskDownloadFile(ctx context.Context, m protoapi.IoTServiceClient, fileName
### 7.4 실시간 알림을 위한 Pub/Sub (발행/구독) 브로드캐스팅 구현
쉽게 말해 Pub/Sub은 '신문 구독'과 같습니다. 구독자(클라이언트)가 한 번 신청해 두면, 발행자(서버)는 새로운 소식(경보)이 생길 때마다 모든 구독자에게 알아서 배달해 줍니다. 클라이언트가 매번 '무슨 일 없어요?'라고 다시 물어볼 필요가 없다는 것이 핵심입니다.
스마트 가전이나 센서 등 실시간 경보 통지가 필요한 AIoT 도메인에서는, 서버가 상시 대기하는 여러 디바이스(클라이언트)들에게 비동기로 이벤트를 밀어 넣어주는 **발행/구독(Publish/Subscribe)** 연동 구조가 필수적입니다. gRPC의 **서버 스트리밍(Server Streaming)** 채널을 응용하면, 다수의 클라이언트가 스트림 통로를 상시 유지한 채 대기하고, 서버가 특정 이벤트 발생 시 채널 리스트를 순회하며 실시간 이벤트를 **브로드캐스팅(Broadcasting)**하는 Pub/Sub 인프라를 단순하고 가볍게 완성할 수 있습니다.
#### 1. 스키마 설계 (`protoapi.proto`)