반업주부의 일상 배움사

옵저버블 플러터: gRPC :: ChatGPT 정리 본문

IT 인터넷/일반

옵저버블 플러터: gRPC :: ChatGPT 정리

Banjubu 2023. 3. 24. 08:49
반응형


> English Summary

> English Full Text

 

[ 요약 ]

옵저버블 Flutter에서 크레이그 르벤스와 함께 Somnio Software의 공동 창립자이자 CTO인 지안프랑코 파파가 GRPC의 강력한 기능을 설명합니다.
Google에서 개발한 원격 프로세스 호출 시스템인 GRPC와 이를 Dart에서 구현하는 방법에 대해 알아보세요.
Flutter 전문가인 지안프랑코는 커뮤니티에서의 경험과 2018년 베타 버전 이후 Flutter의 성장에 대해 공유합니다.
이 Dart 중심 개념에 대해 자세히 알아보고 프로젝트를 향상시킬 수 있는 방법을 살펴보세요.

Dart에서 풀 스택 앱을 만들기 위한 다용도 도구인 GRPC의 강력한 기능을 활용하세요.
Dart에 능숙한 Flutter 개발자는 이제 언어를 전환하지 않고도 프론트엔드 및 백엔드 애플리케이션을 모두 개발할 수 있습니다.
Dart Frog 및 Shelf와 같은 다른 도구도 존재하지만 GRPC는 다양한 프로그래밍 언어와의 원활한 통합을 제공합니다.

GRPC의 언어 간 호환성은 업계의 판도를 바꾸고 있습니다.
풀 스택 Dart 애플리케이션으로 클래스를 재사용하고 중복된 로직을 최소화하세요.
백엔드에서 Dart를 사용할 수 없더라도 GRPC는 JavaScript, Python, Java와 같은 여러 언어로 자동 생성된 바인딩을 통해 언어 장벽을 뛰어넘는 커뮤니케이션을 간소화합니다.

또한 GRPC의 기반이 되는 프로토버프를 마스터하는 것은 일상 업무에 프로토버프가 필수적이기 때문에 Google에서 일하고자 하는 사람들에게 자산이 될 수 있습니다.
따라서 풀 스택 Dart 애플리케이션에 GRPC의 잠재력을 활용하고 개발 기술을 새로운 차원으로 끌어올리기 위한 첫걸음을 내딛으세요.

이 프로젝트는 프론트엔드(Flutter로 빌드), 백엔드(gRPC 사용), 프로토콜 버퍼를 위한 공유 폴더 "Protos"의 세 가지 폴더로 구성됩니다.
이 접근 방식의 주요 장점 중 하나는 프론트엔드와 백엔드 간에 코드를 재사용할 수 있어 개발 및 유지 관리를 간소화할 수 있다는 것입니다.
시작하려면 공식 gRPC 문서를 검토하고 프로토콜 버퍼에 익숙해지는 것이 좋습니다.
그런 다음 gRPC와 Dart를 사용하여 풀스택 앱을 만들어 보세요.

Dart를 사용하여 프로토콜 버퍼 모델을 생성하려면 다음 단계를 따르세요:

1. "프로토콜" 폴더를 생성합니다.
2. "프로토콜" 폴더 안에 lib 폴더가 있는 패키지를 생성합니다.
3. 3. 패키지에 필요한 종속성(protobuf 및 gRPC)을 추가합니다.
4. lib 폴더 안에 "protos" 폴더를 생성합니다.
5. "protos" 폴더 안에 .proto 파일(예: todo.proto)을 생성하여 모델을 정의합니다.
6. "메시지" 키워드를 사용하여 클래스와 유사한 구조를 정의합니다.
7. 이름과 증분 정수 코드가 포함된 특수 표기법을 사용하여 속성을 정의합니다.

구문 세부 사항과 예제는 프로토버프 설명서를 참조하세요.
"메시지" 키워드는 다른 언어의 "클래스" 키워드와 유사하지만 컴퓨터 간에 전송할 수 있는 데이터를 정의하는 데 사용된다는 점을 기억하세요.
GRPC와 Protobuf를 사용하여 프론트 엔드와 백엔드 서비스 간에 메시지를 효율적으로 교환하세요.
이러한 기술은 메시지 크기를 줄이고 바이너리 형식으로 데이터를 전송하여 JSON보다 더 효율적입니다.
proto3 구문과 int32와 같은 기본 유형을 사용하여 첫 번째 메시지를 정의하는 것으로 시작하세요.
인코딩을 위해 각 필드에 고유한 증분 값을 할당합니다.
이 예제에서는 ID, 제목, 완료 상태가 포함된 할 일 메시지를 만듭니다.

Protobuf의 강점은 Dart와 같은 다양한 언어로 모델을 자동 생성할 수 있다는 점입니다.
이를 통해 여러 팀과 프로그래밍 언어 간에 모델을 원활하게 공유할 수 있으므로 모델에 대한 단일 소스를 구축할 수 있습니다.

아래에 요약된 단계를 따라 Dart를 사용하여 프론트엔드 및 백엔드를 위한 공유 패키지를 생성하시기 바랍니다:

1. 생성된 클래스를 위한 새 폴더를 생성합니다.
2. proto C 플러그인을 다운로드하고 활성화한 다음 경로를 내보냅니다.
3. proto C 명령줄을 사용하여 프로토 파일에서 Dart 클래스를 생성합니다.
4. 라이브러리에서 생성된 파일을 내보냅니다.
5. 불필요한 예제를 제거합니다.
6. 모델을 정의하고 프론트엔드 및 백엔드에서 패키지를 공유합니다.
7. 별도의 백엔드 패키지를 생성합니다.
8. 서버에 콘솔 앱 템플릿을 사용합니다.
9. 프로토콜 패키지를 서버 폴더로 가져옵니다.

이 단계를 수행하면 할 일 개체에 액세스할 수 있으며 프런트 엔드와 백엔드 간에 패키지를 효율적으로 공유할 수 있습니다.

서비스를 생성하려면 ToDoServiceBase를 확장하고 메서드를 재정의하여 서비스 클래스를 구현해야 합니다.
지금은 하드 코딩된 ToDo를 반환할 수 있습니다.
이름 매개변수를 사용하거나 프로토 버프에서 빈 매개변수가 있는 기본 구현을 사용할 수 있습니다.
ID 매개변수의 경우 새 매개변수를 생성하는 대신 요청에서 가져올 수 있습니다.
완성된 패턴이 없으므로 거짓으로 설정하고 리스팅 제목을 기반으로 제목을 제공합니다.
마지막으로 추적 키워드를 추가하고 서버 내부에서 이 서비스를 사용해야 합니다.
모든 작업을 완료하려면 현재 사용 가능한 웹 애플리케이션에서는 jrpc가 잘 작동하지 않으므로 Android iOS 및 macOS용 템플릿을 사용하여 Flutter에서 클라이언트 앱을 만들어야 합니다.

서버를 시작하려면 "dart server.dart"를 실행하고 포트 8080에서 수신 대기 중인지 확인합니다.
모든 것이 제대로 작동하는지 테스트하려면 macOS에서 랩을 실행하거나 iOS/Android에 맞게 조정하세요.
GRPC를 사용하면 서버에서 클라이언트로 스트리밍할 수 있습니다.
이제 GRPC를 지원하는 Postman을 테스트에 사용하세요.
소켓과 관련된 오류가 발생하면 Xcode를 열고 구성에서 특수 매개 변수를 구성합니다.


Flutter에서 GRPC를 사용해도 블록이나 리버 포드와 같은 상태 관리 솔루션에 영향을 미치지 않습니다.
또한 메시지는 클래스보다는 구조체에 가깝습니다.

새 속성을 추가하거나 선택적 필드를 필수 필드로 변경하는 등 API를 변경할 때는 변경 사항을 버전 관리할 것을 권장합니다.
이 작업은 다른 언어를 사용할 수 있는 마이크로서비스 아키텍처에서 유용한 프로토버프를 사용하여 수행할 수 있습니다.
서버를 업데이트하려면 클라이언트 앱도 업데이트해야 합니다.
마이크로서비스 아키텍처에서는 한 번에 모두 업데이트할 필요가 없는 서비스 전반의 업데이트를 처리하기 위한 전략을 세우는 것이 중요합니다.
Google에서는 업데이트를 효과적으로 처리하기 위해 필수 필드를 사용합니다.

이 기술을 더 자세히 살펴보고 싶으시다면 한번 사용해 보시기 바랍니다.

 

 

반응형

 

 


Observable Flutter: gRPC
https://www.youtube.com/watch?v=jCbclWBV32o 

 

 






[ 한글 전체 ]

