[Go] Service Weaver
์๋น์ค ์๋ฒ๋ ๊ตฌ๊ธ์์ ์ง์ ๊ฐ๋ฐํ ๋ถ์ฐ ์ ํ๋ฆฌ์ผ์ด์
์ฉ ์๋ฒ ํ๋ ์์ํฌ๋ค.
๊ทธ ๋ถ์ผ ์ต๊ฐ์๋ Erlang OTP์ ํฌ์ง์
์ด ๋น์ทํ๋ค๊ณ ๋ณผ ์ ์๋ค.
์์ง ์ด์ฐฝ๊ธฐ๋ผ ๋ฒ์ ๋ 0.3๋ก ๋ฎ๊ณ , ๋ถ์์ ํ ์ ์๋ค.
๊ธฐ๋ณธ ์์ ์ค์น
์ฐ์ ํ๋ก์ ํธ ๋ง๋ค๊ณ , mod init์ผ๋ก ์ด๊ธฐํํด์ค ๋ค์์

์ ์ฉ CLI๋ฅผ ์ค์นํ๋ค.
go install github.com/ServiceWeaver/weaver/cmd/weaver@latest


ํ๋ก์ ํธ ๊ตฌ์ฑ
์์ค์ฝ๋์ ํจ๊ป Hello World ํ๋ก๊ทธ๋จ์ ๊ตฌ์ฑํด๋ณด๊ฒ ๋ค.
HTTP ์๋ฒ๊ฐ ์๋ ์ผ๋ฐ CLI ํ๋ก๊ทธ๋จ์ด๋ค.
์๋๋ ๋ฌธ์์ด์ ๋ฐ์ ์ํค๋ Reverse ํจ์๋ฅผ weaver์์ ์๊ตฌํ๋ ์๋ฒ ์ปดํฌ๋ํธ์ ํํ์ ๋ง์ถฐ ๊ตฌํํ ๊ฒ์ด๋ค.
package main
import (
"context"
"github.com/ServiceWeaver/weaver"
)
// Reverser component.
type Reverser interface {
Reverse(context.Context, string) (string, error)
}
// Implementation of the Reverser component.
type reverser struct {
weaver.Implements[Reverser]
}
func (r *reverser) Reverse(_ context.Context, s string) (string, error) {
runes := []rune(s)
n := len(runes)
for i := 0; i < n/2; i++ {
runes[i], runes[n-i-1] = runes[n-i-1], runes[i]
}
return string(runes), nil
}
์ผ๋จ์ ์คํ๋ง์ด๋ Nest.js ๋ฑ์์ ๋ค๋ฃจ๋ DI, ์๋น์ค ๋จ์์ ๋์ถฉ ๋น์ทํ๋ค๊ณ ๋ณด๋ฉด ๋๋ค. ์ค์ ๋ก๋ ์์ฃผ ๋ง์ด ๋ค๋ฅด์ง๋ง, ์ผ๋จ ์ง๊ธ์ ๊ทธ๋ ๊ฒ๋ง ์ดํดํ์.
์ ๋ ๊ฒ ์ ์ํด๋๊ณ ์๋ฒ ์์คํ ์ ํตํด ๊บผ๋ด์ ์ฐ๊ฒ ๋๋ค.
์๋๋ ๋ฉ์ธ ์์ค์ฝ๋๋ค.
package main
import (
"context"
"fmt"
"log"
"github.com/ServiceWeaver/weaver"
)
func main() {
// Initialize the Service Weaver application.
ctx := context.Background()
root := weaver.Init(ctx)
// Get a client to the Reverser component.
reverser, err := weaver.Get[Reverser](root)
if err != nil {
log.Fatal(err)
}
// Call the Reverse method.
reversed, err := reverser.Reverse(ctx, "!dlroW ,olleH")
if err != nil {
log.Fatal(err)
}
fmt.Println(reversed)
}
์ ์ํ๋ reverse ํจ์๋ฅผ weaver ๋ฐํ์์ ํตํด ๊ฐ์ ธ์ค๊ณ , ์ฌ์ฉํด์ ์ฌ๋ฐ๋ฅด๊ฒ ๋ค์งํ ํ
์คํธ๋ฅผ ์ถ๋ ฅํ๋ ๋จ์ํ ํ๋ก๊ทธ๋จ์ด๋ค.
ํ๋ฒ ์คํํด๋ณด์.
๋จผ์ tidy๋ก ์ข ์์ฑ์ ์ด๊ธฐํํด์ฃผ๊ณ
go mod tidy


weaver CLI๋ก ์ ์ํ๋ ์๋ฒ ์ปดํฌ๋ํธ์ ๋ํ ์ฝ๋๋ฅผ ์์ฑํด์ค๋ค.
weaver generate .

