mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-04 00:43:14 +08:00
195 lines
8.7 KiB
Plaintext
195 lines
8.7 KiB
Plaintext
# 애플리케이션 개발
|
|
|
|
Wails로 애플리케이션을 개발하기 위한 엄격한 규칙은 없으나 몇 가지의 기본 가이드가 있습니다.
|
|
|
|
## 애플리케이션 셋업
|
|
|
|
기본 템플릿에서 사용되는 패턴은 `main.go`가 애플리케이션 구성 및 실행에 사용되는 반면 `app.go`는 애플리케이션 로직 정의에 사용된다는 것입니다.
|
|
|
|
`app.go` 파일은 기본 애플리케이션에 hook 역할을 하는 2개의 메소드가 있는 구조체를 정의합니다.
|
|
|
|
```go title="app.go"
|
|
type App struct {
|
|
ctx context.Context
|
|
}
|
|
|
|
func NewApp() *App {
|
|
return &App{}
|
|
}
|
|
|
|
func (a *App) startup(ctx context.Context) {
|
|
a.ctx = ctx
|
|
}
|
|
|
|
func (a *App) shutdown(ctx context.Context) {
|
|
}
|
|
```
|
|
|
|
- 시작 메서드는 Wails가 필요한 리소스를 할당하는 즉시 호출되며 리소스 생성, 이벤트 리스너 설정 및 시작 시 응용 프로그램에 필요한 모든 것을 설정하기에 좋은 위치입니다. 일반적으로 구조체 필드에 저장되는 `context.Context`가 제공됩니다. 이 컨텍스트는 [런타임](../reference/runtime/intro.mdx)을 호출하는 데 필요합니다. 이 메서드가 오류를 반환하면 응용 프로그램이 종료됩니다. 개발 모드에서는 오류가 콘솔에 출력됩니다.
|
|
|
|
- Shutdown 메소드는 shutdown 프로세스가 끝날 때 바로 Wails에 의해 호출됩니다. 이것은 메모리 할당을 해제하고 모든 shutodown 작업을 수행하기에 좋은 위치입니다.
|
|
|
|
`main.go` 파일은 일반적으로 애플리케이션 구성을 허용하는 `wails.Run()`에 대한 단일 호출로 구성됩니다. 템플릿에서 사용하는 패턴은 `wails.Run()`을 호출하기 전에 `app.go`에서 정의한 구조체의 인스턴스가 생성되어 변수에 저장된다는 것입니다. 이것은 `app`이라고 합니다. 이 configuration 은 콜백을 추가하는 위치입니다:
|
|
|
|
```go {3,9,10} title="main.go"
|
|
func main() {
|
|
|
|
app := NewApp()
|
|
|
|
err := wails.Run(&options.App{
|
|
Title: "My App",
|
|
Width: 800,
|
|
Height: 600,
|
|
OnStartup: app.startup,
|
|
OnShutdown: app.shutdown,
|
|
})
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
애플리케이션 lifecycle hook에 대한 자세한 내용은 [여기](../howdoesitwork.mdx#application-lifecycle-callbacks)에서 확인할 수 있습니다.
|
|
|
|
## 바인딩 메소드
|
|
|
|
프론트엔드에서 Go 메서드를 호출할 가능성이 높습니다. 이는 일반적으로 `app.go`에서 이미 정의된 구조체에 public method를 추가하여 수행됩니다.
|
|
|
|
```go {16-18} title="app.go"
|
|
type App struct {
|
|
ctx context.Context
|
|
}
|
|
|
|
func NewApp() *App {
|
|
return &App{}
|
|
}
|
|
|
|
func (a *App) startup(ctx context.Context) {
|
|
a.ctx = ctx
|
|
}
|
|
|
|
func (a *App) shutdown(ctx context.Context) {
|
|
}
|
|
|
|
func (a *App) Greet(name string) string {
|
|
return fmt.Sprintf("Hello %s!", name)
|
|
}
|
|
```
|
|
|
|
메인 어플리케이션 구성에서, `Bind` 키는 Wails에 무엇을 바인딩할지 알릴 수 있는 부분입니다.
|
|
|
|
```go {11-13} title="main.go"
|
|
func main() {
|
|
|
|
app := NewApp()
|
|
|
|
err := wails.Run(&options.App{
|
|
Title: "My App",
|
|
Width: 800,
|
|
Height: 600,
|
|
OnStartup: app.startup,
|
|
OnShutdown: app.shutdown,
|
|
Bind: []interface{}{
|
|
app,
|
|
},
|
|
})
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
이렇게 하면 `App` 구조체의 모든 공개 메서드가 바인딩됩니다(시작 및 종료 메서드는 바인딩되지 않음).
|
|
|
|
### 여러 구조체를 바인딩할 때의 컨텍스트 처리
|
|
|
|
여러 구조체에 대한 메서드를 바인딩하고 싶지만 런타임을 사용할 수 있도록 각 구조체가 컨텍스트에 대한 참조를 유지하기를 원하는 경우, 함수에서 좋은 패턴은 `OnStartup` 메서드에서 구조체 인스턴스로 컨텍스트를 전달하는 것입니다.
|
|
|
|
```go
|
|
func main() {
|
|
|
|
app := NewApp()
|
|
otherStruct := NewOtherStruct()
|
|
|
|
err := wails.Run(&options.App{
|
|
Title: "My App",
|
|
Width: 800,
|
|
Height: 600,
|
|
OnStartup: func(ctx context.Context){
|
|
app.SetContext(ctx)
|
|
otherStruct.SetContext(ctx)
|
|
},
|
|
OnShutdown: app.shutdown,
|
|
Bind: []interface{}{
|
|
app,
|
|
otherStruct
|
|
},
|
|
})
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
```
|
|
|
|
바인딩에 대한 더 많은 정보는 [여기](../howdoesitwork.mdx#method-binding)에서 확인할 수 있습니다.
|
|
|
|
## Application Menu
|
|
|
|
Wails는 당신의 애플리케이션에 메뉴 추가를 지원합니다. 이것은 [Menu](../reference/menus.mdx#menu) 구조체를 애플리케이션 구성에 전달하여 수행됩니다. Menu를 반환하는 메서드를 사용하는 것이 일반적이며 lifecycle hooks에 사용되는 `App` 구조체의 메서드인 경우에는 훨씬 더 일반적입니다.
|
|
|
|
```go {11} title="main.go"
|
|
func main() {
|
|
|
|
app := NewApp()
|
|
|
|
err := wails.Run(&options.App{
|
|
Title: "My App",
|
|
Width: 800,
|
|
Height: 600,
|
|
OnStartup: app.startup,
|
|
OnShutdown: app.shutdown,
|
|
Menu: app.menu(),
|
|
Bind: []interface{}{
|
|
app,
|
|
},
|
|
})
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
## Assets
|
|
|
|
Wails v2가 assets을 처리하는 방식의 장점은 그렇지 않다는 것입니다! Wails에 제공해야 하는 유일한 것은 `embed.FS`입니다. 당신이 어떻게 얻어내는가는 전적으로 당신에게 달렸습니다. 바닐라 템플릿과 같은 바닐라 html/css/js를 사용할 수 있습니다. 복잡한 빌드 시스템을 가질 수 있으나, 중요하지 않습니다.
|
|
|
|
`wails build`가 실행되면 프로젝트 최상위에서 `wails.json` 프로젝트 파일을 확인합니다. 프로젝트 파일에는 2개의 키가 있습니다.
|
|
|
|
- "frontend:install"
|
|
- "frontend:build"
|
|
|
|
첫 번째는 노드 모듈을 설치하기 위해 `frontend` 디렉토리에서 실행됩니다. 두 번째는 프런트엔드 프로젝트를 빌드하기 위해 `frontend` 디렉토리에서 실행됩니다.
|
|
|
|
이 2개의 키가 주어지지 않으면 Wails는 프런트엔드에서 아무 작업도 수행하지 않습니다. 그것은 `embed.FS`에서만 기대합니다.
|
|
|
|
### AssetsHandler
|
|
|
|
Wails v2 앱은 선택적으로 `options.App`에서 `http.Handler`를 정의할 수 있습니다. 즉석에서 파일을 생성하거나 POST/PUT 요청을 처리합니다. GET 요청은 항상 `assets` FS에서 먼저 처리됩니다. FS가 요청된 파일을 찾지 못하면 요청은 제공을 위해 `http.Handler`로 전달됩니다. GET 이외의 모든 요청은 지정된 경우 `AssetsHandler`에서 직접 처리됩니다. `Assets` 옵션으로 `nil`을 지정하여 `AssetsHandler`만 사용할 수도 있습니다.
|
|
|
|
## Built in Dev Server
|
|
|
|
`wails dev`를 실행하면 내장된 dev 서버가 시작되어 프로젝트 디렉토리에서 file watcher를 시작합니다. 기본적으로 파일이 변경되면 wails는 응용 프로그램 파일인지 확인합니다(기본값: `.go`, `-e` 플래그로 구성 가능). 그렇다면 응용 프로그램을 다시 빌드하고 다시 시작합니다. 변경된 파일이 assets에 있는 경우 짧은 시간 후에 다시 로드를 발행합니다.
|
|
|
|
개발 서버는 "debouncing"이라는 기술을 사용합니다. 즉, 짧은 시간에 여러 파일이 변경될 수 있으므로 바로 다시 로드되지 않습니다. 트리거가 발생하면 다시 로드하기 전에 설정된 시간 동안 기다립니다. 다른 트리거가 발생하면 다시 대기 시간으로 재설정됩니다. 기본 값은 `100ms` 입니다. 이 값이 프로젝트에서 작동하지 않는 경우 `-debounce` 플래그를 사용하여 구성할 수 있습니다. 사용하는 경우 이 값은 프로젝트 구성에 저장되고 기본값이 됩니다.
|
|
|
|
## External Dev Server
|
|
|
|
일부 프레임워크는 자체 라이브 리로딩 서버와 함께 제공되지만 Wails Go 바인딩을 활용할 수 없습니다. 이 시나리오에서는 Wails가 감시할 빌드 디렉토리에 프로젝트를 다시 빌드하는 watcher script를 실행하는 것이 가장 좋습니다. 예를 보려면 [rollup](https://rollupjs.org/guide/en/)을 사용하는 기본 svelte 템플릿을 참조하세요. [create-react-app](https://create-react-app.dev/)의 경우 다음을 사용할 수 있습니다. [this script](https://gist.github.com/int128/e0cdec598c5b3db728ff35758abdbafd)를 사용하여 유사한 결과를 얻을 수 있습니다.
|
|
|
|
## Go Module
|
|
|
|
기본 Wails 템플릿은 "changeme"라는 모듈 이름이 포함된 `go.mod` 파일을 생성합니다. 프로젝트 생성 후에 이 파일의 이름을 변경해야 합니다.
|