안녕하세요, 여러분. 옵저버블 플러터의 또 다른 에피소드에 오신 것을 환영합니다. 언제나처럼 제가 진행을 맡았습니다,
언젠가 다른 사람이 진행하게 될지도 모르는 크레이그 르벤스입니다. 지금까지는 늘 그랬듯이요. 어쨌든
오늘은 GRPC에 대해 여러분과 이야기를 나누게 되어 매우 기쁩니다.
Google 원격 프로세스 호출의 약자입니다. Google에서 개발한 것으로 알고 있습니다. 아마 제 게스트가
가 G가 무엇을 의미하는지 정확히 설명해 줄 수 있을 것 같은데, 저는 이 문장을 시작하면서 깨달았습니다,
실제로 찾아본 적이 없거든요. 그냥 짐작만 했죠. 하지만 너무 깊이 들어가기 전에
옵저버블 플러터에서 우리는 서로에게 매우 친절하다는 점을 상기시키고 싶습니다.
서로에게. 이것이 바로 Flutter 커뮤니티입니다. 우리의 좋은 이름에 걸맞게 살자고요. 좋아요. 그리고 제 게스트는
우루과이에 있는 솜니오 소프트웨어의 공동 창립자이자 CTO인 존 프랑코입니다. 많은 분들이
트위터에서 Flutter 커뮤니티의 유쾌한 존재이자 모든 면에서 훌륭한
소프트웨어 엔지니어로 알고 계실 겁니다. 존 프랑코와 함께하게 되어 정말 기쁩니다. 환영합니다.
안녕하세요, 크레이그? 잘 지내죠. 저도 잘 지내죠. GRPC에 대해 이야기하게 되어 매우 기쁩니다.
원하신다면 기술 및 Flutter에서의 경력에 대해 몇 마디 말씀해 주실 수 있을까요?
몇 마디 해주시겠어요? 그리고 어떻게 여기까지 오게 되었나요? 네, 물론이죠. 좋아요, 먼저
초대해 주셔서 감사합니다. 정말 기대돼요 쇼를 볼 거예요 쇼의 일부가 된다는 게
정말, 정말 흥분됩니다. 네, 제 소개를 해도 될까요? 저는 존 프랑코입니다,
아빠이고, 솜니오 소프트웨어의 CTO이자 공동 설립자입니다. 그리고 네, 저는 소프트웨어 엔지니어입니다.
소프트웨어 엔지니어입니다. 저는 이 기술을 정말 사랑합니다. 또 다른 이유는 무엇인가요? 저는 라틴 아메리카 우루과이에서
라틴 아메리카의 우루과이에서 커뮤니티를 성장시키고 있습니다. 그리고 저는 Flutter 우루과이의 주최자이기도 합니다. 그렇군요
정말 멋지네요. 그리고 네, 저희 회사에서는 기본적으로 Flutter를 전문적으로 취급하는
전문 업체입니다. 저희는 이 기술에 100% 집중하고 있습니다. 그래서 네, 저희는 Flutter가 처음 만들어질 때
Flutter가 실제로 만들어졌을 때입니다. 2018년에 베타 버전으로 시작했죠. 그리고 계속 프로젝트를 진행하면서
프로젝트에서 계속 일하면서 이것이 큰 일이라는 것을 깨달았습니다. 그래서 그렇게 시작하게 되었습니다. 우리는
기본적으로 이 기술을 신뢰했습니다. 당시에는 모바일 앱으로 작업하고 있었죠. 하지만
지금은 웹과 데스크톱에서 작업할 수 있습니다. Flutter가 모든 종류의 프로젝트에서 작업할 수 있도록
모든 종류의 프로젝트에서 작업할 수 있는 문이 계속 열리고 있습니다. 네, 좋아요. 몇 번의 행사에서 만난 적이 있는 것으로 알고 있습니다.
그리고 저는 항상 초기 베타 버전까지 거슬러 올라가는 사람들을 만나서 이야기하는 것을 좋아합니다,
저도 그렇거든요. 저는 Flutter가 1.0으로 전환된 직후에 알게 되었습니다. 그러니 저보다 더 오래
저보다 더 오래 사용하셨군요. 하지만 오늘은 Flutter에 대해서만 이야기하는 것이 아닙니다. 우리는 실제로
좀 더 다트 중심적인 개념에 대해 이야기하려고 합니다. 개념 자체는 Dart보다 더 큰 개념이지만
GRPC인 Dart에서 구현할 예정입니다. 지안프랑코, 이 에피소드 아이디어를 저에게 제안한 건
바로 관찰 가능한 Flutter가 시작되었을 때였죠. 그래서 즉시
GRPC에 대해 이야기하고 싶다는 것을 바로 아셨군요. 일반 개발자들이 왜 이 아이디어에 동의해야 하고
GRPC에 대해 관심을 가져야 하는 이유에 대해 설명해 주세요. 네, 좋아요. 네, 예, 제가 기억하기로는
옵저버블 플러터가 쇼가 되기 전에도, 우리는 어쩌면 지루할 수도 있는
쇼. 제가 GRPC에 대해 이야기해달라고 한 이유는 그때 풀 스택 앱에 대한 비디오를 본 것 같아요.
풀 스택 앱에 대한 비디오를 본 것 같습니다. 네, GRPC의 장점은 도구 세트에 포함할 수 있는 또 다른
도구 세트에 포함될 수 있는 또 다른 도구라는 것입니다. 왜냐하면
Dart만 사용하여 프론트 엔드와 백엔드를 만들 수 있습니다. 그리고 그것은 정말
이미 Dart에 대해 많이 알고 있고 백엔드 애플리케이션을 만들고자 하는 Flutter 개발자에게
백엔드 애플리케이션도 만들 수 있습니다. 그리고 다른 언어로 전환하고 싶지 않겠죠?
하지만 Dart에서 백엔드를 만들 수 있는 다른 도구가 있다는 것을 모두 알고 있습니다,
예를 들어 Dart Frog나 Shelf와 같은 도구가 있죠. 하지만 GRPC의 경우 조금 다르다고 생각합니다.
왜냐하면 Dart에서 백엔드를 만들 수 있을 뿐만 아니라 다른 프로그래밍
언어도 원활하게 사용할 수 있습니다. 그래서 예, 그것은 우리가 그것을 볼 것이기 때문일 것이지만 기본적으로 할 수 있습니다,
GRPC는 다양한 언어를 지원합니다. 그리고 기본적으로 자동 생성을 할 수 있습니다.
프라다버프라고 하는 것을 사용하면 어떤 언어를 타겟팅하든 자동 생성할 수 있습니다. 그래서
어떤 의미에서는 언어에 구애받지 않는 것과 비슷합니다.
네, 크로스 언어 부분은 매우 중요한 부분입니다.
개발자가 전체 스택을 보유함으로써 얻을 수 있는 가치와 같은 것이기 때문입니다.
다트 애플리케이션은 여러 클래스를 재사용할 수 있고 로직을 중복할 필요가 없으며
뭐 그런 거죠. 그리고 GRPC를 사용하더라도 양쪽 끝에 Dart가 있으면
최상의 시나리오를 만들 수 있습니다. 하지만 어떤 이유로든 백엔드에서
백엔드에서 Dart를 사용할 수 없다면 오늘은 백엔드에서 Dart를 사용하겠습니다. 하지만 만약
바인딩이 양쪽 끝에서 다양한 언어로 생성되기 때문입니다.
백엔드에서 자바스크립트, 파이썬, 자바 등 다양한 언어로 생성되기 때문입니다,
언어 장벽을 넘어 자신과 소통하는 작업이
훨씬 간단해집니다. 왜냐하면 말씀하신 간단한 프로토버프 정의부터 시작해서,
모든 것이 거기서 빠져나오기 때문입니다. 그나저나 혹시 구글에서 일하고 싶으신 분들 중
구글에서 일하고 싶고, 구글에 지원하고 싶다면 프로토버프와 같은 친숙함이 모든 구글 개발자에게 필요합니다.
Google 개발자가 매일 사용하는 모든 것이 프로토버프와 그 다운스트림에서 생성된 코드에서 실행됩니다.
방금 생성 된 코드입니다. 그러니 다음 직업을 위해
다음 직업을 위해서요. 좋아요, 존 프랑코, 이제 몇 가지 시작 단계를 안내해 주실 준비가 되셨을 것 같은데요.
몇 가지 단계를 안내할 준비가 된 것 같네요. 그렇죠? 네, 준비합시다. 그럼
완벽해요 좋아요, 오늘 제 아이디어는 그렉과 의논한 건데
아주 처음부터, 아주 간단한 거지만
네, 그리고 아이디어는 처음부터 만드는 것이므로 정말 멋진 것은 아닙니다. 하지만 그렇죠,
우선, 저는 여기에 문서를 열어두고 싶었습니다.
그 gRPC는 정보가 너무 많고 개와 같은 주제가 아니거나 그렇게 같지 않습니다.
휴식과 같은 일반적인 것, 맞죠? 하지만 네, 여기에 문서가 있으므로 언제든지 가서들을 수 있습니다.
공식 문서. gRPC는 최신 오픈소스 고성능 원격 프로시저 코드입니다,
따라서 원격 프로시저 코드는 우리가 사용할 프로토콜이 될 것입니다.
또는 웹소켓이 있습니다. 여기서는 RPC를 사용하겠습니다. 그리고 g가 Google에 적합하다고 생각합니다,
맞죠? 사실 그 질문은 안 해봤는데 아마 구글 때문일 것 같지 않나요?
저도 그렇게 생각했습니다. 랜달은 이것이 건방진 재귀 알고리즘이나 약어 중 하나라고 말합니다.
알고리즘이나 약어 중 하나일 뿐이라고 하더군요. 그래서 공식적으로 g는 구글을 위한 것이 아니라 그냥 무의미하다고 생각해요.
하지만 구글이 만든 것이기 때문에 의미 없는 글자를 골랐다면,
구글이 g를 골랐다고 해서 놀랄 일도 아니죠. 네, 말이 되네요. 자, 이제
시작하세요. 우리에게는 많은 언어가 있습니다. 물론 어두운 색을 선택하겠죠? 하지만 여러분은
정말 일반적인 언어를 가지고 놀 수 있습니다. 그리고 네, 또 하나 보여드리고 싶은 것은
제가 보여드리고 싶은 또 다른 것은 빠른 인트로입니다. 여기에는 예, 인트로가 있습니다.
정말 타이트한 프로토콜 버퍼에 대해서도 이야기할 것입니다. 여러분은 프로토콜 버퍼를
프로토콜 버퍼를 REST용 JSON이라고 생각하시면 됩니다. gRPC용 프로토콜 버퍼는 일종의
정보를 전달하는 방식은 동일합니다. 하지만, 네, 저희는 이 용어를
더 잘 설명해드리겠습니다. 그래서 그 부분만 보여주고 싶었습니다. 어쩌면 우리는 어떤 것들에 대한
문서화할 수도 있지만, VS 코드로 전환해서 처음부터 풀 스택 앱을
풀 스택 앱을 처음부터 만들려고 합니다. 그래서 네, 제가 가장 먼저 이야기하고 싶은 것은
프로토콜 버퍼입니다. 프로토콜 버퍼를 만드는 것으로 프로젝트를 시작할 수 있을 것 같거든요,
프로토콜 버퍼의 줄임말 같은 거죠? 그리고 네, 제 아이디어는 세 가지 다른 폴더를 만드는 것입니다.
폴더를 만드는 거죠? 하나는 Flutter에서 만들 프론트엔드용이고, 다른 하나는 백엔드용입니다.
백엔드용 폴더, 그리고 또 다른 폴더는 공유 폴더가 될 것입니다.
프로토스라고 부르지만 백엔드와 프론트엔드에서 모두 사용할 것입니다. 그리고 이것이 바로
프론트엔드와 백엔드 사이에서 많은 코드를 재사용할 수 있다는 장점입니다.
정말 마음에 들어요. 네 완벽해요. 자, 이제 터미널에서 프로젝트를 만들어 보겠습니다,
프로젝트를 만들겠습니다. 저는 항상 템플릿이 무엇인지, 기본 템플릿이 무엇인지 잊어버립니다. 그래서,
서버 선반을 원하십니까? 아니요, 사실 프로토콜 패키지부터 시작하겠습니다. 그럼
패키지를 선택하겠습니다. 그러면 모든 제품 버퍼 파일을 저장할 수 있습니다. 좋아요, 그럼
템플릿 패키지를 사용하여 생성할 거죠? 아, 디렉토리를 만들 수 있을 것 같습니다.
디렉토리를 만들 수 있습니다. 좋아요, 그럼 프로토콜 폴더를 만들어 보겠습니다. 그런 다음 프로토콜로 이동할 수 있습니다. 그리고 여기
패키지를 만들 수 있겠죠? 이 디렉터리에서 패키지를 누르면 강제로
이것. 여기에는 정말 간단한 순수 다트 패키지가 있습니다. 이제 테스트 폴더를 삭제할 수 있습니다.
폴더를 삭제할 수 있습니다. 조만간 폭발할 것 같지 않나요?
네, 정말 멋지네요. 프로토버프에 대한 테스트를 작성하지 않는 이유는 다음과 같습니다.
테스트가 잘 되어 있으니까요. 모델을 제대로 정의하지 않은 게 아니라면 그렇겠죠.
그렇군요. 이 폴더를 테스트하고 있는 것 같네요.
네, gRPC의 작동 방식을 불신하고 있는 것 같네요, 그렇죠? 아니면 프로토버프도 그렇고요.
그렇군요. 자, 여기 예제에 lib 폴더가 있습니다. 가장 먼저 해야 할 일은
실제로 의존성을 파악하는 것이죠? 그래서 우리는 protobuf와 gRPC를 사용할 것입니다.
PubDep에서 볼 수 있는 Dart 패키지입니다. 이제 모든 것이 제자리에 있는지 확인해 봅시다.
제자리에 있는지 확인해 봅시다. 자, 여기 종속성이 있습니다. 여기에 종속성을 넣겠습니다. 이제 끝났죠?
좋아 보이네요. 완벽하네요. 자, 이제 첫 번째 프로토 파일을 만들려면
프로토 파일이라는 폴더를 만들 수 있습니다.
그리고 여기서 프로토콜 버퍼 모델의 첫 번째 정의를 만들 수 있습니다.
그리고 기본적인 할 일 파일을 생각하고 있었는데, 아무거나 선택할 수는 없겠죠? 그것은 여러분이 무엇을
의존할 수 있습니다. 하지만 할 일부터 시작하겠습니다. 확장자는 프로토가 되겠죠?
이제 여기서 모델의 프로토타입을 정의하기 시작할 수 있습니다. 그럼
프로토타입의 기본 구문을 볼 수 있도록 문서로 돌아가 보겠습니다. 그럼
프로토콜 작성자를 검색해서 별도의 문서를 찾아보겠습니다.
하지만 여기서는 프로토버프를 사용하여 모델을 생성하기 위해 사용해야 하는 구문을 설명하겠습니다.
모델을 만들기 위해 사용해야 하는 구문입니다. 예를 들어 할 일 클래스를 만들고 싶다면
메시지라는 키워드를 사용해야 합니다. 그리고 모든 속성을 정의하려면
프로퍼티의 이름을 정의하는 특별한 표기법을 사용해야 합니다.
그리고 코드가 필요합니다. 이 코드는 증분 적분과 같은 것입니다.
그리고 메시지 키워드는 기본적으로 다른 언어의 키워드 클래스와 비슷합니다.
키워드 클래스 같은 거죠? 하지만 여기서는 메시지로 작성된 이유는 GRPC의 전체 아이디어가
이 데이터를 유선으로 가져올 수 있는 기능이기 때문이죠? 이 데이터를 다른 곳으로 보내는 방법. 그래서
GRPC는 이 모든 것을 메시지로 생각합니다. 한 컴퓨터에서 시작된 데이터는
다른 컴퓨터로 이동합니다. 하지만 키워드 클래스와 정말 비슷합니다,
키워드 클래스와 정말 비슷하죠. 네, 그럴 수도 있습니다. 그래서, 네, 문제는
연결하기 위해서는 효율적인 방식으로 메시지를 교환해야 합니다,
GRPC, 프로토부프, 죄송합니다만, 우리가 서비스를 통해 전달하는 메시지의 전체 개념이
프론트 엔드와 백엔드를 통해 전달되는 메시지의 전체 개념을 줄입니다. 따라서 더 효율적일 수 있습니다.
크기 면에서 더 효율적일 수 있습니다. 왜냐하면 JSON을 아신다면 아마 아시겠지만
정말 읽기 쉽습니다. 하지만 유선으로 전달하는 것은 그렇게 효율적이지 않습니다. 따라서 이 경우에는
읽기 쉬운 것을 줄이는 것이 아니라, 앞뒤로 전달하는 것이 정말 효율적일 것입니다.
좋아요, 그럼 할 수 있겠네요. 아, 죄송해요. 방금 말하려던 건, JSON은 시간이 너무 많이 걸린다는 거였어요,
괄호나 따옴표, 따옴표로 공간을 너무 많이 낭비하죠.
그냥 원시 문자열처럼 보내는 거죠. 그리고 GRPC는 바이너리 형식으로도 전송합니다. 그래서
엄청나게 효율적이죠. 맞아요. 이제 첫 번째 메시지를 정의할 수 있습니다. 그럼
이 예제를 복사하여 붙여넣겠습니다. 여기서는 프로토 3 구문을 사용하겠습니다.
그리고 여기에서는 이름을 바꿔서 작성할 수 있습니다. 이 부분을 제거할 수도 있습니다.
따라서 편리하게 문서를 보관하고 싶으시다면, 저희는 다양한 유형의
제품 앱이 지원하는 유형이 있습니다. 하지만 유형을 검색하고 있습니다.
좋아요, 전체 값입니다. 스칼라 값 유형. 아니요, 여기 전체 목록에 나와 있네요.
그래요 모든 유형이 표시된 단일 목록을 찾고 있는 거군요.
그렇군요. 네, 맞아요 네, 이게 전체 목록입니다. 네, 아마도, 아마도 섹션이있을 것입니다.
모든 타입의 값을 실제로 검색할 수 있는 섹션이 있을 수도 있습니다. 하지만 그건 문제가 되지 않습니다. 제 말은
여기서는 기본 유형을 사용할 거니까요. ID에 32를 사용하겠습니다. 따라서 프로퍼티의 이름을
프로퍼티의 이름을 정의하고 증분값이 될 실제 값을 정의하는 것을 잊지 마세요.
이것은 단지 정보를 인코딩하기 위한 것입니다. 그리고 기본적으로 필드의 순서는 맞죠?
그 이상도 이하도 아닙니다. 그렇군요. 물론이죠. 그러니까, JSON에서처럼
이렇게 읽으면 됩니다. ID는 키 값과 같은 이 필드가 될 것입니다. 그리고 이
는 ID만 있고 다른 것은 없습니다. 그리고 네, 이것은
고유해야 합니다. 맞습니다. 그 외에 제목을 정의할 수 있습니다. 그래서 이것이 두 번째가 될 것입니다.
그리고 이것이 완료되었는지 여부를 말할 수 있는 다른 유형을 사용할 수 있습니다. 맞습니다.
이것은 본질적으로 할 일 메시지에 대한 정의와 같습니다. 맞습니다. 그리고 우리는 이것을
프로토 버퍼 표기법에서 볼 수 있습니다. 하지만 이것의 멋진 점은 우리가 실제로 이것을
Dart에서 자동으로 생성한다는 것입니다. 어떤 언어로든 가능하지만 저희는 Dart를 사용하고 있습니다.
따라서 프런트엔드 팀뿐만 아니라 다음과 같은 사람들과도 모델을 공유할 수 있습니다.
할 일의 정의를 구현하고자 하는 모든 사람과 공유할 수 있습니다. 따라서 이것은 정말
모델에 대한 신뢰할 수 있는 단일 소스를 확보할 수 있는 궁극적인 솔루션인 셈이죠. 맞습니다.
전체 모델을 수많은 짝수 언어, 프로그램 언어와 공유할 수 있기 때문입니다.
그리고 우리는 정말 많이 쓰지 않았죠. 이 할 일 클래스를 간결하게 정의하면 다음과 같습니다.
클래스입니다. 저도 그렇게 부를게요. 물론이죠. 물론이죠 자, 여기서 우리가 해야 할 일은
생성될 다른 폴더를 만드는 것입니다. 그리고 라이브러리의 일부로 이것을 제거 할 수 있습니다.
필요 없을 겁니다. 그렇게 하세요. 그리고 여기, 좋아요, 여기, 나중에 내보낼 수 있습니다. 그리고 우리 라이브러리,
여기서는 생성된 클래스를 실제로 내보낼 것입니다. 그래서 아이디어는 다운로드할 수 있는 proto
C 명령을 다운로드하는 것입니다. 설정은 생략하지만, 이 설정을 사용하면
이 설정을 사용하세요. 어디 보자. 이것에 대한 빠른 시작이 있습니다. 하지만 좋아요. 그럼 실제로 검색해 보겠습니다.
빠른 시작. 기본적으로 여기서는 프로토 C 플러그인을 다운로드하고 활성화한 다음
경로를 내보내야 합니다. 그런 다음 proto C 명령줄을 사용하여 이 프로토 파일을 생성할 수 있습니다.
이 프로토 파일을 생성합니다. 이 명령은 기억하기 어렵기 때문에 복사하겠습니다. 그래서
라고 말할 수 있지만, 여기서는 프로토 C를 사용하고 있습니다. Dart 출력은 생성된 폴더가 될 것입니다.
기본적으로 proto 폴더 아래에 있는 모든 파일을 가져옵니다. 모든 파일입니다. 그리고 우리는
다트 클래스를 자동 생성하고 있습니다. 따라서 엔터키를 누르면 여러 개의 클래스가 생성됩니다.
생성됩니다. 가독성은 떨어지지만 중요한 것은 Dart에 모델이 있고
사용할 수 있다는 것입니다. 이제 실제로 여기에 할 일을 할 객체를 만들 수 있습니다,
좋아요. 좋아요. 이제 여기서 할 수 있는 일은 실제로 내보내는 것입니다,
라이브러리에 있는 모든 파일을 내보내는 것입니다. 이 파일에서 내보낼 수 있습니다. 그래서, 그것은
소스, 생성. 그리고 필요할 경우를 대비해 다른 파일도 내보낼 수 있습니다.
하지만 모든 것이 아, 그건 아니고 JSON이라는 것을 알게 될 것입니다.
좋아요. 그래서 여기서 우리가 한 일은 예제를 제거해야 할 수도 있다는 것을 정의한 것입니다.
이제 모델에 대한 정의를 정의했고, 프론트엔드에서 이
패키지를 프론트 엔드와 백엔드에서 공유할 수 있으며, 할 일 객체에 액세스할 수 있게 되겠죠?
좋아요. 지금 당장 할 수 있는 또 다른 일은 백엔드를 별도의
패키지입니다. 네, 좋아요. 완벽하네요. 이제 전체 설정으로 돌아가서 이번에는 서버를 만들 수 있습니다.
서버를 만들 수 있습니다. 좋아요, 다른 폴더를 만들겠습니다. 그리고 여기에 이 폴더로 들어가면
다른 템플릿을 사용하고 싶습니다. 왜냐하면 이것은 우리가 프론트 엔드에서 가져올 수 있는 패키지가 될 것이기 때문입니다.
프론트엔드에서 가져올 수 있는 패키지가 되겠지만 콘솔 앱을 사용하여 메인 서버를 시작할 수 있습니다.
좋아, 이것이 실제로 기본 템플릿이 될 것입니다. 따라서 생성 시작을 누르면
템플릿을 지정하는 대신 기본 템플릿을 사용할 수 있습니다. 그리고 이 템플릿을 강제로
이 폴더, 서버 폴더에 생성되도록 할 것입니다. 자, 여기 프로젝트가 있습니다.
이제 프로토콜 패키지를 서버 폴더로 가져올 수 있습니다. 그럼
사용을 시작할 수 있겠죠? 이 패키지는 로컬에 있는 패키지이기 때문에 기본적으로
기본적으로 경로를 제공해야 합니다. 그리고 실제로 프로토콜 폴더에서 경로를 가져와서
폴더에서 경로를 가져옵니다. 알겠습니다. 좋아요. 좋아요. 오, 게시하지 않음으로 추가해야 합니다.
정말 빨리요. 그럼 경고가 없어지네요. 알았어요 완벽해요 좋아요. 그래서 여기서 아이디어는
계산 메서드가 있기 때문에 이것도 폭발할 수 있다는 것입니다.
그리고 bin 안에는 메인 함수가 있는 server.dart가 있습니다. 하지만 여기서 우리가 실제로 하고 싶은 것은
실제로 하고 싶은 것은 gRPC 서버를 만드는 것입니다. 따라서 누구나 클라이언트를 사용해 gRPC 서버에 연결할 수 있습니다.
연결할 수 있습니다. 그리고 예, 우리가 언급하지 않은 것 중 하나는 이 프로토콜의 멋진 점은
이 프로토콜의 멋진 점은 프론트엔드에서 직접 호출하는 것처럼 원격 함수를 호출할 수 있다는 것입니다.
호출할 수 있다는 것입니다. 따라서 정말 원활한 커뮤니케이션이 될 것입니다. 우리는 그것을 보게 될 것입니다,
하지만 Flutter 앱에 있을 때는 서버를 호출하는 것과 같습니다.
프론트엔드 프로젝트에 있는 함수를 호출하는 것과 같습니다. 정말 멋질 것 같습니다. 여러분은
HTTP 요청을 생성하고 파싱할 필요가 없습니다. 그냥 함수를 호출하기만 하면 됩니다.
호출하기만 하면 됩니다. 그렇죠. 자, 여기 메인 파일이 있습니다. 이제 서버를 생성하겠습니다.
이 부분의 속도를 높이기 위해 가져온 코드 중 일부입니다. 빨리 복사해서
이걸 복사해서 붙여넣겠습니다. 좋아요, 기본적으로 서버를 정의해야 합니다. 지금은 이 부분을 지우겠습니다.
이 서버는 GRPC 라이브러리에서 가져올 것입니다. 이 라이브러리도 설치해야 합니다.
라이브러리도 설치해야 합니다. 실제로 프로토 라이브러리에서 내보낼 수 있습니다.
어디 보자. GRPC 패키지도 내보낼 수 있습니다. 이제 서버에서 사용할 수 있습니다. 그래서
여기로 가면 서버를 만들 수 있습니다. 그런 다음 포트에서 서버를 실행해야 합니다. Let's
해봅시다. 왜 그런지 모르겠어요. 그래요. 기본적으로 환경에서 포트를 검색하거나
또는 기본값으로 8080 포트를 사용할 수 있습니다. 그리고 나서, 네, 우리는
대기 중이므로 이 함수의 이름을 비동기로 지정해야 합니다. 마지막으로 서버에서 간단히 인쇄할 수 있습니다.
8080 포트에서 수신 대기 중이죠? 따라서 이 가져오기를 사용할 필요가 없는 것 같습니다.
그게 다입니다. 이것은 우리의 전체 서버, 우리가 연결할 전체 GRPC 서버와 같습니다.
서버 전체와 같습니다. 그리고 한 가지, 지금 보이지 않는 매개변수 하나가 바로 이 배열입니다. 이
는 서비스 배열이 될 것입니다. 이것은 우리가 지금까지 실제로 이야기하지 않은 부분입니다. 그래서
이제 서비스에 대해 이야기할 수 있을 것 같죠? 왜냐하면 지금까지는
모델. 메시지 말이죠. 맞아요. 메시지요. 하지만 GRPC와 통신하기 위해 프론트엔드에서 호출할 함수도 정의해야 합니다.
프론트엔드에서 호출할 함수도 정의해야 하죠? 그러기 위해 우리는 우리의
프로토 파일로 돌아갑니다. 그리고 메시지를 정의하는 대신 이번에는 인터페이스와 거의 비슷한 서비스를 정의하겠습니다.
구현해야 하는 인터페이스와 거의 비슷할 것입니다. 하지만 여기서는
GRPC와 통신하는 데 사용할 모든 메서드를 정의할 수 있습니다. 따라서 이 서비스의 이름을
로 이름을 지정할 수 있습니다. 여기서는 RPC라는 표기법을 사용할 수 있습니다. 메서드 이름, 요청
그리고 응답이 있습니다. 기본적으로 이것이 표기법입니다. 그리고 저는
GRPC에서 간단하게 할 수 있습니다. 그래서 이걸로 이름을 지으면 되겠네요. 좋아요, 그럼 여기에서는
만들 때까지는 아무것도 얻을 수 없겠죠? 그렇죠. 네, 그냥 보기만 하도록
하드 코딩을 할 수 있을지도 몰라 그래, 좋아 아니면, 그래, 우리가 도구를 만드는 방법을
도구를 만들 수도 있죠. 하지만 일단 할 수 있는 도구를 만드는 것부터 시작하죠. 그래요 완벽해요 좋아요, 그럼 여기
우리가 해야 할 일은 메서드를 기억하세요. 요청과 응답이 있습니다. 그래서
무언가를 반환해야 합니다. 그리고 이것이 실제 키워드 반환입니다. 그리고 우리는 실제로
요청과 응답이 있어야 하므로 다른 메시지를 만들어야 합니다.
메시지입니다. 따라서 이 경우 요청을 생성하려면 get to do 요청이라는 메시지를 만들 수 있습니다.
ID로 할 수도 있겠죠? 따라서 요청에 ID를 추가할 수 있습니다. 그리고, 좋아요,
이걸 여기에 넣을 수 있습니다. 그리고 여기에서는 메서드에서 했던 것처럼, 여기에
32를 제공하겠습니다. 그러면 메시지를 통해 ID를 전달할 수 있습니다. ID로 도구를 가져오고 싶다면
ID를 전송하는 것이 좋습니다. 따라서 여기 메서드에서 get to do에 get to
ID 요청을 넣을 수 있습니다. 그리고 우리는 이미 입력한 할 일만 반환할 수 있습니다,
우리 메서드에는 이미 그에 대한 메시지가 있습니다. 따라서 기본적으로 이 메서드를 사용하면
요청에 의해 ID가 있다는 것을 알 수 있습니다. 그리고 우리는 그것을 간단하게 반환 할 것입니다. 이 경우
이 경우에는, 네, 그렇습니다. 좋아요. 완벽하네요. 그리고 여기서 다시 프로토 파일을 수정하면서
생성된 클래스를 다시 자동 생성해야 하죠? 그래서 명령줄을 다시 눌러야 합니다.
자, 다시 프로토, 프로토 패키지로 돌아가 봅시다.
보통 빌드 러너를 실행하고 있다면 지금쯤 모두 일어나서
커피를 마실 때입니다. 정말 빠른 세대입니다. 눈을 깜빡이면 놓치죠.
좋아요, 그럼 500을 가져올 수 있을 것 같아요. 이제 바로 액세스할 수 있습니다. 그리고 여기서 우리는
지금 서비스를 포함하고 있기 때문에 생성된 다른 클래스가 있습니다. 따라서 이
이 경우, 이것은 읽기 쉽지는 않지만, 실제로 get to 메서드를 호출하기 위한 모든 통신을 생성합니다.
메서드를 호출하기 위한 모든 통신을 생성합니다. 따라서 지금 당장 할 수 있는 일은 이 클래스를 내보내는 것입니다. 그러면 백엔드에서
백엔드에 접근할 수 있습니다. 여기, 완벽합니다. 이제 프로토 파일에 다른 것들을 많이 만들지 않을 것 같습니다.
프로토 파일. 하지만 다른 메소드를 만들 수도 있습니다. 하지만 이미 메시지와
그리고 서비스. 그리고 이것으로 기본적으로 Flutter와
TRPC. 자, 이제 서버로 돌아가 보겠습니다. 여기서 우리가 실제로 하고 싶은 것은
서비스를 생성하는 것입니다. 그러면 서비스를 프론트엔드에 노출할 수 있습니다. 이제 제가 할 일은
지금 할 일은 실제로 서비스를 만드는 것입니다. 하지만 문제는 이 서비스를 만들지 않았다는 것입니다.
기본 서비스인 TRPC, 프로토 버프가 만들었기 때문입니다,
자동 생성되었습니다. 하지만 실제로 서비스를 구현해야 합니다. 그래서 우리가 할 수 있는 일은
서비스 클래스를 만드는 것입니다. 서비스 이름을 서비스 클래스로 지정하겠습니다. 그리고 여기서
실제로 서비스를 만들 수 있습니다. 그리고 우리는 to do 서비스 기반을 확장하고 있습니다. 좋아요, 그럼 이 할
서비스 기반, 우리가 갖게 될 것, 여기에 빨간색으로 강조 표시된 것은 아직 구현하지 않았기 때문입니다.
아직 구현하지 않았기 때문입니다. 서비스에서 해당 메서드를 정의한다는 점을 기억하세요. 따라서 어느 정도
인터페이스처럼 작동합니다. 이 메서드를 구현해야만 우리가 이 메서드를
기본적으로 재정의할 수 있습니다. 그리고 이 경우 기본적으로 우리가 할 수 있는 일은 단순히
를 반환하는 것입니다. 하드 코딩된 할 일처럼요. 따라서 이 메서드의 기본 구현을 할 수 있습니다.
기본 구현을 할 수 있습니다. 좋아요, 프로토 버프의 멋진 점은 이미 두 개의 클래스가 있다면
두 개의 클래스가 있다면, 여기와 같은 이름 매개변수와 함께 사용할 수도 있고, 다른 메서드를 사용할 수도 있습니다.
같은 다른 메서드를 사용할 수도 있습니다. 그리고 어쩌면 이것은 기본 구현 이외의 다른 것을 반환하지 않을 수도 있습니다,
빈 매개변수 같은 것을 반환할 수도 있습니다. 하지만 몇 가지 기본 매개 변수를 만들 수 있습니다,
제목은 제목을, ID는 ID를 요청에서 가져올 수 있을까요?
전달된 ID를 사용하면 어떨까요? 네, 좋은 생각입니다. 그럼 기본적으로
여기에 최종 ID 요청 점 ID를 넣으면 됩니다. 그리고 이 ID를 대신 사용하겠습니다. 완벽하네요.
그러면 프런트 엔드에서 ID를 생성하고 그 ID로 새로운 할 일을
새로운 할 일을 반환합니다. 그러면 완성된 패턴이 누락됩니다. 이것은 거짓이 될 것입니다.
어쩌면 우리가 할 수 있는 일은 제목과 ID를 입력하는 것입니다,
리스팅 제목을 입력하는 것입니다. 그리고, 좋아요. 그리고 네, 우리가 할 수 있는 또 다른 일은,
실제로 할 일을 반환하는 것입니다. 이것은 할 일의 기능을 반환하는 것이기 때문입니다. 그래서
여기서 우리가 놓치고 있는 것은 추적 키워드입니다. 그게 다입니다. 우리는 이것을 구현하고 있습니다.
메서드로 이동하여 반환합니다. 이것이 우리의 정의입니다. 이제 서버 내부에서
서버 내부의 서비스를 사용할 수 있죠? 그래서, 이것은 이것을 서비스에 노출시킬 것입니다.
서비스에 노출됩니다. 그리고 프런트엔드에서 사용할 수 있습니다. 좋아요. 그게 다입니다.
이제 마지막으로 해야 할 일은 프론트엔드를 만드는 것입니다,
플랫을 올리는 거죠? 이제 모든 것이 실행됩니다. 이 경우에는 다른 폴더를 만들어야 합니다.
폴더를 만들어야 합니다. 따라서 Flutter에서 클라이언트 앱을 만들 수 있습니다. 그리고 여기에서는 템플릿을 사용하여 기본 앱을 만들겠습니다.
템플릿을 사용하여 Flutter에서 기본 앱을 만들겠습니다. 이제 예제를 작성하고 있습니다.
매크로 프로에서 작성하고 있는데, Android iOS 및 macOS를 사용하여 만들 수 있습니다. 웹을 사용할 수도 있습니다,
하지만 웹에서 jrpc를 처리하려면 웹에서 하지 않는 특별한 작업을
아직 완벽하게 지원되지 않는 몇 가지 특별한 작업을 수행해야 하기 때문입니다. 몇 가지
좀 더 고급 작업을 해야 합니다. 하지만 모바일과 데스크톱에서는 확실히 테스트할 수 있습니다.
좋네요. 그래요. 그럼 이름도 앱으로 정할 수 있겠네요. 저는
어떤 새로운 조직. 그리고 플랫폼은 제가 말씀드린 대로 선택할 수 있습니다,
안드로이드 iOS와 맥OS. 좋아요. 그리고 여기에 모든 것을 만들어 봅시다. 좋아, 이제 이렇게 하면
앱이 생성됩니다. 아주 기본적인 것들입니다. 이제 폴더, iOS, Android, macOS가 생겼습니다. 그리고
패스 팩 YAML이 있습니다. 지금 당장 할 수 있는 일은 이 패스를 조금 정리하는 것입니다.
팩 YAML. 그래서 우리가 할 수 있는 일은 몇 가지 정규 표현식을 사용하여 실제로 이것을 정리하는 것입니다.
그럼 부팅해 봅시다. 예, 표기법이 이렇게 되어 있었죠?
아, 권한을 선택해야 하죠? 네, 모든 줄을 제거하려고 하죠?
그래요 미안해요 됐어요 그래요 좋아 보통은 자동으로 서식이 지정되지 않나요?
네, 일반적으로는 새 줄로 바꿉니다. 왜냐하면 가끔은 새 줄로 바꾸지 않으면
새 줄로 바꾸지 않으면 내용이 뭉개질 수 있으니까요. 그렇군요. 메인 파일도 똑같이 해보겠습니다. 자, 여기
이 부분을 주석으로 바꾸겠습니다. 제가 얼마 전에 발견한 건데요,
플래터 생성 시 대시 대시 빈 플래그를 사용하면 파일에 이 모든 내용을 넣지 않는다는 것을요.
당신. 오, 그래서 그렇게 하는 플래그가 있군요. 네, 플래터 생성 대시 대시 비어 있습니다. 아니요
이미 많은 작업을 하셨잖아요. 그래요 하지만 앞으로는 대시보드가 비어있을 거야
저기 보여요 그래, 여기 있어 그래 아무 말 없어 완벽해 네, 좋은 팁이네요 그래서
걸레를 안 써도 되겠네 그럼, 네, 모든 것을 청소하세요. 그래 그렇군요 자, 여기서 우리가 할 일은
프로토 버프, 프로토 패키지를 실제로 가져오는 거죠? 서버에서 했던 것처럼요. 그럼
빠르게 제작할 수 있고 경로도 동일할 것입니다.
완벽하죠. 이제 모든 것에 액세스할 수 있습니다. 예제 속도를 높이기 위해 여기서는
어떤 종류의 상태 관리나 리포지토리 패턴 같은 것을 사용하지 않을 것입니다.
네. 그냥 우리가 가지고 있는 상태 저장 위젯을 사용하면 될 것 같습니다. 상상력을 발휘해 보세요.
그렇죠. 그리고 예, 아마도 여기에 따르는 모범 사례와 같은 것이있을 수 있지만 속도를 높일 것입니다.
그리고 GRPC와 소통을 시작할 수 있도록 클라이언트 채널을 만들고 싶습니다.
이를 위해서는 클라이언트 채널이 필요합니다. 그리고 이런 속성을 가질 수 있습니다. 어쩌면 우리가
패키지를 가져올 수 있습니다. 네. 그리고 우리는 그 패키지에서 GRPC 패키지를 내보내고 있기 때문에,
맞죠? 그러면 초기화 상태에서 이 채널을 초기화할 수 있습니다. 좋아요, 그럼 초기화 상태를 만들어 봅시다.
상태를 만들어 봅시다. 여기서 우리가 할 수 있는 일은 여기에 클라이언트 채널을 만드는 것입니다. 그리고 호스트는
이 경우에는 로컬 호스트가 되겠죠? 왜냐하면 우리는 우리 컴퓨터에서 작업하고 있기 때문입니다. 그리고 포트는 기억하세요,
8080을 선택하지만, 환경 변수를 통해 서버에 제공하는 포트일 수도 있습니다.
환경 변수를 통해 서버에 제공하는 포트일 수도 있습니다. 그리고 채널 옵션도 전달해야 합니다. 따라서 이를 위해
안전하지 않은 모드와 같은 채널 옵션을 사용할 것이지만, 이것은 다음에 따라 달라집니다.
SSL 인증서를 제공하느냐에 따라 달라지겠지만, 클래스와 함께 진행하겠습니다.
그리고 모든 것을 비용으로 계산해 봅시다. 자, 여기에는 이미 채널이 있습니다. 그리고 우리가 만들어야 할 것은
지금 당장 만들어야 하는 것은 스태프입니다. 스태프는 단지 추상화일 뿐입니다.
GRPC와 통신하고 실제로 우리의 메소드를 호출하는 데 사용할 수있는 프록시입니다.
따라서 여기서 우리가 할 수 있는 일은 스태프를 만드는 것입니다. 이를 위해 이를 사용하는 방법을 검토해 보겠습니다.
기본적으로 우리는 다른 자동 생성 클래스를 호출해야 합니다.
할 일 서비스 클라이언트입니다. 여기 할 일 서비스 클라이언트를 넣겠습니다. 그리고 이것은 우리 직원이 될 것입니다.
이제 초기화 상태에서 초기화할 수도 있습니다. 그래서 여기서 우리가 할 수 있는 일은,
기본적으로 할 일 서비스 클라이언트를 초기화하고 채널을 전송하는 것입니다. 그게 다입니다. 우리에게는 직원이 있고
를 사용하여 할 일 메서드와 같은 사용 가능한 모든 메서드와 상호 작용하기 시작할 수 있습니다.
좋아요, 그럼 채널을 잠시 숨겨 보겠습니다. 그러면 여기에는 기본 카운터 예제인
기본 카운터 예제가 있죠? 그래서 우리가 할 수 있는 것은 여기에 채우기를 넣는 것입니다.
여기에 할 일을 넣는 것입니다. 그래서 이것은 빡빡하지 않을 것입니다. 메인 화면에 해당 할 일을 표시할 수 있습니다.
메인 화면에 표시할 수 있습니다. 그래서 무효화할 수 있습니다. 하지만 예, 카운터에서 이것은 실제로
카운터의 상태를 설정하는 것입니다. 카운터가 필요하지 않으므로 카운터를 삭제하겠습니다.
또한 그렇습니다. 그리고 여기서 우리가 할 수 있는 일은 서버에서 할 일을 가져오는 것입니다. 좋아요. 아이콘에서
이 아이콘으로 바꾸겠습니다. 그리고 여기서 할 일이 null과 다른 경우 제목이 있는 텍스트를 표시할 수 있습니다,
제목이 있는 텍스트를 표시할 수 있습니다. 좋아요. 아, 맞다. 그럼, 좋아요,
여기 있습니다. 아니면 '할 일 처리하기'와 같은 텍스트를 표시할 수도 있습니다.
마음에 들어요. 완벽해요. 정말 간단하죠. 하지만 기본적으로 전체 연결을 건드리고 있습니다.
이걸 열에 넣으면 더 많은 정보를 표시할 수 있습니다. 그러면 더 많은
정보를 표시할 수 있습니다. ID와 이 작업이 완료되었는지 여부도 표시할 수 있습니다.
좋아요. 이 정보는 정수가 될 것입니다. 그래서 우리는 그것을 파싱해야 합니다. 그리고 이것도
이것은 부울이 될 것입니다. 완벽하네요. 이건 단점에 대해 불평하는 것 같아요.
완벽해요. 좋아요, 기본적으로 모든 것이 작동하면 실제로 Flutter 앱에서 할 일을
할 일 봇을 클릭한 후에야 Flutter 앱에서 할 일을 볼 수 있습니다. 그렇군요. 완벽하네요. 그럼 어떻게
어떻게 할까요? 우선 서버를 시작해야 하겠죠? 그래서, 우리는
서버 폴더로 이동합니다. 서버를 시작하는 것이 매우 도움이 될 것 같습니다. 네. 완전히요. 이제 서버로 돌아가서
서버로 돌아가면 bin 폴더가 있는 것을 볼 수 있습니다. 그리고 여기 안에는
서버가 있죠? 따라서 간단히 다트를 수행하고 서버 도트 다트로 끝낼 수 있습니다. 그리고 서버가
시작되어야 합니다. 시작되었습니다. 서버가 포트 8080에서 수신 대기 중입니다. 그렇군요. 우리가
Postman에서 테스트를 시작할 수 있는 것과는 다릅니다. 이것은 다른 프로토콜이기 때문에 더 어렵습니다.
하지만 랩을 실행하여 모든 것이 작동하는지 확인할 수 있습니다. 여기서 다른 상단을 열 수 있습니다.
그리고 고객에게 갈 수 있죠? 여기서 우리가 해야 할 일은 랩을 실행하는 것입니다. 그리고, 저는
먼저 macOS에서 실행하겠습니다. 네, macOS입니다. 가장 쉽게 시작할 수 있는 방법이죠.
그렇군요. 에뮬레이터가 없군요. 네, 맞아요. 시작이 없죠. 에뮬레이터를 시작하는 방법을 아시잖아요. 맞아요 하지만
iOS나 안드로이드에서 실제로 조정할 수 있습니다. 문제는 macOS의 경우 처음에는
구성에서 특별한 매개 변수를 설정해야 하기 때문입니다.
구성해야 하기 때문입니다. 하지만 비슷한 것 같지 않나요?
네, 네트워크 요청을 보낼 수 있는 거죠. 네. 그래서 저는 이것이 실패 할 것이라는 것을 보여줄 것입니다,
하지만 우리가 고칠 것입니다. 그래서 네, 지금까지는 이것이 전체 예제입니다. 또 한 가지
GRBZ에서 특히 중요한 것은 우리가 할 것입니다.
서버에서 다양한 것을 스트리밍할 수 있다는 것입니다. 그래서 우리는 정보를 푸시할 것입니다.
정보를 푸시할 것입니다. 정말 멋진 기능입니다. 많은 사용 사례가 있습니다. 그래서 여기, 우리는
할 일이 있습니다. 버튼을 누르면 이렇게 작동하지 않습니다. 하지만 맞아요.
여기에 오류가 발생하지 않나요? 오류가 안 나요.
오, get to do에 아무 것도 넣지 않았기 때문이죠.
메서드를 넣지 않았어요. 좋아요, 그럼 여기서 우리가 해야 할 일은...
제가 놓친 것 같네요.
네, 여기서 실제로 할 일을 해야 합니다. 자, 여기서 우리가 만든 할 일 요청을
전달해야 합니다. 아, 사실 저 카운터가 필요해요.
그래요 그렇군요. 여기에 임의의 ID를 만들 수 있겠죠? 그럼...
알았어
그렇게 무작위는 아닌 것 같아요.
입력하는 동안 포스트맨이 GRPC 지원을 추가했습니다.
오, 그건 몰랐네요. 그래서 누군가 말하길...
멋지네요. 정말 멋지네요. 수정해야겠어요. 그래
그래 자, 수학 좀 보자 아마 도서관이 있겠지
무작위인 것 같아 그건 모르겠어
수학을 가져와요.
그럼 다음에는 100개 정도는 있을 거예요.
완벽하네요.
그럼 여기서 ID를 사용할 수 있습니다. 좋아요, 이제 할 일이 생겼습니다.
그리고 물론 우리는 이것을 기다려야 합니다.
그런 다음 R의 상태를 설정하여 이 작업을 수행 할 수 있습니다.
아, 맞습니다. 거기에 최종이라는 키워드를 추가했기 때문입니다. 그래서 실제로는
아직 위젯에 설정하지 않았습니다. 멋지네요.
그렇군요. 자, 이제 다시 시작하면 실제로 우리가 얻을 수있는 무언가를 할 것입니다.
바닥. 그리고 이것으로 돌아가 봅시다. 여기 화살표가 있습니다. 좋아요.
이 문제를 해결하기 위해 우리는 ...에 들어갈 수 있습니다.
그래요 그리고 그것은 작동 중이고, 허용되지 않고, 소켓, 물건, 어쩌고 저쩌고.
그래서 이걸 보면 존 프랑코가 지금 하고 있는 것처럼 Xcode를 열어야 합니다.
좋아요, 그럼 빨리 열어봅시다. 아니요, Xcode 프로젝트를 열겠습니다.
알았어요
Xcode를 여는 게 아니라 최고의 비법을 보여줄 줄 알았는데요.
아뇨, 이번엔요. 알았어요. 자, 여기요. 여기 있습니다
서명 및 기능, 나가는 연결. 좋아, 모든 걸 다시 시작해야 하지만
이번엔 작동할 거야 그리고, 네. 이것이 전체 예제입니다. 조금만 기다려 봅시다.
맥OS를 로딩하는 중입니다. 그리고 제가 언급하면서 보여주고 싶었던 또 다른 것은
서버에서 정보 스트리밍을 시작하는 방법입니다. 그래서 우리가 할 일은
실제로 할 일을 가져오는 대신 할 일을 스트리밍하는 것입니다. 하지만 먼저...
바로 이것입니다. 좋아요, 이제 작동합니다. 임의의 ID로 할 일이 생겼습니다.
계속 진행하면 돼요 그러면 무작위에서 진짜 기본으로 바뀌겠죠?
좋아요, 다음은 스트리밍입니다...
계속 진행하기 전에 스트리밍은 매우 멋질 것이지만 지금까지 우리가 한 일을 요약하고 싶습니다.
지금 50분 정도 진행했는데
많은 부분이 설명과 자료 검색이었습니다. 거의 아무것도 작성하지 않으셨어요.
그리고 우리는 서버와 완전히 강력하게 타이핑 된 통신을했습니다.
바로 이 지루한 쇼에서, 이 지루한 쇼에서, 클라이언트에서 서버로 가는 코드를 공유했습니다.
서버로 가는 코드를 공유했는데, 이보다 더 많은 시간이 걸렸습니다. 하지만 그것조차도
강력하게 입력된 것이 아니었습니다. 하지만 여기서는 물론 클래스가 강력하게 유형화되어 있다는 사실입니다,
코드를 공유하고 있지만 네트워크 요청 자체가 강력하게 입력된 적이 없었습니다.
이 점이 정말 멋진 점입니다. 그래서 우리가 바꾸면... 전례가 없던 일이죠.
서버의 작동 방식을 변경하면 클라이언트에 유형 오류가 발생하여 알려주는 것은 사실입니다,
아, 그 엔드포인트를 삭제하고 이름을 다른 것으로 바꿨어요, 아시죠? 그런 일은
전에는 없었던 일이죠. 그래서 이것은 정말 정말 깔끔합니다. 그리고 성능도 뛰어납니다. 그리고 존 프랑코가 말했듯이
말했듯이 곧 스트리밍을 시작합니다. 제 개가 여기서 시끄러워요. 네, 정말요
정말, 정말 깔끔해요. 정말 멋지네요. 네, 정말 멋진 요약이네요. 그리고 네, 이건
자동 생성된 파일 덕분에 정말 빨랐습니다. 저희는 할 일 클래스, 서비스
할 일 클래스, 서비스. 이것도 자동 생성됩니다. 그래서 정말 빠르죠. 하지만 네
좀 더 멋진 사용 사례를 보여드리기 위해 이 할 일을 스트리밍해 보겠습니다.
이제 모든 일이 일어나는 프로토 파일로 다시 돌아갈 수 있습니다. 따라서 우리가
프로토 패키지로 돌아가면, 여기서 할 수 있는 일은 할 일을 반환하는 get-to-do가 아니라
할 일의 스트림을 반환하는 것이겠죠? 따라서 이름을 바꾸고, 다른 메서드를 만들 수 있습니다.
다른 메서드를 만들 수 있습니다. 그리고 네, 실제 요청은
동일합니다. 우리는 전달할 수 있습니다... 글쎄요, 그건 말이 안 되죠 왜냐하면 실제로는 할 일을 만들어서
고객에게 보내지 않을 것이기 때문입니다. 우리가 할 일은 일종의 스트림과 같습니다.
스트림을 만들어서 고객에게 푸시하는 것입니다. 따라서 별도의 메서드를 만들어서
할 일을 만들어서 스트리밍으로 클라이언트에게 전송할 수 있겠죠? 네, 그렇게 할 수도 있습니다. 스트림은
스트림이 1초에 한 번씩 무작위로 할 일을 스트림에 추가할 수도 있습니다. 그리고 프론트엔드에서
프런트 엔드에서 모든 작업을 저장하고 목록 보기 등에 표시할 수 있습니다. 네, 그렇게 할 수 있습니다.
여기서 우리가 해야 할 일은 할 일 스트림을 제공하는 것뿐입니다. 정말 간단합니다.
이 키워드를 사용하여 수정하기만 하면 됩니다. 실제로 클라이언트로부터
클라이언트에서. 사용 사례를 찾을 수 있을지도 모르죠. 하지만 네, 단일 호출을 할 수도 있습니다,
서버에서 스트리밍할 수도 있고, 서버 없이 클라이언트에서 스트리밍할 수도 있고, 둘 다 할 수도 있습니다. 그래서
사용 사례에 따라 다르겠지만 양방향 통신을 통해 이점을 얻을 수 있습니다.
이점을 얻을 수 있습니다. 따라서 지금 당장 해야 할 일은 물론 명령어로 이동하여
명령을 다시 생성하고 자동 생성하는 것입니다. 매개 변수에 스트림 키워드를
매개변수에 그대로 두시겠습니까? 아, 맞습니다. 네, 서버에서 스트리밍하는 것만으로 간단하게 시작할 수 있습니다.
서버에서. 이제 제품 생성에 대해 확인해 보면 서버에 오류가 있음을 알 수 있습니다.
다른 방법을 다시 구현해야 하기 때문에 서버에 오류가 있습니다.
저는 이런 오류가 정말 마음에 듭니다. 이봐요, 뭔가 잊으셨네요. 네, 최고입니다.
따라서 누락된 오버라이드를 생성할 수 있으며 이 경우에는 정확히
같은 방법입니다. 서비스 호출이 있고 바이트 ID 요청을 받지만 기능 대신 할 일의 스트림을
기능 대신 할 일의 스트림이 있죠? 따라서 여기서 우리가 해야 할 일은 실제로는
반환하는 대신 양보하는 것입니다. 그래서 우리가 할 수 있는 일은 아마도 이 작업을 수행하는 가장 좋은 방법이 무엇일까요?
아마도 할 일 컨트롤러를 만들 수 있을 것입니다. 자, 여기요. 한 시간 동안 기다리는
1초 동안 기다린 다음 다른 1초를 생략하는 루프를 만들 수 있습니다. 그럴 수도 있죠.
좋아요. 이제 우물 참이 생겼습니다. 좋아요, 완벽해요. 참입니다. 아주 간단해 그래
할 일을 양보할 수 있죠? 그럼, 잡을 수 있겠네. 스코피 네, 여기서부터 전부요
하지만 난수겠죠? 그래 그럼 여기서요 재밌는 건, 요청에
숫자를 지정합니다. 따라서 가설이 약간 모호해졌지만 이해해 주시기 바랍니다.
그래서, 아마도 여기서 우리는 예, 좋은 감각과 100을 할 수 있습니다. 네, 여기 할 일이 있고 양보해야 합니다.
이 할 일을 양보해야합니다. 사실 이 작업을 수행하려면 비동기 별표가 있어야 합니다. 그리고 비동기 별을 모르는 분들을 위해
비동기 스타를 모르는 분들을 위해 먼저 유튜브에 '비동기 스타'라는 멋진 시리즈가 있습니다,
아니요, 이름은 잊어버렸지만 Flutter의 원조 개발자 중 한 명인 앤드류 브로그던이
유튜브에 5부작 시리즈가 있습니다. 이 시리즈의 제목은 Flutter and Focus인 것 같습니다. 어쨌든
Dart에서는 비동기식입니다. 이 모든 과정을 거치는데, 비동기 스타는 A, 여러분의 함수가
스트림을 반환합니다. 그리고 산출 키워드를 사용할 때마다 산출하는 객체는 그냥 계속
스트림으로 이동합니다. 이것이 바로 우리가 여기서 설정하는 것입니다. 완벽하네요. 네, 네, 지연은 잊었습니다.
지연은 잊어버렸지만, 그렇지 않다면 많은 것을 제공할 것입니다. 그럼 이걸 조금 지연시켜 봅시다. 어쩌면
1초 정도면 충분히 알아차릴 수 있을 겁니다. 그럼 이렇게 하면...
완벽하네요. 수익률 이후, 솔직히 시작이든 끝이든요.
완벽합니다. 이제 클라이언트인 Flutter 앱을 수정하여 서버에서 1초마다 한 번씩
서버로부터 이러한 메시지를 한 번씩 수신할 수 있도록 수정해야 합니다. 이제 메인 파일로 돌아가면,
여기에 할 일이 있는데, 이번에는 단일 할 일이 아니라 여러 개의 할 일 스트림이 필요합니다.
그러면 할 일의 스트림을 만들 수 있습니다. 좋아요.
그럼... 스트림 빌더 위젯을 오랜만에 사용하게 되니 앞으로의 모습이 기대됩니다.
네, 그렇죠. Flutter 블록 라이브러리를 사용하기 전에는 스트림 빌더로 많이 작업했었는데요.
라이브러리를 사용하기 전에는 스트림 빌더를 많이 사용하곤 했었는데, Flutter 블록이 전체 구현을 완전히 지배하기 때문에 무의미했죠,
하지만 예, 예전에는... 여전히 스트림 빌더입니다. 단지 잘 위장되어 있을 뿐이죠.
그렇죠. 예, 예전에 저는 웹 시작에서 많은 스트림을 처리하곤 했습니다.
웹 시작. 그래서 예, 이것은 제가 예전에 일했던 방식을 기억하는 것과 같았지만 어떤 의미에서는 ... 하지만
할 일 스트림은 '아니오'라고 말할 수도 있습니다. 따라서 여기서 초기화할 필요는 없습니다.
우리가 할 수 있는 것은 할 일 스트림을 초기화하는 것입니다. 비공개로 설정해 봅시다.
물론 직원에게 전화해야 하겠죠? 따라서 메서드는 getToDoStream이 될 것입니다.
그리고 요청은 여기서 사용하는 것과 동일합니다. 복사할 수 있습니다.
좋아요. 이제 이 ID는 아무 의미가 없지만 그냥 여기에 넣으면 됩니다.
그리고 여기에는 할 일 스트림이 있습니다. 이제 우리가 할 수 있는 일은 스트림이 있는 것입니다.
빌더를 사용하는 것입니다. 여기에 스트림 빌더를 넣을 수 있습니다.
그리고 먼저 스트림을 제공하겠습니다. 스트림은 toDoStream이 될 것입니다.
그리고 빌더를 제공해야 하죠? 따라서 빌더에는 컨텍스트가 필요합니다.
그리고 스냅샷도요. 좋아요. 줄이 정말 길어지고 있습니다. 하지만 여기까지입니다.
자, 여기 스냅샷에서 우리가 할 수 있는 일은 실제로 데이터가 있는지 확인하는 것입니다.
아니면 인쇄하거나 표시하거나 로딩 중일 수도 있습니다. 기다릴 테니까요.
네, 그 경우를 대비해야 합니다. 스트림에 아무것도 없을 경우를 대비해서요.
그래요. 스트림에 데이터가 있다면 스트림에서 할 일을 가져올 수 있을 겁니다. 그럼 그렇게 해봅시다.
그러면 할 일이 있는 열을 표시할 수 있겠죠? 그리고 이번에는 실제로
열을 반환해야 합니다. 그게 다입니다. 이걸 실제로 구문 분석해야 하는지 모르겠습니다.
준비하세요. 하지만... 네, 거짓말하지 않겠습니다. 전 이걸 해본 지 얼마 안 됐어요. 그래서 나도 잘 모르겠어
나도 잘 모르겠어 같이 알아보자 그래요 자, 여기서 널 연산자를 제거할 수 있습니다.
멋지네요. 그리고 여기 오류가 있습니다. 어디 보자
오, 이건 반환되지 않는 것 같아요. 이게 작동할 것 같아요. 이게 맞는 것 같아요.
좋아 잘 되길 바라자고요, 그렇죠? 그래서 조금 검토 중입니다. 이 겟투는
호출하고 싶어요. 내 말은, 호출 할 수 있지만 다른 방법이 될 것입니다. 그리고 우리는
스트림을 직접 호출하고 스트림 빌더를 사용하여 데이터를 표시합니다. 그럼 다시 돌아가서
서버를 다시 실행해 봅시다. 몇 가지 변경을 했으니까요.
좋은 생각입니다. 그럼 다시 실행해 봅시다. 전화로 재시작할 수도 있었어요.
그래 그래 나쁘네 알았어 내 잘못이야
재시작이라고 합니다. 그래 자, 여기요 모든 게 작동하면
정말 빠르죠, 1초 정도요 네, 얼마나 무작위로 우리한테 오는지...
좋아 번리가 먹혔어 잘했어 완벽해 당신과 GRPC 모두요 아마도 G는
존 프랑코 그 생각도 해봤어요 그럴 수도 있겠죠? 네, 그건 또 다른 질문이죠.
그래 아니, 확인해 봐야겠어 물어봐야죠 이것 좀 봐요 서버에서 데이터를 스트리밍하고 있습니다.
서버에서 정말 멋지네요. 이 기능을 다른 방법으로 사용하려면 어떻게 해야 하는지 생각해 보세요.
반드시 웹 소켓을 사용해야 합니다. 그리고 그게 세상의 끝은 아닙니다,
하지만 훨씬 쉬워졌어요. 그리고 말씀하신 것처럼 로컬에서 사용할 수 있는 네이티브 메서드처럼
네이티브 메서드를 호출하는 것처럼 느껴지죠? 양쪽 끝에서 스트림을 처리하는 것뿐이죠.
그리고 데이터를 직렬화하고 유선으로 전송하고 연결을 관리하기 위한 모든 배짱은
전혀 생각할 필요가 없었어요. 전혀 생각하지 않았죠. 그리고 경계를 넘어
경계를 넘어, 네트워크 요청 경계를 넘어. 정말 정말 깔끔하죠. 정말 멋지죠.
물론이죠. 네, 이제 전체 주식 앱 구현이 마무리되었습니다,
클라이언트, 서버와 같이 말이죠? 우리 제품 패키지로 모든 게 끝났죠. 이 패키지를
이 패키지를 클라이언트와 서버 간에 공유할 수 있습니다. 우리는 정보를 스트리밍하는
스트리밍 정보입니다. 이제 우리가 할 수 있는 일은 다른 스트리밍 기능을 테스트하는 것일 수도 있습니다.
앞서 서버에서 무언가를 스트리밍할 수 있을 뿐만 아니라
클라이언트에서 스트리밍할 수도 있습니다. 따라서 잠재적으로 클라이언트에서 서버로 스트리밍을 시작할 수 있습니다.
서버로 스트리밍할 수 있습니다. 이에 대해 잘 생각한 예는 없지만 유용한 방법이 될 수 있습니다. 그래서
아니요, 사람들이 이해한 것 같아요. 네, 네, 이해하신 것 같아요. 자, 이제
하지만 프런트 엔드에서 그렇게하면 스트림이 있고 스트림에 물건을 추가하면됩니다.
스트림에 추가하면 백엔드에 표시될 것입니다. 그렇군요. 그렇죠. 네, 완전히요. 내 말은, 당신은
기본적으로 프론트엔드에서 스트림을 초기화하게 됩니다. 그리고 나서, 백엔드에 정보를 스트리밍하고
백엔드, gRPC로 정보를 스트리밍하면 어떤 일이 일어날 것입니다. 어쩌면 모든 것을
모든 것을 기록하고, 인쇄하고, 볼 수 있습니다. 아니면 테스트나 다른 작업을 위해 그렇게 할 수도 있습니다.
다른 플랫폼에서 어떻게 작동하는지도 보여주고 싶었습니다. iOS
를 열어볼 수도 있겠죠. 두 플랫폼 간에 메시지를 보낼 수 있을지도 모르죠.
한 클라이언트에게 정보를 스트리밍하고 있지만, 동시에 여러 클라이언트에게 정보를 스트리밍할 수도 있고
동시에 스트리밍할 수 있습니다. 그리고 그들은 모두 같은 것을 보게 될 것입니다.
다른 것을 보게 되겠죠? 네, 맞아요. 그것도 꽤 좋은 예라고 생각해요,
좋은 예라고 생각하지만, 여기서 꽤 잘 다루었다고 생각합니다. 몇 가지 질문이 있습니다.
몇 가지 질문이 있는데, 사람들이 몇 가지 좋은 질문을 해 주셨어요. 그리고 제 생각에는
iOS와 Android에서는 이렇게 마무리하는 것이 좋을 것 같습니다.
이렇게 생겼어요. 정말 멋지죠. 하지만 거기에서 큰 도약이 있어서는 안됩니다.
그래서 앞서 한 가지 의견을 받았습니다. 메시지를 클래스라고 계속 언급했습니다. 그리고
토치코프는 메시지가 클래스라기보다는 구조체에 가깝다고 말했습니다.
로직을 포함하지 않기 때문이죠. 저는 그렇게 표현하는 것이 좋다고 생각합니다. 메시지 자체는 확실히
구조체이지만, protoc 명령을 실행하면 클래스에 일대일로 매핑됩니다.
그래서 메시지와 수업의 경계가 때때로 모호하게 느껴질 때가 있습니다. 그래서
하지만 엄밀히 말하면 그게 더 좋은 표현이라고 생각합니다. 자, 존
프랑코, 다음 몇 개는 먼저 여러분의 의견을 듣고 싶고, 그다음에 제가 추가할 수도 있을 것 같아요.
제가 어떤 사람이든, 어떤 생각을 가지고 있든, 마지막에 해설을 추가하고 싶어요,
몇 가지 좋은 질문이 있습니다. 그래서 Tim은 국가 관리 블록이나 리버 포드, 또는 다른 사람들이
백엔드의 프론트 엔드에서 GRPC와 동일하게 작동합니다. 그래서 제 생각에 이 질문은 다음과 같습니다.
상태 관리에 어떤 영향을 미치나요? 맞아요. 제 말은, 저희 클라이언트 앱에서는
스테펠 위처를 가지고 노는 간단한 예제만 제시하고 있습니다,
이 작업을 처리할 때는 실제로 블록 오브
리버 포드. 그리고 좋은 구조, 좋은 아키텍처를 따르고 있다면
블록이 저장소를 호출하는 것과 같기 때문에 실제로 영향을 미치지 않습니다.
리포지토리는 클라이언트 채널이라는 것을 사용하여 궁극적으로 GRPC를 호출할 것입니다. 따라서
모든 것이 준비되어 있다면 Flutter에서 블록이나 리버 포드 같은 것을 계속 사용할 수 있습니다. 그리고
블록의 핵심은 프런트 엔드와 프레젠테이션의 연결을 해제하는 것입니다.
레이어를 분리하는 것입니다. 따라서 REST를 사용하든 웹소켓이나 GRPC를 사용하든,
동일합니다. 따라서 영향을 받지 않습니다. 그렇죠.
추가할 내용이 없습니다. 잘 말씀하셨습니다. 좋아요, 다음 질문입니다. 이 질문이 몇 번 나왔는데요. 오
사실, Tim의 질문이 좀 더 관련성이 있으니 이 질문으로 넘어가죠.
그런 다음 다른 질문으로 넘어가겠습니다. Tim은 나중에 일반적인 상태는 어떻게 되냐고 묻습니다.
코드가 어떻게 반환되나요? 저는 이 질문을
성공과 오류를 어떻게 구분할 수 있느냐는 질문으로 해석합니다. 일반적으로
200인가? 만약 내가 무언가를 만들었다면 202나 204를 기대할 수도 있죠,
어떻게 설정했든요. 만약 그렇지 않다면 404입니다. 이 설정에서는 어떻게 작동하나요?
맞아요. 네, 저도 그렇게 해석합니다. REST에 상태 코드가 분명히 있기 때문입니다.
인증되지 않은 상태인지 아니면 인증된 상태인지를 알려주기 때문입니다,
글쎄요, 다른 오류, 그냥 404, 맞죠? 하지만 이 경우에는 당연히 그렇겠죠,
저희는 그렇지 않았기 때문에 오류 처리에 대한 별도의 문서가 있습니다. 하지만
항상 예외를 던질 수 있습니다. 왜냐하면 예, 당신은 같은 문제가 발생할 것이기 때문입니다,
사용자를 인증해야 하므로 인증이 작동하지 않는 경우와 같은 문제가 발생할 수 있습니다,
gRPC 오류를 던져서 클라이언트에서 처리할 수도 있고, 아니면
사용자 지정 예외를 보낼 수 있죠? 언제든지 그렇게 할 수 있습니다. 하지만 상태 목표와 실제 목표 사이에는 맵이 없다고 생각합니다,
상태 목표와 실제 gRPC 사이에는 맵이 없다고 생각합니다. 하지만 네, 확실히 그렇게 하세요,
우리가 이것을 보지 못했을 수도 있지만 각 통화를 인증하는 인터셉터를 가질 수 있습니다.
인증하는 인터셉터가 있을 수도 있죠. 무언가가 작동하지 않으면 인증되지 않고 gRPC 오

 

 

