[go-app/WASM] #3. Fiber 연결하기

2021. 11. 21. 00:12Challenge/Go

728x90

지난 2편에서 정했던 Fiber 프레임워크를 go-app과 사용하는 방법입니다.

 

[go-app/WASM] #2 서버 Framework 선택하기

Background go-app은 기본적으로 go의 내장 모듈인 net/http 를 사용합니다. net/http는 표준 라이브러리이며, 확장이 용이하고 매우 무궁무진하며 대중적이고 쉽고 간편합니다. 하지만 라우팅 부터 해서

gmyankee.tistory.com

 

 

 

 

시작하기전에

go-app에 fiber를 적용하기 위해서는 몇 가지 귀찮은 작업을 필요로 하는데 왜 그런지에 대해서 먼저 언급하고 시작하겠습니다.

 

go-app은 1편에서도 언급했듯이, JS의 역할을 대체하는 Frontend Framework 입니다.

fiber는 2편에서 정했던 Backend Framework 입니다.

 

그런데 go-app에서 작성하는 WASM을 빌드 할 때, fiber가 프로젝트 내 Externals Libarary에 설치되어 있을 때,

즉 여러분의 Go Project Environment(고 프로젝트 환경)에 fiber가 설치되어 있다면 fasthttp에 사용되는 tcplisten에서 소켓이 정의되지 않았어! 라고 오류를 뱉어냅니다.

 

소켓이 정의되지 않은 이유는 매우 간단합니다. 서버가 실행하지 않고, wasm만 빌드하고 뱉어내기 때문이죠.

이 오류를 해결하기 위해서는 프로젝트내 main 함수를 2개로 분리할 필요가 있습니다.

그런데 go-app의 클라이언트 라우팅 handler를 재 사용할 수 있게 함수화를 또 해주어야 합니다.

서버에도 해당 핸들러를 등록하여야 하기 때문이죠...

 

 

 

Client Router

// client/router.go

package client

import (
	"github.com/maxence-charriere/go-app/v9/pkg/app"
)

type hello struct {
	app.Compo
}

func (h *hello) Render() app.UI {
	return app.H1().Text("Hello World!")
}

func SetupClientRoute()  {
	// Components routing:
	app.Route("/", &hello{})
	app.RunWhenOnBrowser()
}

저는 예시를 보여드리기 위해 hello 구조체와 Render를 같은 라우터 파일에 작성하였습니다.

나중에 점차 프로젝트가 커지면, 컴포넌트로 분리해서 구조체만 빼다가 호출하는 식으로 변경됩니다.

 

 

 

Client Main

// client.go
package main

import (
	"<respository>/client"
)

func main() {
	client.SetupClientRoute()
}

client.go 는 정말 저게 다인데 fiber 새끼 때문에 이렇게 비 효율적인 파일을 만들어야 합니다.

 

 

이 파일을 다음 명령어로 빌드를 하게되면 web/app.wasm 파일이 생성됩니다.

set GOARCH=wasm
set GOOS=js
go build -o web/app.wasm

공식문서를 보면 반드시 web 폴더 하위로 존재하여야 한다고합니다. 그게아니면 동작하지 않습니다.

이건 반드시 지켜야해요!

 

 

 

 

ServeHTTP

// go_app_router.go
package router

import (
	"github.com/gofiber/adaptor/v2"
	"github.com/gofiber/fiber/v2"
	"github.com/maxence-charriere/go-app/v9/pkg/app"
)

func GoAppServeHTTP(server *fiber.App, handler *app.Handler)  {
	goAppServeFunc := adaptor.HTTPHandlerFunc(handler.ServeHTTP)

	goAppServe := server.Group("")
	goAppServe.Static("/web", "web")

	// default required server side to client-side serving files
	goAppServe.Get("/app.js", goAppServeFunc)
	goAppServe.Get("/app.css", goAppServeFunc)
	goAppServe.Get("/wasm_exec.js", goAppServeFunc)
	goAppServe.Get("/app-worker.js", goAppServeFunc)
	goAppServe.Get("/manifest.webmanifest", goAppServeFunc)
}

go-app은 handler의 ServeHTTP라는 함수를 통해서 'app.js', 'app.css', 'wasm_exec.js', 'app-worker.js', 'manifest.webmanifest' 파일들을 제공합니다.

이 파일들은 서버에서 응답해서 뱉어주도록 설계가 되어 있습니다.

하지만 fiber를 그냥 틱 갖다 붙이면 해당 경로에 요청할 경우 404 not found 이므로 이를 연결 해주어야 합니다.

 

go-app의 ServeHTTP 함수는 파라미터만 봐도 net/http 로 작성된걸 알 수 있으므로 이를 fiber로 변환시키기 위해 어댑터를 사용합니다.

 

https://github.com/gofiber/adaptor

 

GitHub - gofiber/adaptor: 🧬 Adaptor middleware to convert net/http handlers from/to Fiber request handlers

🧬 Adaptor middleware to convert net/http handlers from/to Fiber request handlers - GitHub - gofiber/adaptor: 🧬 Adaptor middleware to convert net/http handlers from/to Fiber request handlers

github.com

 

 

 

 

Server Main

// server.go

package main

import (
	"fmt"
        "<repository>/client"
	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/middleware/cors"
	"log"
)

func main()  {
	server := fiber.New()
        client.SetupClientRoute()
        indexHandler := &app.Handler{
		Name:        "Main Page",
		Title:       "테스트",
		Description: "An Hello World! example",
	}

	GoAppServeHTTP(server, indexHandler)
        server.Get("/", adaptor.HTTPHandler(indexHandler))

	fmt.Println("Server Start 🚀 :3333")
	if err := server.Listen(":3333"); err != nil {
		log.Fatalln("서버 실행 도중 오류가 발생하였습니다.")
	}
}

마찬가지로, net/http 모듈로 작성된 go-app의 app Handler를 fiber handler로 사용하려면 adaptor 를 이용해서 핸들러를 부착 시켜주고 

 

 

이제 go build server.go 를 통해 서버를 빌드 할 수 있습니다.

 

 

 

 

 

꿀팁

Goland를 사용중이신 분들은 

before launch에 Run Another Configuration으로 WASM 빌드 실행을 달아두면 개발이 굉장히 편해집니다.

서버가 실행되기 전에 WASM을 먼저 빌드해주기 때문이죠!

 

728x90