뇽안뇽안!
오늘도 돌아온 왕초보 강의이다. 내가 왕초보라 왕초보 눈에 맞게 쓰려고 노력했다. ㅎㅎ 나도 진짜 처음 배운 지식이라 간단한 단계의 강좌 겸 포스팅을 마련하였으니, 처음 배우는 사람들도 따라오기 적합할 것이다.
용기를 가지고 다음의 완전 간단한 예제를 따라서 코딩해보도록 하자. 딱 예제 코드 2개다! 이것만 마스터한다는 생각으로 가보자~
나도 처음에는 튜토리얼 영상보단 블로그 자료로 독학하려고 했었다. 그런데, 한국 자료들 중에는 어렵게 설명한 자료도 많고, 직접 따라해봐도 이해가지 않는 경우가 많았다.
그러나, 외국 개발자 유튜버의 튜토리얼 영상을 따라하니 10분만에 바로 쉽게 배울 수 있었다! 아래에있는 golang protocolbuffer 튜토리얼 영상을 보길 적극 권장한다. 이 포스팅은 저 영상의 내용을 정리한 것이다. (문제가 된다면 댓글 주십시오)
게다가, 완성된 코드 하나만 보고 이해하려는 게 아니라 코드를 짜는 과정을 한 단계 한 단계 따라가는 게 배우는 데 훨씬 배우기 좋다.
꼭 이 블로그 정리본을 오른쪽에, 영상을 왼쪽에 켜놓고 같이 보면서 한줄 한줄 코드 짜는 것을 따라해보자!!
어렵게만 느껴지던 protocol buffer가 이해가 되기 시작할 것이다.
https://www.youtube.com/watch?v=NoDRq6Twkts
그러니까..protocol buffer는 일종의 구조체 데이터 저장 형식이라고 보면 된다. 그 중에서도 protocol buffer는 **“직렬화”**의 원리를 사용하여 데이터 용량을 압축시켜준다고 한다.
→ 구조체 데이터를 객체에 압축 저장해주는 도구라고 보면 편할 듯하다.
1. 사전 설치 작업
protoc 패키지 설치
protoc은 proto 파일을 컴파일 하기 위한 명령어/컴파일러라고 보면 된다. 따로 설치해주자.
go get github.com/golang/protobuf
go get github.com/golang/protobuf/proto
protoc-gen-go 의존성 설치
go에서는 .proto 파일을 protoc 하기 위해 별도 의존성을 따로 제공하고 있다.
go install google.golang.org/protobuf/cmd/protoc-gen-go
proto 파일을 go 언어로 컴파일
proto 파일이 있는 디렉토리에 접근해 터미널에 다음의 명령어를 입력한다.
protoc --go_out=. *.proto
→ person.proto 파일을 컴파일하니 person.pb.go 파일이 생겼다.
protocol buffer를 사용한 go 파일의 실행
go run main.go person.pb.go
2. go에서 protocol buffer 사용하기
ex01
다음은 elliot이라는 객체에 사람의 이름, 그 사람의 나이를 함께 저장하고 압축(marshal), 압축해제(unmarshal) 해주며 각각의 값을 출력해주는 예제이다.
(엄밀히 말하자면 압축보다는 010101 등의 binary로 바꾸는 직렬화이지만, 지금 단계에서는 그냥 압축-압축해제라고 연상해서 이해하는 게 더 좋다)
일단 다음과 같이 protocol buffer 파일을 만들었다. 이때 파일 명은 person.proto 라고 정했다.
여기서 데이터 객체의 type은 모두 message이다.
syntax="proto3";
package main;
message Person {
string name=1;
int32 age=2;
}
golang으로 main.go 코드를 만들었다.
package main
import "fmt"
import "github.com/golang/protobuf/proto"
import "log"
func main() {
fmt.Println("Hello World!")
// proto 객체 형식에 맞게 데이터 저장
elliot := &Person{
Name: "Elliot",
Age: 24,
}
// data를 marshalling한 뒤, 그 data 를 출력
data, err := proto.Marshal(elliot)
if err != nill {
log.Fatal("Marshalling error", err)
}
fmt.Println(data)
// data를 unmarshalling 한 뒤, 그 data를 출력
newElliot := &Person{}
err = proto.Unmarshall(data, newElliot)
if err != nil {
log.Fatal("unmarshalling error: ", err)
}
fmt.Println(newElliot.GetAge())
fmt.Println(newElliot.GetName())
// GetAge(), GetName()은 proto.pb.go에 있는 함수
}
- marshal과 unmarshall 실행 시 모두 에러를 체크해준다.
- 두 함수 모두 동작 실패 시 nil을 리턴한다.
- unmarshalling 할 때는 새로운 빈 객체를 생성해준 뒤, unmarshal 함수에 각각 (marshal된 데이터, 새 객체)를 넣어준다.
→ marshal된 데이터 ⇒ 새 객체로 unmarshal된 데이터가 들어가는 것 같다.
→ 비유하자면, marshal ↔ unmarshal은 [암호화 ↔ 복호화], [압축 ↔ 압축해제] 이런 식으로 연상해서 생각할 수 있을 것 같다.
그런데 한가지 신기한 점으로, 저기에 GetAge()와 GetName() 함수를 볼 수 있다. 일단 내가 만든 함수는 아닌데 저게 어디서 난걸까?
저건 person.proto 파일을 person.pb.go로 컴파일할 때, pb.go 파일에 저런 함수가 자동으로 만들어진 것이다.
→ unmarshalling한 데이터 값을 저런 함수를 통해 받을 수 있어 매우 편리하다
실행 결과 다음과 같은 값을 볼 수 있다.
ex02
이제 개인정보에 sns 팔로워들 = {트위터 팔로워, 유튜브 팔로워 ... } 등의 정보도 함께 넣어볼 것이다.
다음과 같이 proto 파일을 변경하였다.
syntax="proto3"
package main;
message SocialFollowers {
int32 youtube = 1;
int32 twitter = 2;
}
message Person {
string name = 1;
int32 age = 2;
SocialFollowers socialFollowers = 3;
}
main.go 파일에서 elliot의 구조체 정의를 바꾸고, 코드 아래에 sns팔로워를 가져와 출력하는 코드도 2줄 넣었다.
elliot := &Person {
Name: "Elliot",
Age: 24,
SocialFollowers: &SocialFollowers{
Twitter: 1400,
Youtube: 2500,
},
}
fmt.Println(newElliot.SocialFollowers.GetTwitter())
fmt.Println(newElliot.SocialFollowers.GetYoutube())
실행 결과 다음과 같은 값을 볼 수 있다.
'IT > go 언어' 카테고리의 다른 글
[Go] 고 루틴(go routine)의 활용 - 기초 (0) | 2022.05.27 |
---|---|
[golang] 왕초보 grpc 튜토리얼 - 간단한 서버-클라이언트 메시지 교환 (0) | 2022.03.28 |