SMALL




[ English Summary ]

In Observable Flutter, Gianfranco Papa, co-founder and CTO of Somnio Software, joins Craig Levens to explain the power of GRPC.
Learn about GRPC, a remote process invocation system developed by Google, and how to implement it in Dart.
As a Flutter expert, Gianfranco shares his experience in the community and the growth of Flutter since its beta version in 2018.
Learn more about this Dart-centric concept and see how it can enhance your projects.

Leverage the power of GRPC, a versatile tool for creating full-stack apps in Dart.
Dart-savvy Flutter developers can now develop both front-end and back-end applications without switching languages.
While other tools like Dart Frog and Shelf exist, GRPC offers seamless integration with a wide range of programming languages.

GRPC's cross-language compatibility is a game changer.
Reuse classes and minimize duplicate logic with full-stack Dart applications.
Even if Dart isn't available on the backend, GRPC simplifies communication across language barriers with auto-generated bindings in multiple languages like JavaScript, Python, and Java.

Additionally, mastering prototyping, which GRPC is based on, can be an asset for those who aspire to work at Google, as prototyping is integral to their day-to-day work.
So take the first step to unlock the potential of GRPC for your full-stack Dart application and take your development skills to a new level.

The project consists of three folders: the frontend (built with Flutter), the backend (using gRPC), and a shared folder "Protos" for the protocol buffers.
One of the main advantages of this approach is that you can reuse code between the frontend and backend, which simplifies development and maintenance.
To get started, we recommend reviewing the official gRPC documentation and familiarizing yourself with the protocol buffer.
Then try building a full-stack app using gRPC and Dart.

