From ba643fe013b8688c3709fc93e99b12356d437ee2 Mon Sep 17 00:00:00 2001 From: Godopu Date: Fri, 17 Jul 2026 16:12:29 +0900 Subject: [PATCH] docs: reform GRPC.md section 3 into formal textbook style --- docs/GRPC.md | 53 +++++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/docs/GRPC.md b/docs/GRPC.md index 8612a5b..28e2593 100644 --- a/docs/GRPC.md +++ b/docs/GRPC.md @@ -49,31 +49,46 @@ gRPC는 HTTP/2를 기반으로 구축된 구글의 고성능 오픈소스 원격 ## 3. 인터페이스 명세서 (`protoapi.proto`) -저장소 루트의 [protoapi.proto](../protoapi.proto) 파일은 앞서 설계한 `IoTService`를 구축하기 위해 아래와 같이 사양을 선언해 둡니다. +### 3.1 인터페이스 명세서의 개념 및 도입 목적 +인터페이스 명세서(Interface Description Document)란 시스템을 구성하는 상이한 노드나 기기들이 데이터를 어떠한 규격과 규약으로 상호 교환할지 사전에 조율하고 합의하여 기술해 둔 설계 문서입니다. gRPC 환경에서는 이를 프로토콜 버퍼(Protocol Buffers)의 `.proto` 파일 형식을 활용해 데이터 명세와 서비스를 통합 기술하는 IDL(Interface Description Language)로 구체화합니다. + +인터페이스 명세서를 강제하여 설계하는 목적은 다음과 같습니다: +1. **강력한 스키마 계약 강제(Schema Contract)**: 송수신할 데이터의 이름, 형태(타입) 및 지원 함수를 코드 레벨에서 선언적으로 봉인하여, 런타임 단계가 아닌 컴파일 단계에서 데이터 구조 불일치 오류를 완전히 원천 차단합니다. +2. **이종 스택/다국어 간의 원활한 호환성**: 하나의 명세서만을 공유하면, 번역 도구 체인을 통하여 Go, C++, Python, Java 등 서로 다른 소스 언어로 동작하는 클라이언트와 서버 기기들이 상호 간에 기술적 문맥 충돌 없이 원활하게 패킷 데이터를 해석하고 소통할 수 있게 유도합니다. +3. **효율적인 패킹을 통한 대역폭 절약**: JSON 등 텍스트 기반 통신 규약에 비해 바이너리 압축 포맷을 생성하는 메커니즘을 명세 단계에서 조율함으로써 패킷 용량을 극대화하여 낮추고, 분산 에이전트와 센싱 노드 간 통신 오버헤드를 경감합니다. + +### 3.2 인터페이스 명세서 설계 가이드 (작성 요령) +* **사양 정의**: 파일 최상단에 `syntax = "proto3";` 스펙 버전을 선언하고, 대상 플랫폼에 맞는 패키지 출력 경로(`go_package` 옵션 등)를 제공합니다. +* **원격 프로시저 선언**: `service` 블록을 구성하여 외부 단말이 호출을 제기할 수 있는 진입 함수군(RPC 메서드)을 정의하며, 입력과 반환값으로 매핑될 데이터 규격을 선언합니다. +* **메시지 직렬화 필드 정의**: `message` 블록을 선언하여 구조체 데이터를 정의합니다. 이때 필드값 뒤에 정의하는 식별자 번호(예: `= 1`, `= 2`)는 값을 대입하는 대입 연산자가 아니라, 컴퓨터가 데이터 직렬화 및 역직렬화 시 순서를 식별하는 **필드 번호 태그(Field Number Tag)**입니다. 한 번 릴리즈된 인터페이스의 태그 번호는 과거 하위 호환성을 보장하기 위하여 임의로 수정하거나 재사용해서는 안 되며, 확장 시 새로운 번호를 꼬리에 덧붙이는 전방향 호환성 설계를 준수해야 합니다. + +### 3.3 명세서 소스코드 및 구체적 분석 + +저장소 루트에 선언된 [protoapi.proto](../protoapi.proto) 명세서 코드는 앞서 기획한 `IoTService` 통신 구조를 수립하기 위해 다음과 같이 사양을 기재해 둡니다. ```proto syntax = "proto3"; option go_package = "./protoapi/;protoapi"; -// 1. 기기들이 통신할 서비스 창구(고객센터) 정의 +// 엣지 센싱 단말과 중앙 관리 서버가 연동할 원격 호출(RPC) 창구 정의 service IoTService { rpc GetDate (RequestDateTime) returns (DateTime); rpc UpdateSensingData (SensingData) returns (SensingResponse); rpc GetRandomPass (RequestPass) returns (RandomPass); } -// 2. 기기가 센서 값을 실어 보낼 포장 상자 (요청 데이터) +// 센싱 디바이스가 측정하여 전송할 환경 데이터 구조 message SensingData { - string DeviceId = 1; - double Temperature = 2; - double Humidity = 3; + string DeviceId = 1; // 기기 식별 고유 일련번호 + double Temperature = 2; // 수집된 대기 온도 센싱값 + double Humidity = 3; // 수집된 상대 습도 센싱값 } -// 3. 서버가 처리 결과를 알려줄 영수증 (응답 데이터) +// 데이터 수신 완료 및 가공 결과를 통보하는 응답 영수증 구조 message SensingResponse { - bool Success = 1; - string Message = 2; + bool Success = 1; // 트랜잭션 정상 반영 성공 여부 + string Message = 2; // 상태 상세 정보 안내 메시지 } message DateTime { @@ -94,22 +109,10 @@ message RandomPass { } ``` -### 💡 명세서의 핵심 규칙 쉽게 읽기 - -처음 명세서를 접하는 후배 개발자들을 위해 각 기호와 키워드가 뜻하는 바를 친절하게 설명해 줍니다: - -1. **`service IoTService` (통합 소통 창구)**: - * 기기(클라이언트)가 서버에게 요청할 수 있는 **기능 리스트**를 모아둔 일종의 '메뉴판'입니다. - * 그 안의 `rpc`는 **"원격에 있는 서버의 함수를 내 기기에 있는 함수처럼 직접 두드려 깨운다"**는 뜻의 약속(Remote Procedure Call)입니다. - * `rpc GetDate (질문 상자) returns (답변 상자)`: 서버 시계 물어보기 - * `rpc UpdateSensingData (질문 상자) returns (답변 상자)`: 센서 정보 보고하기 - -2. **`message SensingData` (포장 상자 구조)**: - * 기기가 서버에 보내는 정보 꾸러미입니다. 그 속에 `string DeviceId`, `double Temperature`, `double Humidity`라는 세 종류의 알맹이를 고이 담고 있습니다. - -3. **`= 1`, `= 2` (기본값 대입이 아닌 "고유 번호표" / 태그)**: - * 초심자가 가장 많이 헷갈려 하는 부분입니다! 이는 변수에 `1`이나 `2`라는 기본값을 집어넣는 수학적인 대입 연산자가 **아닙니다**. - * 기기와 서버가 통신 데이터를 매우 가볍고 압축된 이진 데이터(0과 1)로 빠르게 주고받기 위해, **"첫 번째 자리에 있는 데이터는 DeviceId이고, 두 번째 자리에 있는 데이터는 Temperature다"** 라고 컴퓨터끼리 정한 **순서 번호표(Tag Number)**입니다. 이 번호표는 이미 통신 중인 이전 버전의 기기들과 호환성을 유지해야 하므로, 명세서 개정 시 한 번 지정한 번호를 마음대로 바꾸거나 중복 사용해서는 안 됩니다. +#### 명세 구조의 구성 분석 +* **`IoTService`**: 센서 단말이 중앙 관제소(서버)에 접근하여 실행 가능한 세 가지 원격 서비스의 인터페이스 스펙을 나타냅니다. 기기는 서버 시계를 연계 조회(`GetDate`)하거나, 측정값을 안전하게 전달(`UpdateSensingData`)하고, 암호 세션 비밀번호 발급(`GetRandomPass`)을 동기식으로 호출할 수 있습니다. +* **`SensingData`**: 실제 환경에 노출된 IoT 단말 기기의 정보를 포장하여 송신하기 위한 데이터 모델입니다. 기기 식별을 위한 식별자(`DeviceId`) 및 물리 센서 측정 변수(`Temperature`, `Humidity`)를 순서 번호 태그 1, 2, 3으로 매핑하여 순서가 흐트러지지 않도록 보장합니다. +* **`SensingResponse`**: 서버가 수신 데이터를 트랜잭션 처리한 결과를 다시 단말로 되돌려주기 위한 수신 회신 메커니즘입니다. 통신 처리 및 갱신의 안전한 성패 지표(`Success`) 및 원격 디버깅을 위한 가시적인 스트링 로그(`Message`)를 캡슐화해 줍니다. ---