๊ทธ๋ผ ์ด๋ฐ์์ผ๋ก "weaver_gen" ์์ค์ฝ๋๊ฐ ์ถ๊ฐ๋ ๊ฒ์ด๋ค.
์ ๋ด์ฉ์ด ์ค์ํ๊ฑด ์๋๊ณ , ์ด๊ฒ ์์ฑ๋์ด์ผ ์คํ์ด ๋๋ค๋ ๊ฒ๋ง ์๋ฉด ๋๋ค.
๊ทธ๋ผ ๋ค์๊ณผ ๊ฐ์ด ์คํํ ์ ์๋ค.
๊ฐ๋จํ๋ค.
์ฌ๊ธฐ์ ๋ง๋ค๊ณ ์ฌ์ฉํด๋ณธ Reverser๊ฐ ๋ฐ๋ก ์๋ฒ์ ๊ทผ๊ฐ์ ์ด๋ฃจ๋ "์ปดํฌ๋ํธ" ์์คํ ์ด๋ค.
๊ทธ๋ฅ ์ ์ฝ๋๋ง ๋ณด๋ฉด ๋ณ๊ฑฐ ์๋๊ฒ์ฒ๋ผ ๋ณด์ผ ์ ์์ง๋ง, ์ปดํฌ๋ํธ๋ ์๋ฒ๋ฅผ ์ค์ ํ๊ธฐ์ ๋ฐ๋ผ์ ๊ทธ๋ฅ ํจ์๋ก ๋์ํ ์๋, ์๋๋ฉด ๋ณ๋ ํ๋ก์ธ์ค๋ก ๋์ํ ์๋ ์๊ณ , ๋ณ๋์ ๋จธ์ ์์ ๋์ํ๋๋ก ํ ์๋ ์๋ค!
ํ๋์ ํ๋ก์ ํธ ๋จ์๋ฅผ ๋ณ๋์ ๋จธ์ ์์ ๋์ํ๊ฒ ํ๋ ํธ๋ฆฌํ "๋ถ์ฐ ์์คํ
"์ด ๋ฐ๋ก ์๋ฒ๊ฐ ์งํฅํ๋ ๋ชฉํ๋ผ๊ณ ํ ์ ์๋ค.
HTTP ์๋ฒ ๋ง๋ค๊ธฐ
์ด๋ฒ์๋ ๊ทธ๋ฅ ์ฝ์ ์ฐ๊ณ ์ฃฝ๋๊ฑฐ ๋ง๊ณ ์ ๋๋ก๋ ์๋ฒ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค์ด๋ณด๊ฒ ๋ค.
์๋ฒ์์ ๋ฑํ ๋๋จํ ๊ตฌ์กฐ๋ฅผ ์ ๊ณตํ๋๊ฑด ์๋๊ณ , API ์ ์๋ ๊ธฐ๋ณธ http ๋ชจ๋๋ก ํ๋ฉด ๋๋ค.
์ ๋ฌ๋ฐ์ name์ผ๋ก ์ธ์ฌ๋ฅผ ํด์ฃผ๋ "/hello"๊ณผ ์์์ ์ ์ํ๋ reverse ํจ์๋ก ๋ค์งํ ๋ฌธ์์ด์ ๋ฐํํด์ฃผ๋ "/reverse" API๋ฅผ ์ ์ํด๋ดค๋ค.
package main
import (
"context"
"fmt"
"log"
"net/http"
"github.com/ServiceWeaver/weaver"
)
func main() {
// Initialize the Service Weaver application.
ctx := context.Background()
root := weaver.Init(ctx)
// Get a client to the Reverser component.
reverser, err := weaver.Get[Reverser](root)
if err != nil {
log.Fatal(err)
}
// Get a network listener on address "localhost:12345".
opts := weaver.ListenerOptions{LocalAddress: "localhost:12345"}
listener, err := root.Listener("hello", opts)
if err != nil {
log.Fatal(err)
}
fmt.Printf("hello listener available on %v\n", listener)
// Serve the /hello endpoint.
http.HandleFunc("/hello", func(writer http.ResponseWriter, request *http.Request) {
name := request.URL.Query().Get("name")
fmt.Fprintf(writer, "Hello, %s!\n", name)
})
// Serve the /reverse endpoint.
http.HandleFunc("/reverse", func(writer http.ResponseWriter, request *http.Request) {
reversed, err := reverser.Reverse(request.Context(), request.URL.Query().Get("text"))
if err != nil {
http.Error(writer, err.Error(), http.StatusInternalServerError)
return
}
fmt.Fprintf(writer, "%s", reversed)
})
http.Serve(listener, nil)
}
๊ทธ๋ฌ๊ณ ์คํํ๋ฉด
์ด๋ฐ์์ผ๋ก ๋ฌ๋ค.

์ ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์๋ฒ ์๋น์ค๊ฐ ๋๋ ๊ฒ์ weaver CLI๋ฅผ ํตํด์ ํ์ธํ ์ ์๋ค.
์ด๋ฐ์์ผ๋ก ๋ฌ๋ค.

์ฐธ์กฐ
https://serviceweaver.dev/
https://opensource.googleblog.com/2023/03/introducing-service-weaver-framework-for-writing-distributed-applications.html?m=1
https://serviceweaver.dev/docs.html