To create a protocol buffer model using Dart, follow these steps

1. Create a "protocols" folder.
2. Create a package with a lib folder inside the "protocols" folder.
3. Add the necessary dependencies (protobuf and gRPC) to the package.
4. Create a "protos" folder inside the lib folder.
5. Create a .proto file (e.g. todo.proto) inside the "protos" folder to define your model.
6. Define a class-like structure using the "message" keyword.
7. Define properties using a special notation with names and incremental integer codes.

See the protobuff documentation for syntax details and examples.
Remember that the "message" keyword is similar to the "class" keyword in other languages, but is used to define data that can be transferred between computers.
Use GRPC and Protobuf to efficiently exchange messages between your front-end and back-end services.
These technologies are more efficient than JSON by reducing message size and sending data in a binary format.
Start by defining your first message using proto3 syntax and a basic type like int32.
Assign a unique incremental value to each field for encoding.
In this example, we'll create a to-do message with an ID, subject, and completion status.

The power of Protobuf is that it can automatically generate models in a variety of languages, such as Dart.
This allows you to seamlessly share models across teams and programming languages, building a single source of truth for your models.

Follow the steps outlined below to create shared packages for your frontend and backend using Dart:

1. Create a new folder for the generated classes.
2. Download and activate the proto C plugin, and then export the path.
3. Use the proto C command line to generate Dart classes from the proto file.
4. Export the generated files from the library.
5. Remove unnecessary examples.
6. Define the model and share the package on the frontend and backend.
7. Create a separate backend package.
8. Use the console app template for the server.
9. Import the protocol package into the server folder.

These steps give you access to the to-do objects and allow you to efficiently share packages between the front-end and back-end.

To create a service, you need to extend ToDoServiceBase and override its methods to implement a service class.
For now, you can return a hard-coded ToDo.
You can use the name parameter or use the default implementation with empty parameters in the proto buff.
For the id parameter, you can get it from the request instead of creating a new one.
Since we don't have a completed pattern, we set it to false and provide a title based on the listing title.
Finally, we need to add the tracking keyword and enable the service inside the server.
To get everything done, you'll need to create a client app in Flutter with templates for Android iOS and macOS, as JRPC doesn't work well with currently available web applications.

To start the server, run "dart server.dart" and make sure it's listening on port 8080.
To test if everything is working properly, run the lab on macOS or adapt it for iOS/Android.
GRPC allows you to stream from a server to a client.
Now use Postman with GRPC support for your tests.
If you get errors related to sockets, open Xcode and configure special parameters in the configuration.


Using GRPC in Flutter doesn't affect state management solutions like blocks or river pods.
Also, messages are more of a structure than a class.

When making changes to the API, such as adding new properties or changing an optional field to a required field, we recommend that you version control your changes.
This can be done using protobufs, which are useful in microservice architectures where you can use different languages.
Updating the server requires updating the client app as well.
In a microservice architecture, it's important to have a strategy for handling updates across services that don't need to be updated all at once.
Google uses required fields to effectively handle updates.

If you're interested in exploring this technique further, we encourage you to give it a try.

 

 

 

[ English Full Text ]

Hello, everybody. Welcome to another episode of Observable Flutter. I'm your host, as always,
Craig LeBens, the maybe one day someone else will host. Just as always, so far. Anyway,
today I'm excited to talk to everybody about GRPC, which for those who don't know stands
for, I believe, Google Remote Process Call. I know it's invented by Google. Maybe my guest
will be able to clarify exactly what the G stands for, which I realized as I started this sentence,
I've never actually looked up before. I've just assumed. But before we get too far into that,
I just want to remind everybody that here on Observable Flutter, we're all very kind to each
other. This is the Flutter community. Let's live up to our good name. All right. And my guest
is John Franco, who is the CTO and co-founder of Somnio Software in Uruguay. And many of you will
know him as just a delightful presence on Twitter in the Flutter community and all around great
software engineer. So, John Franco, man, I am really excited to have you. Welcome.
Hey, how are you, Craig? I'm great. I'm great. I'm very excited to talk about GRPC.
Maybe if you'd like, you could begin by just saying a few words about your history with tech
and in Flutter. And, you know, how did we get here? Yeah, of course. Okay. So first of all,
thanks for having me here. I'm really excited. I will see a show. So being part of the show right
now is really, I'm really excited. And yeah, maybe I can introduce myself. I'm John Franco,
Papa, and I'm a CTO and co-founder of Somnio Software. And yeah, I'm a software engineer
who specializes in Flutter. I really love this technology. And what else? I've been growing the
community in Uruguay here in Latin America. And I'm an organizer of Flutter Uruguay. Yeah,
so that's really cool. And yeah, in our company, we are basically an adept shop that specializes
in Flutter. We are like 100% focused on this technology. So yeah, we started at the same time
that Flutter actually was created. We started with Beta back in 2018. And then we keep working
in projects and realize, okay, this is something big. So yeah, that's how we all started. We
basically trusted in this technology. And yeah, back then we were working with mobile apps. But
now, as we do now, we can work with web and desktop. So that's really great that Flutter keeps
opening us doors to work in any kind of project. Nice, yeah. I know we've met at a couple events.
And I always love to meet and talk to folks who go all the way back to the early Beta,
because I don't even. I found Flutter shortly after it went to 1.0. So you've got a longer
Flutter tenure than I have. But today, we're not just talking about Flutter. We're actually hitting
a more kind of Dart-centric concept. Although the concept itself is larger than Dart, we're just
going to implement it in Dart, which is GRPC. So, Gianfranco, you pitched this episode idea to me
a long time ago, basically right when observable Flutter started. And so you knew immediately
that you wanted to talk about GRPC. Tell us a little bit about why kind of the average developer
should agree with you and also be excited about GRPC. Yeah, okay. So, yeah, I remember that we
talked about, even before observable Flutter was a show, we were talking about maybe the boring
show. I think that I asked you to talk about GRPC because, yeah, back then, I think I saw a video
about full stack apps, but with WebSockets. So, yeah, the thing about GRPC is that it's another
tool you can have in your toolset to kind of create full stack apps in Dart. Because as it has
Dart support, you can create your front end and your back end by only using Dart. And that's really
advantageous for ask Flutter developers who already know a lot about Dart and want to
also create back end applications. And we don't want to switch to another language, right?
But, I mean, we all know that there are other tools to create back ends in Dart,
for example, Dart Frog or Shelf. But in the case of GRPC, I think that it's slightly different
because you can not only make your back end in Dart, but you can also use other programming
languages seamlessly. So, yeah, that would be because we are going to see it, but you can basically,
I mean, GRPC has support for a variety of languages. And you can basically auto generate
with a thing that is called PradaBuff, whatever language you are targeting. So,
it's kind of like more or less language agnostic, in a sense.
Yeah, the cross language part is a huge deal because, you know, one of the
one of the driving goals are like a value that a developer gets by having a full stack
Dart application is to be able to reuse a bunch of classes and not have to duplicate logic and
whatnot. And, you know, there's still if you even if you use GRPC, having Dart on both ends
will kind of put you in the best possible scenario there. But if you can't use Dart on
the back end for any reason, you know, we'll be using Dart on the back end today. But if for
some reason you can't, that's a great point because those bindings are generated on both ends in a
variety of languages, whether using JavaScript or Python or Java or whatever on the back end,
you're the task of communicating just with yourself across that language barrier becomes
so much simpler. Because from that simple protobuf definition you mentioned, which will get into,
you know, everything kind of falls out of that. And by the way, if any of you ever want to work
at Google, and you want to apply to Google, familiarity like protobufs, that is what every
Google developer uses every day, everything at Google runs on protobufs and the code that
just generated downstream of that. So, you know, you might be training yourself a little bit for
your next job. All right, John Franco, I believe you are ready to kind of walk us through some
steps of getting started. Are you, am I right? Sure. Yeah, let's get ready. So,
perfect. Okay, so my idea for today, we were discussing with Greg like to present kind of
like something from the very, from scratch, okay, it would be something real simple, but
yeah, and the idea is to make it from scratch, so it won't be something really fancy. But yeah,
first of all, I wanted to like, I have the documentation open here, so actually, I consider
that gRPC is not that topic that there's so much information and like dogs, or it's not like so
common, such as rest, right? But yeah, here's the documentation, so you can always go and hear
the official docs. Well, gRPC is a modern open source, high performance remote procedural code,
so remote procedural code would be the protocol that we are going to use, just as you have rest
or WebSockets. And here we are going to use RPC. And I think the g could be right for Google,
right? I actually didn't ask that question, but probably it will be because of Google, right?
That's what I thought as well. Randall tells us that it's just one of those cheeky recursive
algorithms or acronyms, so I guess the g is officially not for Google, it's just meaningless.
But since this was invented by Google, if they picked a meaningless letter,
you know, I'm not surprised that they picked g, so. Right, makes sense. So, okay, and here you can
get started. We have a lot of languages. Of course, we are going to choose dark, right? But you can
play around with any of these languages that are really common. And so, yeah, another thing
that I want to show is, okay, the quick intro. So, here we have like, yeah, an intro, and it
will also talk about protocol buffers that are really tight. I imagine that you can kind of like
look to protocol buffers as JSON for REST. The protocol buffer for gRPC would be kind of the
same, the way it communicates information. But, yeah, we're definitely going to explain
better this term. So, yeah, I wanted to like only show that. Maybe we are keeping hand
the documentation for some things, but we are switching into VS Code and we are going to create
full stack app from scratch. So, yeah, the first thing I want to talk about actually is
protocol buffers, right? Because maybe we can start our project by creating some protocols,
like just a short for protocol buff, right? And, yeah, my idea is to have like three different
folders, right? One for the frontend that will be made in Flutter, then another one for the backend
that will be made in gRPC, using gRPC, and another one that will be the share folder that we will
call it Protos, but we will use it in the backend and the frontend. And that is one of the first
advantages that we can reuse a lot of the code between the frontend and the backend.
I love it. Yep. Perfect. So, I'm going to just create, okay, let's, we are here in the terminal,
I'm going to create a project. I always forget what is the template, the default template. So,
you want server shelf? No, I actually, we're going to start with the protocols package. So,
I'm going to select the package. So, we can store all of our product buffer files. So, okay, so we
are going to create, using the template package, right? Oh, maybe we can create the directory
first. Okay, so let's create a protocols folder. And then we can move to the protocols. And here,
okay, we can create the package, right? So, if we hit package in this directory, I think I might force
this. So, here we have a pure Dart package, like really simple. So, maybe we can delete the test
folder because we are not going to have any tests. This is going to explode sooner or later, right?
Yeah, that's really nice. Well, you wouldn't really write tests for your protobufs because
gRPC is well tested. So, right, unless you just didn't even define your model correctly.
Right. I guess you're testing this folder, I don't think.
Yeah, I guess you're mistrusting the way gRPC works, right? Or protobufs, yeah.
Right. Okay, so, here, we have an example, we have a lib folder. And the first thing to do would be
to actually grab our dependencies, right? So, we are going to use protobuf and gRPC, okay?
Those are Dart packages that you can see in PubDep. So, yeah, let's make sure that everything is in
place. So, here, we have our dependencies. Let's put here the dependencies. And that's it, right?
Looks good. Perfect. Okay. So, okay, to create our first
proto file, maybe we can create a folder that will be called protos.
And in here, we can actually create our first definition of our protocol buffer model.
And I was thinking about a basic to-do file, but we can't choose anything, right? It would depend
on what you want to build. But let's start with a to-do. And the extension would be proto, okay?
So, in here, we can start defining, like, what would be the protobuf for our model. So,
I want you to get back to the documentation so we can see the basic syntax of the protobuf. So,
let me search in here for the protocol authors that it has a separated documentation.
But here, it would be more or less the syntax that we have to use in order to create a model
using protobuf, okay? So, you see that if we would like to create maybe a to-do class,
we will have to use the keyword message. And then, for defining every property,
we will have to, like, use this special notation where you define the name of the property
and a code. That code would be, like, an incremental integral, okay?
And that message keyword, that's kind of like, it's basically just, like, the keyword class
in any other language, right? But it's written as message here because the whole idea of GRPC
is the ability to get this data on the wire, right? How to send this data somewhere else. So,
you know, GRPC thinks of all these things as messages. Their data that starts on one computer
is going to go to another computer. But it's really similar to the keyword class,
if you're looking at this for the first time. Yeah, it could be. So, yeah, the thing is that
in order to have this connection, this interchange messages in an efficient way,
GRPC, Protobuf, sorry, kind of, like, reduce the whole concept of a message that we are
passing through services, so through the front end and the back end. So, it can be more efficient
in terms of size because if you know JSON, probably you know it, it will be something that
is really easy to read. But it's not so efficient to pass over the wire. So, in this case, we are
not reducing something so readable, but it will be really efficient to pass back and forth.
Okay, so maybe we can. Oh, sorry. I was just going to say, JSON spends so much time,
or so it's waste so much space with all the parentheses or the curleys and the quotes and
just sending things as like raw strings. And GRPC also sends this in a binary format. So,
it's incredibly efficient. Right. So, yeah, maybe we can start defining our first message. So,
I'm going to copy and paste this example. We are going to use the syntax proto three here.
And in here, maybe we can rename this to write. So, maybe we can also remove this.
So, if you want to also keep in handy, keep in handy documentation, you have, we have different
types that we, that product app support, let me say it. But I'm searching for the types.
Okay, the full values. Scalar value types. No, that's just, oh, you're on the whole list here.
Yeah. You're looking for like a single list that shows all the types.
Right. Yeah. Yeah, this is the whole, the whole list of, yeah, maybe, maybe there is a section
where you can actually search all of the values of your types. But that's not a problem. I mean,
we're going to use like basic types here. We're going to use in 32 for our ID. So, we can define
the name of the property and remember to define an actual value that would be an incremental value.
This is just for encoding the information. And then basically the order of the fields, right?
It's not, it's nothing more than that. Right. Of course. So, instead of, right, like in JSON,
we'll be like, you could read it. I know the ID will be this field, like key value. And this
will be like, okay, the number one will be the ID, but nothing else. And yeah, this has to be
unique. Right. So, apart from that, we can define a title maybe. So, this will be number two.
And then we can use another type that is able to say if this is completed or not. Right.
So, this is in essence like our definition of our to-do message. Right. And we are seeing this in
in the proto buffer notation. But we, the cool thing about this is that we are going to actually
auto generate this in Dart. It can be in any language, but we are using Dart.
So, you can start sharing your models, not only with your front-end team, but also with
anyone that wants to implement a definition of to-do. So, this is really like a really,
an ultimately solution for having a single source of truth for your models. Right.
Because you are sharing the whole model with a lot of even languages, program languages.
And boy, did we not write much. You know, that is, that is a terse definition of this to-do
class. I'll even call it. Of course. Of course. Okay. So, here, what we have to do is to
create another folder that will be generated. And maybe we can remove this as part of the library.
We won't need it. Do it. And here, okay, here, we can export things later. And our library,
here, we are going to actually export our generated classes. So, the idea is to grab using the proto
C command that you can download. I mean, we skip the setup, but the idea is that you can
use this setup. Let me see. There is a quick start for this. But, okay. So, let me actually search.
Quick start. So, basically, here, we have to download the proto C plugin and activate it and
then export the path. And then we can start using the proto C command line in order to
generate this proto file. So, I'm going to copy this command because it's hard to remember. So,
but we can say, okay, here, I'm using the proto C. The Dart output will be the generated folder.
We are basically grabbing everything that is under the proto folder. It's every file. And we are
auto generating Dart classes. So, if we hit enter, this will generate a bunch of classes
in Dart. And, yeah, this is not so readable, but the thing is that you have your models in Dart
and you can start using it. So, you have your, you can actually here create an object that is to do,
okay. Great. So, what we can do here right now is to actually export the, let me see,
the, all of these files in the library. So, maybe in this file, we can export it. So, it will be
source, generated. And we can do it with the other ones as well, just in case we need it.
But you will find that everything is, oh, that's not, and then JSON.
So, great. So, here what we did is we defined, we have to, maybe we can remove the example as well.
So, we just defined our definition of our models and we can start sharing this
package in our front end, in our back end, and we will have access to our to do object, right?
Okay. So, maybe another thing we can do right now is to create our back end and in a separate
package. Okay. Sounds good. So, perfect. So, maybe we can go back to our full setup and create this time
a server. Okay. So, I'm just creating another folder. And if we enter to this folder here,
I would like to use another template, because this would be a package that we can import in
our front end, but maybe we can use the console app so we have our main and we can start our server.
Okay. So, this will be actually the default template. So, if we hit start create,
instead of specifying the template, we can use the default one. And we are going to force it to
be created in this folder, in the server folder. Okay. So, here we have our projects.
And maybe what we can do now is to import the protocols package into our server folder. So,
we can start using it, right? So, because this is a package that we have locally, we have to
basically provide the path. And we can actually say, okay, let's grab the path in the protocols
folder. Okay. Great. Okay, saying that. Oh, we have to add like the publish to none.
Just really quick. So, we don't have that warning. Okay. Perfect. All right. So, the idea here would
be we can also, well, this is going to also explode because we have our calculate method.
And inside bin, we have our server.dart that is having a main function. But in here, what we
actually want to do is to create the gRPC server. So, anyone can start connecting with the gRPC server
using a client. And yeah, one of the things that we didn't mention is that a cool thing about
this protocol is that you can call a function, a remote function, as if you were calling directly
in your frontend. So, it will be a really seamless communication. We are going to see it,
but when we are going to be in the Flutter app, it will be calling the server, it will be like
calling a function that we have in our frontend project. It would be really great. You don't
have to create an HTTP request and parsing. It's like, you just kind of call the function
and that's it. But yeah. So, here we have our main file. I'm going to create the server right now.
So, this is also some of the code I bring just to speed up this part. So, let me quickly copy
and paste this. Okay. So, basically, we have to define a server. We're going to erase this
just for now, but this server will come from the GRPC library. We have to also install this
library because we are in the other project. We can actually export it from the proto library.
Let me see. We can export as well the GRPC package. So, we can start using it in our server. So,
if you go here, we can, yeah, create our server. Then we have to run our server in a port. Let's
do this. I don't know why. Yeah. So, basically, we are retrieving the port from the environment
or as a default, we can use the 8080 port as a really default one. And then, yeah, we have to
name this function async because we are waiting. And finally, we can simply print by the server
it's listening in the port 8080, right? So, I guess we don't have to use this import.
And that's it. This is like our whole server, our whole GRPC server that we are going to connect
in Flutter. And one thing, one parameter that we are not seeing right now is this array. This
will be an array of services. That is something that we actually didn't talk about so far. So,
maybe we can jump in and talk about the services, right? Because till now, we only defined like
a model. The message. Right. The message. But we have to define also the functions that we are
going to call in our frontend to communicate with GRPC, right? So, to do that, we can get back to our
proto file. And instead of defining a message, we are going to define this time a service that
will be more or less like an interface that you need to also implement. But here, we can define
all of our methods that we are going to use to communicate with GRPC. So, maybe we can name this
to the service. And here, we can use a notation of RPC. We have our method name, our request,
and our response. So, basically, this is the notation. And I was thinking about getting a
simple to do from GRPC. So, maybe we can name this, get to do. Okay. So, here, we won't have
anything to get until we create some, right? Right. Yeah. I mean, maybe we can hard code
something just to see it. Okay. Sounds good. Or maybe, yeah, we can also create, have a method
to create a tool. But let's start with getting a tool to do. Yeah. Perfect. Okay. So, in here,
what we will have to do is to have a, remember the method, we have a request and a response. So,
we will have to return something. And this is the actual keyword returns. And we actually
have to create another message because we will have to have a request and a response that are
also messages. So, in this case, to create a, we can create a message called get to do request.
Maybe it could be by ID, right? So, we can add an ID to the request. And we can, okay, we,
maybe we can put this here. And here, as we did with the method to do, we are going to provide
maybe an int 32. So, we can pass the ID through the message. If we want to get the tool by the
ID, it's a good idea to send the ID. So, here, in our method, get to do, we can put the get to
do by ID request. And we can return just a to do, right, that we already put it in,
in our, we already have a message for that. So, basically, this method, we will be sending
get to do by the request that it has an ID. And we will return it as simple to do that. In this
case, we are going to, yeah. All right. So, perfect. And here again, as we modify the proto file, we
need to auto generate again, the generated classes, right? So, we have to hit again, the command line.
And, okay, let's go back to our proto, proto package.
And normally, if we were running build runner here, this is when we'd all get up and go get some
coffee. This is a pretty fast generation. You blink, you miss it.
Okay. So, maybe we can grab the 500. So, we can access directly. And here, we can notice that
there's another class that was generated, because we are including services right now. So, in this
case, this is not so readable, but it creates all of the communication to actually call the get to
do method. So, maybe what we can do right now is to export this class. So, we can have access in
our backend. So, here, perfect. So, I think we won't be creating so much other things in our
proto file. But, maybe we will create other methods. But, we already have like a message
and a service. And that's it to basically have our very first example connecting Flutter with
TRPC. Okay. So, let's get back to our server, right? In here, what we want to do actually is to
create a to do service. So, we can expose the service to our frontend. So, what I'm going to do
right now is to actually just create a service. But, the thing is that the service, we didn't
create it because we have our base service, that is what TRPC, the proto buff created,
auto generated. But, we have to actually implement the service. So, what we can do is to create
a service class for the service. We're going to name it to the service. And here, we can
actually create a service. And we are extending the to do service base. Okay. So, this to do
service base, what we'll have, we have like red highlight here because we are not implementing
yet the get to do method. Remember that we define that method in our service. So, it more or less
works such as an interface. You should, you need to implement those methods so we can
basically override them. And in this case, basically what we can do is just to return
a to do, right? Like a hard coded to do. So, we can have basic implementation of this method
that is returned to do. Okay. So, one cool thing about proto buff, if that you already have your
two class, you can use it with name parameters such as here, or maybe you have different methods
such as get default. And maybe this is returning no other than the default implementation with,
I don't know, like empty parameters. But we can, yeah, maybe create some basic parameters,
maybe the title, we can do title for the, for the ID, can we pull it out of the request?
Why don't we use the ID that was passed in? Yeah, that's a great idea. So, basically,
if we go here, maybe we can put final ID request dot ID. And we will use this ID instead. Perfect.
So, it will be like, yeah, the front end will generate the ID and we will return a new to do
with that ID. And then we have the completed pattern that is missing. This will be false.
Maybe what we can do also is to provide, put in the title, the ID,
our listing title, in a sense. And, okay. And, and yeah, another thing that we can do is,
okay, to actually return the to do, right? Because this is returning a feature of to do. So,
here, what we are missing is the tracing keyword. And that's it. I mean, we are implementing this
get to the method and returning it. And so, yeah, this is our definition. And now we can make use
of the service inside our server, right? So, this will expose this to the service
in the jrpc server. And we can start using it in our front end up. Okay. That's, that's really it.
Okay. So, the last thing we need to do, actually, is to create our front end up,
our flatter up, right? So, we have everything running. We will need to, this case, create another
folder. So, maybe you can create a client app in Flutter. And in here, okay, we're going to create
a basic app in Flutter using the template, the create template. And now I'm writing my example
in a macro pro, maybe we can create it using Android iOS and macOS. We could use the web,
but it's not going to work because the thing is that to deal with jrpc in the web, we have to
do some special things that it doesn't have full support yet out of the box. We have to do some
more advanced things. But yeah, we can definitely test it in mobile and desktop.
Sounds good. Yeah. So, maybe for the name, we can choose app. I'm going to use the
some new organization. And then maybe the platforms, we can choose, as I said,
Android iOS and macOS. Okay. And let's create everything here. Okay. So, this should create
our app in Flutter. Really basic stuff. So, we have our folders, iOS, Android, macOS. And we
have our pass pack YAML. So, maybe what we can do right now is to clean a little bit this pass
pack YAML. So, what we can do is to use some regular expressions to actually clean up this.
So, let's boot. I think it was, yeah, the notation was just like this, right?
Oh, you have to select the rights, right? Yeah, you're looking to get rid of all the lines.
Yeah. Sorry. There you go. Yeah. And then, nice. I normally, is it not auto formatting for you?
Oh, so, generally, I replace that with a new line. Because sometimes, if you don't replace it with a
new line, it can squish things up. Okay. We're going to do the same for our main file. So, here,
let's replace this for the comments. You know, I found, I discovered the other day,
the dash dash empty flag on flutter create just doesn't put all this gobbledygook in the files for
you. Oh, so there is a flag to do that. Yeah, flutter create dash dash empty. We don't, you
know, you've already done the heavy lifting. Yeah. But for the future dash dash empty.
Hey, we can see it. Yeah, here it is. Yeah. No comments. Perfect. Yeah, that's a nice tip. So,
we don't have to, yeah, use ragged. So, yeah, clean everything. Yeah. Right. So, here, what we have
to do is to actually import our proto buff, proto package, right? As we did with the server. So,
maybe we can quickly produce and also the path would be the same.
Perfect. So, we can have access to everything. Just for speeding up the example, we are not
going to use any kind of state management or repository pattern or something like that.
Yeah. I think that we can just use the stateful widgets that we have. Use our imaginations.
Yeah. And yeah, probably there are like best practices follow here, but I'm going to speed up.
And we kind of would like to have a client channel so we can start communicating with GRPC.
For this, we need to have a client channel. And we can have like this property. Maybe what we
can do is to import the package. Yeah. And because we are exporting the GRPC package in that package,
right? So, we can then initialize this channel in our init state. Okay. So, let's create our init
state. And here, what we can do is to create a client channel here. And the host will be,
in this case, local host, right? Because we're working in our machine. And the port, remember,
we choose 8080, although it could be the one that we are providing to the server through the
environment variables. And we also have to pass, let me see, the channel options. So, for this,
we are going to go for the channel options, like the insecure mode, but this will depend on
if you want to provide some SSL certificates, but we are going to go with the classes.
And let's put everything on cost. Okay. So, here, we already have our channel. And what we need to
create after, right now, would be the staff. So, the staff would be just an abstraction
proxy that we can use to communicate back and forth with GRPC and call, actually, our methods.
So, what we can do here is to create our staff. And to do that, let's review how to use that.
So, basically, we will need to call another auto generate class that we have that would be the
to-do service client. So, let's put here a to-do service client. And this will be our staff.
Okay. So, we can also initialize this in the, in our init state. So, here, what we can do is,
basically, to-do service client, initialize and send the channel. And that's it. We have our staff
and we can start using it to interact with all of the methods available, like our get-to-do method.
Okay. So, yeah, let's hide the channel one moment. So, we can notice that, here, we have, like, the
basic counter example, right? So, what we can do is to maybe put a fill here to, maybe what we can
do is have that to-do here. So, this won't be tight. So, we can display that to-do in our main
screen if we have one. So, that's why it's nullable. But, yeah, in our counter, this is really
setting our state of our counter. We are going to delete our counter because we don't need it.
Also, yes. And, here, what we can do is get our to-do from the server. Okay. We're going to replace
this in our icon. And, here, maybe we can say, okay, if our to-do is different than null,
we can display, maybe, a text with a title. Okay. We have to use the, oh, right. So, okay,
this is here. And, else, we can display, maybe, a text that it would say, get your to-do.
I love it. Perfect. Really simple. But, we are basically touching the whole connection.
And, okay, so, maybe what we can do also is to put this in a column. So, we can display more
information, actually. Maybe we can display, also, the ID and whether or not this is completed.
Okay. So, this information will be an integer. So, we have to parse it. And, this as well,
this will be a Boolean. So, perfect. I think this is complaining about the, okay, the cons.
Perfect. Okay. So, basically, if everything works, we will be able to see, actually, the
to-do in our Flutter app, only after we click on the get to-do bot. Okay. Perfect. So, how
we do that, right? We have to, on one hand, like, start the server, right? So, we are going to
move to the server folder. Starting the server sounds very helpful. Yeah. Totally. So, we have to,
if we go back to the server, we can see that we have our bin folder. And, inside here, we have
the server, right? So, we can simply do dart, end up server dot dart. And, the server should
be starting. Okay. The server is listening on port 8080. So, yeah. It's not like we can go to
Postman and start testing in Postman. It's more difficult because, yeah, this is another protocol.
But, we can run a wrap and see if everything is working. So, here, I can open another top.
And, we can go to our client, right? So, here, what we need to do is to run a wrap. And, I'm
going to run it first on macOS. Yeah, macOS. Absolutely the easiest way to get started.
Right. No emulators. No, yeah. No start. You know how to start emulators. That's right. But,
we can actually adjust it in iOS or Android. The thing with macOS is, it's not going to
actually work the first time, because we have to configure something, a special parameter
in the configuration. But, I think it is something like that, right?
Yeah, to be able to send network requests. Yeah. So, I'm going to show that this is going to fail,
but then we are going to fix it. So, yeah, so far, I mean, that is the whole example. Another thing
that we are going to do that is really especially important in GRBZ is that we are going to be
capable of streaming different things from the server. So, we are going to push information
into our client. That's really nice. It has a lot of use cases. So, here, we have like our
get your to do. And if we hit the button, like this won't work. But, yeah.
Are you not getting an error for this? I'm not getting an error.
Oh, because you didn't put anything in get to do.
We didn't put the method. Okay. So, here, what we need to do is...
I thought I missed that.
Yeah. Here, we need to actually get our to do. So, here, we need to pass the to do request
that we created. Oh, we kind of do need that counter, actually.
Yeah. Right. Maybe we can create a random ID here, right? So...
All right.
So, maybe I think it's not that random.
While you're typing that, Postman added GRPC support.
Oh, I didn't know that. So, someone is saying...
That's cool. That's very cool. I have to adjust that. Yeah.
Yeah. So, here, let me see math. Probably there is a library.
Oh, it's random, I think. I don't know that.
Import math for it.
So, next thing, maybe we can have like 100.
Perfect.
So, we can use the ID here. Okay. So, here, we are getting the to do.
And we have, of course, to await this.
And then, we can set the states of the R to do to this, right?
Oh, right. Because you added the keyword final there. So, it actually had not
had not set it on the widget yet. Nice.
Right. Okay. So, now again, if we restart, we are going to actually do something in our get to
bottom. And let's go back to this. And here, we have the arrow. Okay.
So, to solve this, we can enter to the...
Yeah. And it's at operation, not permitted, sockets, stuff, blah, blah, blah.
So, when you see that, you got to do what John Franco is doing now, open up Xcode.
Okay. So, let's quickly open. No, I'm going to open the Xcode project.
Okay.
I thought you were going to show me the greatest trick of all, not opening Xcode.
No, this time. Right. So, here, yeah. Here will be
the signing and capabilities, outgoing connections. Okay. So, we have to restart everything, but
this time is going to work. And, yeah. That's the whole example. Let's wait a little bit
that is loading the macOS up. And the other thing I wanted to show as I was mentioning is
how we can start streaming information from the server. So, what we are going to do is to
actually stream add to do instead of getting one to do, and that's it. But let's first...
That's this. Okay. So, this is working. We have our to do with a random ID.
So, we can keep going. And that will produce a random to real basic, right?
Okay. So, the next thing would be to stream...
Before we move on, I mean, streaming is going to be very cool, but I want to just recap kind of
what we've done so far because, you know, we've been at it for about 50 minutes now,
but a lot of that's been explanation, looking stuff up. You've written almost nothing.
And we have completely, strongly typed communication with the server.
You know, on this very show, on the boring show, we've had shared code going from the client to
the server, which, by the way, took more time than this to get working. But even that was not
strongly typed. But here, the fact that the classes, of course, are strongly typed,
if you're sharing code, but the network requests themselves were never strongly typed before.
And that is such a cool thing here. So, if we change... You know, never before has it been
true that if you change how your server works, your client will get type errors to remind you,
oh, I deleted that endpoint and I renamed it something else, you know? That has never been
a thing before. So, this is really, really neat. And it's super performant. And, like John Franco
has said, we're about to start streaming. My dog is making a lot of noise here. Yeah, really,
really, really neat. It's just so cool. Yeah, that's a really nice summary. And yeah, this was
really fast, mainly because of the auto-generated files that we have. We didn't have to create our
our to-do class, our service. This is also auto-generated. So, that's really fast, yeah. But yeah,
to give a little bit more about a more cool use case, we're going to stream this to-do.
So, we can go back to our maybe to our proto file again, where everything happens. So, if we go to
our proto package, maybe what we can do here is instead of having a get to-do that returns a to-do,
we are going to return a stream of to-dos, right? So, maybe we can rename, we can create
another method that it would be get to-do stream, maybe. And yeah, the actual request would be the
same. We can pass the... Well, it won't make sense because actually, we are not going to create
a to-do and send it to our client. What we are going to do is kind of like have a stream of
to-do and send it and push it to our client. So, maybe we can create a separate method that will
be creating our to-dos and sending to our client in streaming, right? Yeah, we could also... The
stream could just once a second, it could just add a random to-do to the stream. And then the front
end could maybe store them all and show them in the list view or something. Yeah, we can do that.
So, what we have to do here is to provide a stream of to-do and that's it. That's really simple.
We only need to modify using this keyword. We can actually also stream here from things
from the client. Maybe we can find a use case for that. But yeah, we can either have a single call,
we can have streaming from the server, from the client, without the server, or both. So,
that will depend on your use case, but you have this bi-directional communication that you can
get an advantage for that. So, what we need to do right now is, of course, to go to our commands,
produce your command again and auto-generate. Are you intending to leave the stream keyword
in the parameter? Oh, that's right. Yeah, maybe we can start simple with only streaming things from
the server. Okay, so now if we go and see about generate with product, we can see that our server
has an error because we have to re-implement the other method.
I love these errors. Hey, you forgot something. Yeah, just the best.
So, maybe we're going to create the missing override and in this case, it is the exact
same method. We have our service call and you get to the byte ID request, but we have a stream
of to-dos instead of a feature, right? So, here what we will need to do is to actually
yield to instead of returning. So, what we can do is maybe, what would be the best way to do this?
So, maybe we can have a to-do controller. So, here. We could just have a loop that
awaits a duration of one second and then omits another one. It could be well true.
So, okay. So, we have a well true. Okay, perfect. Well true. Real simple here. Yeah,
and we can yield a to-do, right? So, maybe we can grab. Scoppy. Yeah, everything from here.
But maybe a random number, right? Right. So, maybe here. Although it's funny, the request
specifies a number. So, our hypothetical is getting a little fuzzy here, but bear with us.
So, maybe here we can, yeah, nice sense and 100. Yeah, we have our to-do here and we need to yield
this to-do. So, actually, for doing this, we have to have the async star. And for anyone who's not
aware, async star, first of all, there's a great series on YouTube called,
nope, I forget the name, but Andrew Brogdon, one of the original Flutter, DevRel people,
has a five-part series on YouTube. I think the series is called Flutter and Focus. Anyway,
it's asynchronous in Dart. It goes through all this, but async star means that, A, your function
returns a stream. And every time you use the yield keyword, the object that you yield just goes on
the stream. And so, that's what we're setting up here. Perfect. So, yeah, we forgot about the
delay, because if not, this is going to provide a lot. So, let's delay a little bit this. Maybe a
second would be reasonable enough to notice. So, maybe we can put it...
Perfect, yeah. After the yield, either the beginning or the end, honestly.
Perfect. So, here, we need to modify our client, our Flutter app, so it can start receiving
these messages from the server once over a period of a second. So, if we go back to our main file,
we had our toDo here, and we will need to have a stream of toDo this time, instead of a single one.
And maybe what we can do is to then create a stream of toDo. Okay.
Okay. So... I'm excited to use the stream builder widget in so long, for see it in our future.
Yeah, that's right. I used to work a lot with stream builders before using the Flutter block
library, but then it was pointless, because Flutter block kind of kites the whole implementation,
but, yeah, back in the old days... It's still a stream builder. It's just well disguised.
Right. So, yeah, back in the old days, I used to deal with a lot of streams on our
web start. So, yeah, this was like remembering how I used to work, but in a sense... But, yeah,
the toDo stream, maybe we can put it as no, also. So, we don't have to initialize this here.
And what we can do is to initialize our toDo stream. Let's put it private.
And we, of course, have to call the staff, right? So, the method would be getToDoStream.
And our request would be the same one that we use here. We can copy.
Okay. Now, this ID will be pointless, but we just have to put it there.
And here, what we will have is our stream of toDo. So, what we can do now is to have a stream
builder, right, instead of our column. Maybe we can put here a stream builder.
And let's first provide the stream. The stream will be toDoStream.
And then we have to provide the builder, right? So, for the builder, we need the context.
And the snapshots. Okay. This is getting really long line. But I think that's it.
Okay. So, here in the snapshot, what we can do is to actually see if there is any data.
And else, we can print or show, maybe loading. Because we will wait.
Yeah, we have to cover that case. In case nothing else is in the stream.
Yeah. So, if this has data, we can probably grab our toDo from the stream. So, let's do that.
And we can display a column with the toDo, right? And we have to actually return the
column this time. And that's it. I don't know if we have to actually parse this or
be ready. But... Yeah, I'm not going to lie. I've not done this in a minute. So, I'm not really
sure either. Let's find out together. Yeah. So, here we can remove the null operators.
That's cool. And here, I have an error. Let me see.
Oh, I think I don't return this. I think this is going to work. I think this is right.
Okay. Let's cross our fingers, right? So, I'm reviewing a little bit. This getTo,
we want to be called. I mean, it can be called, but it will be the other method. And we are
calling directly the stream and using a stream builder to present data. So, if we go again,
let's rerun our server, right? Because we made some changes.
Good idea. And let's rerun. Oh, we could actually have used the call to restart.
Yeah. Yeah. Bad. Okay. That's my bad.
It's called restart. Yeah. So, here, yeah. If everything works, we are going to see
really fast, not really fast, like one second. Yeah. How random to those are heading to our...
All right. Burnly worked. Well done. Flawless. By both you and GRPC. Maybe the G stands for
John Franco. We thought about that. It could be, right? Yeah, that's another question.
Yeah. No, we'll have to check. We'll have to ask. Look at this. We are streaming data from
the server. This is so cool. Think about what you have to do to get this functionality any other way.
You have to, you know, definitely use a web socket. And that's not the end of the world,
but, oh boy, was this easier. And like you said, it feels like you call a native method
that's just like locally available, right? We're just dealing with a stream on both ends.
And then all of the guts to serialize stuff and get it on the wire and manage the connection
never had to think about it. Never thought about it at all. And it was type safe across
the boundary, across the network request boundary. Just really, really neat. Really cool.
Of course. Okay. So, yeah, that kind of wraps up the whole implementation of the full stock app,
like with our client, with our server, right? With our product package, everything. We can
share this package between client and server. We saw the implementation of a method that
is streaming information. Maybe what we can do now is test the other streaming capabilities.
You know, we mentioned that you can not only stream something from the server, but you can also
stream from the client. So you could potentially like start streaming things from the client to the
server. I don't have a really well thought example of this, but it could be something useful. So
no, I think folks get it. Yeah, no, I think, I think, I think we get it. Now, the,
but if you did that on the front end, you'd just have a stream, and you'd just add stuff to the
stream, and then it would show up on the back end. Right. Yeah. Yeah, totally. I mean, you will be
basically initializing your stream in your front end. And then, like, you will be streaming
information to the, to the backend, gRPC, and then something will happen. Maybe you can log
everything, print it, we can see it. Or yeah, I mean, we can either do that to test or another thing
I was also wanted to show is like how this can work in different platforms. Maybe we can open iOS
as well and play around. Maybe we can send messages between both of them, because here we are
streaming information to one client, but maybe we can stream information to multiple clients
at the same time. And they all are going to see the same, the same to do instead of like
different ones, right? Right, right. Well, I think that is also, you know, a pretty good,
a good example, but I think we've covered stuff quite nicely here. There are a few questions
that we should, we could get to some, there's folks have asked a couple of good ones. And I think
that is probably a nice way to finish, you know, in terms of on iOS and Android, it's going to look
just like this, you know, which is amazing. But it's not, there shouldn't be like a big jump there.
So we did get one comment earlier. I kept referring to the message as a class. And
Tokchikov says the message is more of a struct than a class, I think, because it doesn't contain
any logic. And I think that's a nice way to put it. You know, the message itself is definitely
a struct, but it is mapped one to one to a class after you run the the protoc command.
So the, the boundary between the message and the class is, you know, it feels thin sometimes. So,
but I think you are, you are technically, that is a better way to put it for sure. Now, John
Franco, I think the next few here, I'd love to get your takes on first, and then maybe I'll add
commentary at the end, whatever I'm, whatever thoughts I might have, but I think there's some,
some good questions here. So Tim asked the state management block or river pod, or others work
the same with GRPC on the front end in the back end. So I think this question is like, how does
using this impact your state management? Right. I mean, I know that in, in our client app, we
actually only present a simple example where we play around with Steffel Witcher, but this,
when you deal with this, you have to actually have a state management solution such as block of
river pod. And if you are following a good structure, a good architecture, that won't
impact really because your block will be kind of like calling probably a repository and that
repository will call ultimately a GRPC by using what we saw that is a client channel. So if you
have everything in place, you can still use like block or river pod in Flutter. And, and that won't
be, I mean, the whole point of block is just to uncouple your front end, your presentation
layer from whatever data source you have. So if you're using REST or WebSockets or GRPC,
that would be the same. So yeah, that won't impact. Yep.
And nothing to add. Well stated. Okay, next question. This one came up a couple of times. Oh,
actually, let's stick with one from Tim here, because it's a little more related.
Then we'll, we'll jump to some other questions. Tim asks, later on, how are your typical status
codes returned in a traditional REST API architecture? So I interpret this as saying,
like, how do I differentiate from, you know, a success from an error, right? Normally,
you can check, is it a 200? Is it a, if I created something, I maybe expect a 202 or 204,
kind of, however you set it up. If it's not there, it's a 404. How does that work in this setting?
Right. Yeah, I interpret the same because you clearly have, like, status codes in REST and
everyone, each of them are really telling you if you're not authenticated or if you have, like,
I don't know, different errors, just 404, right? But in this case, I think that you, of course,
I mean, we didn't, so error handling, there is a separate documentation for that. But you can
always, like, throw your, your exceptions because, yeah, you, you will have the same problems, like,
you will have to authenticate the user so you can, like, if the authentication is not working,
you can throw in a gRPC error and you can handle that in, into your client, or you can send, like,
custom exceptions, right? You can always do that. But I don't think that there is a map between,
like, status goals to actually, like, gRPC. But yeah, definitely do that, like, have, like,
maybe we didn't didn't see this, but maybe we can have an interceptor that is authenticating
each call. If something is not working, I mean, you're not authenticated, you just send a gRPC error.
And then if you, if the user, like, is authenticated, you can perform your logic and throw
custom exceptions. What could happen is that the channel connection is not working. So you have
to handle that in case you are, for example, streaming something. So you might present something
to the user. Actually, I remember we, we didn't also cover this case, but I remember when we
opened the channel, we could have closed it whenever the stateful widget is disposed. I mean,
that wasn't the case, but whenever we disposed the widget, yeah, you'll let you close the
the channel. So you don't have something like streaming unnecessary things. Yeah. And yeah.
Now, part of the way this works, where Google uses protobufs, like, for example, the Firebase SDKs,
you know, all the communication happens using protobufs. And instead of just returning it to
do, which was a perfectly reasonable kind of shortcut for this demo, instead of returning it
to do, if you also, if you look at the documentation, you'll see something like, you know, the whatever
request and the whatever response. And so instead of just returning that raw object, you can return
something that wraps it. And then you can have like an error code in there. The error code can be
its own enum, essentially. And, you know, which is like also a gRPC object. And then you, and
your client, you just check. Yeah, exactly. Yeah. And then on your client, you check,
did I get my dot to do? Or did I get my dot error? And you wouldn't, you wouldn't necessarily, you
could, if you wanted, I guess, you could set 200 equal, okay, and 404 equal not found, if you just
kind of wanted to keep that. But however you set up your errors at that point. Or another question,
this came up a couple times about like data migrations. As you, as your data evolves over
time, you add new fields, you know, I think this was the first time I saw it in the chat.
Daniel says, what's a recommended way to handle API changes, for example, adding new properties
to models or changing optional to required? Is there a way to version these changes?
Yeah, actually, there's a way of versioning. In the documentation, it says like,
but yeah, it's true that whenever you make some changes, it will impact
interior clients that are using the same protobuf models. So I think you should see
like what is the best strategy. This is like always something that is a problem, especially like
using, for example, in Reds, it's also a problem because if you add something, you can, you have to,
you will have your client that is breaking because it doesn't have the last parameter.
But in this case, as everything is already generated, at least your client will be noticed
that change, like really soon, as we saw, like everything is typed. So yeah, I guess that
versioning like your protobuf should be a really cool solution to implement.
I think I'm not hearing you.
Yeah, sorry. I muted myself. My chair makes noise.
So yeah, Pascal asked this question with a with another good angle. He said, you know,
this is this gets at kind of an awkward point when you're always talking about updating a
distributed system that has to talk to itself. So how does this deal with updates to the model?
Will all the apps be able to talk to the updated server? So yeah, what about people who don't
click that download new app version and they're running the old protobuf?
I know some thoughts about how this is handled at Google, but I'd love to first hear,
you know, how you handle this. Yeah, because I mean, the thing is that for me,
something that we didn't mention is that this kind of gRPC is also used in microservices,
architectures, right? We saw an example of using client on a server. So really communicating
at the front end with the backend. But this is really how lots of systems like that uses
microservices, architecture, it's really handy because as we
we saw, like you can especially microservice architectures where you can really choose
whatever language you need for your use case. That's really handy because you will be sharing
your definition and you can share it across multiple program languages. So yeah, in our case,
we deal mostly like with Dart. So in our case, it's really easy because when something changes
in the protobuf, mainly because of the server change, you can you have to only like update
your flatter app and that's it. But I guess that if you're having a microservice architecture,
you have to have that strategy well placed because maybe not all your services need to update,
maybe they have to continue working as they did without new definitions or changes.
So yeah, I think that there will be a real problem mostly in your microservice architecture,
especially in the backend. Yeah, a way that this works at Google is essentially required fields
are swear words and you're not allowed to add required fields because you can't trust when
when clients will be updated, even a web client, you know, someone could just have an open session
and not refresh the page. And if the server changes out underneath them, you know, all future
visitors will be fine. But current viewers could be totally hosed. So no required fields are allowed.
Now that creates its own thing where now you can't trust any of your fields, even if you know this
field is actually required, I just pretend it's optional for like backwards compatibility. Do you
really want to carry this burden into perpetuity of like, is the required field there? Oh, weird,
it was again. So you could version it for sure, you know, you could just add a new endpoint that
returns, you know, the the response v2 or something and it returns the updated model with the with
the required field there. And then the old clients just keep calling v1. And once, you know, in your
logs, you haven't seen v1 called in a month, then you can finally delete it, you know, something
like that. But it's definitely that's a tricky thing for sure. All right, there was another
question. This one a bit lighter. Wajisak? I don't think I was close there. But I wish I was closer.
asked, said slash asked, I thought of creating a chat in Flutter using gRPC. This is a good idea.
What do you think? Well, I mean, naturally, you will think about that because you have a bi-directional
support, right? So yeah, if you're dealing with a chat, the most common way like to have, for
example, a front end communication with a backend is rest, right? And yeah, rest is not a particularly
good use case for a chat because you have to send information between the your front end and your
backend. So that can be actually pushed to another client that you need to chat. So in this case,
as we can push information, this could be something that you could actually
implement in gRPC. Why not? Because, well, we didn't see it. But if we started another client,
we can actually play around a little bit and share the same streams. So we can push messages
between one client and another one. It could be done. But yeah, also, I guess that a more
suitable technology for doing that would be also WebSockets. So you can also try WebSockets to
have that communication in a chat, right? Yeah, I would say in a world where gRPC didn't exist,
in a world, there would be WebSockets would be essentially the only kind of sane way to do
things like if you just tried to use old school HTTP requests and polling and whatnot, it's like
you'd have the worst chat app ever. So WebSockets would always rule the day. But I think gRPC is
essentially you get that kind of low latency immediacy of WebSockets. It's not the same as
WebSockets. The implementation is different than where the ones in the zeros are on the wire is
different. But that doesn't really matter for most of us. I honestly just think of gRPC as
WebSockets where I got a lot of code generated for me and it's type safe across the boundary.
I mean, it might literally be on an actual WebSocket under the hood and then, you know,
I don't really know how it works. That's one of the great things about gRPC.
Like you don't have to know every single part of the stack all the way down.
But it just, you know, it's really, really, really efficient in a way that we kind of
all expect out of chat now. So I think it's a great choice for that.
Yeah, I guess that's right. It will be more efficient probably in your mobile phones that
maybe, I don't know, like nowadays it's, you can really have like a really good mobile phone,
but there are other ones that are mobile phones that are not so advanced. So you can push
that binaries instead of like string-based messages more faster and that could be like
a huge improvement in terms of efficiency by only using gRPC.
Yeah, absolutely. Well, John Franco, I think we have gotten to the end of the questions.
And I, you know, the demo was perfect. Everything worked first try.
Except when we knew it wasn't going to work because of the entitlement. So bravo there.
And man, I had a great time. I hope you had a great time.
I think our, I think the viewers had a great time. But this seems like a good time to call.
Any, any last thoughts, John Franco? No, I mean, yeah, I had a great time. I really enjoyed it.
I was actually doing the live demo was pretty cool. And yeah, any last thoughts? I know,
like, I guess that maybe if you haven't tried this technology, I guess this is a really great
starting point for doing that. It really caught my eye, especially because of the
basically sharing code between front-end and back-end. We, as Flutter developers, we always
struggle with, okay, we have to deal with a different program language in another back-end.
So why can't we use Dart, right? So, and yeah, that's that's why I keep exploring different
alternatives for doing everything full stack. And in terms of gRPC, you can really
use Dart or whatever language you like. So that's really another point on top of gRPC,
for the advantages we name it. So, so yeah, and it's, for me, it's really cool to auto-generate
these things. It's, it's worth, it works like magic and, and you can share your product files.
And that's, that's awesome. So if you can't try it, like, give it a try, but because it's,
it's a cool toolset, you could have it. And as you said, Craig, this is used by Google, so it will
let you know how they work. So, so yeah, I really enjoyed to be here and yeah, hope to be here soon.
Awesome. Yeah. Well, I think that's a great place to leave it. So everybody, I think I'm going to
be off next week, doing some prep for Google I.O. coming up in May, but I'll be back after that.
So until the next episode, have a good one, everybody. Okay, bye.

 

 

 

반응형
LIST
Comments