기여하기

이 문서 편집

문서를 번역하거나 컴퓨터에서 전체 프로젝트를 여세요.

작업을 제출하기 전까지는 아무것도 게시되지 않습니다.

블로그

Wails v3로 가는 길

Wails 릴리스 노트 및 공지

leaanthony읽는 데 6분

다중 창 스크린샷

소개

Wails는 Go를 사용하여 크로스 플랫폼 데스크톱 애플리케이션을 더 쉽게 작성할 수 있게 해 주는 프로젝트입니다. 프런트엔드에 내장 브라우저가 아닌 네이티브 웹뷰 컴포넌트를 사용하므로, 가벼운 크기를 유지하면서도 세계에서 가장 널리 사용되는 UI 시스템의 강력한 기능을 Go에서 활용할 수 있습니다.

버전 2은 2022 9월 22일에 릴리스되었으며, 다음을 비롯한 여러 개선 사항이 포함되었습니다.

  • 널리 사용되는 Vite 프로젝트를 활용한 실시간 개발
  • 창 관리 및 메뉴 생성을 위한 풍부한 기능
  • Microsoft의 WebView2 컴포넌트
  • Go 구조체와 동일한 형태의 TypeScript 모델 생성
  • NSIS 설치 프로그램 생성
  • 난독화 빌드

현재 Wails v2는 기능이 풍부한 크로스 플랫폼 데스크톱 애플리케이션을 만들기 위한 강력한 도구를 제공합니다.

이 블로그 게시물에서는 프로젝트의 현재 상황을 살펴보고 앞으로 개선할 수 있는 부분을 알아봅니다.

현재 상황은 어떨까요?

v2 릴리스 이후 Wails의 인기가 높아지는 모습을 지켜보는 것은 놀라운 경험이었습니다. 커뮤니티의 창의성과 Wails로 만들어지는 멋진 결과물에 늘 감탄합니다. 인기가 높아질수록 프로젝트를 지켜보는 사람도 많아지고, 그에 따라 기능 요청과 버그 보고도 늘어납니다.

시간이 지나면서 프로젝트가 직면한 가장 시급한 문제 몇 가지를 파악할 수 있었습니다. 또한 프로젝트의 발전을 저해하는 몇 가지 요인도 확인할 수 있었습니다.

현재 문제점

프로젝트의 발전을 저해한다고 생각되는 영역은 다음과 같습니다.

  • API
  • 바인딩 생성
  • 빌드 시스템

API

현재 Wails 애플리케이션을 빌드하는 API는 2개 부분으로 구성됩니다.

  • 애플리케이션 API
  • 런타임 API

애플리케이션 API에는 잘 알려진 대로 함수가 1개뿐입니다. 바로 애플리케이션의 작동 방식을 제어하는 수많은 옵션을 받는 Run() 함수입니다. 사용법은 매우 간단하지만 제약도 매우 큽니다. 이는 내부의 많은 복잡성을 감추는 “선언적” 접근 방식입니다. 예를 들어 기본 창에 대한 핸들이 없으므로 기본 창과 직접 상호 작용할 수 없습니다. 그러려면 런타임 API를 사용해야 합니다. 여러 창을 만드는 것처럼 더 복잡한 작업을 하려 할 때 이는 문제가 됩니다.

런타임 API는 개발자에게 다음을 비롯한 다양한 유틸리티 함수를 제공합니다.

  • 창 관리
  • 대화 상자
  • 메뉴
  • 이벤트
  • 로그

런타임 API에는 마음에 들지 않는 부분이 몇 가지 있습니다. 첫 번째는 “컨텍스트"를 전달해야 한다는 점입니다. 이는 번거로울 뿐만 아니라, 컨텍스트를 전달한 뒤 런타임 오류를 겪는 신규 개발자에게 혼란을 줍니다.

런타임 API의 가장 큰 문제는 창을 하나만 사용하는 애플리케이션을 대상으로 설계되었다는 점입니다. 시간이 지나면서 여러 창에 대한 수요가 늘었지만, 이 API는 이에 적합하지 않습니다.

v3 API에 대한 구상

다음과 같은 작업이 가능하다면 멋지지 않을까요?

go
func main() {
    app := wails.NewApplication(options.App{})
    myWindow := app.NewWindow(options.Window{})
    myWindow.SetTitle("My Window")
    myWindow.On(events.Window.Close, func() {
        app.Quit()
    })
    app.Run()
}

이 프로그래밍 방식의 접근법은 훨씬 직관적이며 개발자가 애플리케이션 요소와 직접 상호 작용할 수 있게 해 줍니다. 현재 창과 관련된 모든 런타임 메서드는 단순히 창 객체의 메서드가 됩니다. 그 밖의 런타임 메서드는 다음과 같이 애플리케이션 객체로 옮길 수 있습니다.

go
app := wails.NewApplication(options.App{})
app.NewInfoDialog(options.InfoDialog{})
app.Log.Info("Hello World")

이는 훨씬 더 강력한 API로, 더욱 복잡한 애플리케이션을 구축할 수 있게 해 줍니다. 또한 GitHub에서 가장 많은 추천을 받은 기능인 다중 창 생성도 지원합니다.

go
func main() {
    app := wails.NewApplication(options.App{})
    myWindow := app.NewWindow(options.Window{})
    myWindow.SetTitle("My Window")
    myWindow.On(events.Window.Close, func() {
        app.Quit()
    })
    myWindow2 := app.NewWindow(options.Window{})
    myWindow2.SetTitle("My Window 2")
    myWindow2.On(events.Window.Close, func() {
        app.Quit()
    })
    app.Run()
}

바인딩 생성

Wails의 핵심 기능 중 하나는 Go 메서드를 Javascript에서 호출할 수 있도록 바인딩을 생성하는 것입니다. 현재 방식은 다소 임시방편에 가깝습니다. 특수 플래그를 사용해 애플리케이션을 빌드한 다음, 리플렉션을 사용하여 무엇이 바인딩되었는지 확인하는 결과 바이너리를 실행합니다. 이 때문에 닭이 먼저냐 달걀이 먼저냐와 같은 상황이 발생합니다. 바인딩 없이는 애플리케이션을 빌드할 수 없고, 애플리케이션을 빌드하지 않고는 바인딩을 생성할 수 없습니다. 이를 우회하는 방법은 많지만, 가장 좋은 방법은 애초에 이 접근 방식을 사용하지 않는 것입니다.

Wails 프로젝트용 정적 분석기를 작성하려는 시도가 여러 차례 있었지만 큰 진전은 없었습니다. 최근에는 이 주제에 관한 자료가 늘어나면서 구현이 조금 더 쉬워졌습니다.

AST 접근 방식은 리플렉션보다 훨씬 빠르지만 상당히 더 복잡합니다. 우선 코드에서 바인딩을 지정하는 방식에 일정한 제약을 적용해야 할 수도 있습니다. 목표는 가장 일반적인 사용 사례를 먼저 지원한 다음 나중에 범위를 확장하는 것입니다.

빌드 시스템

API의 선언적 접근 방식과 마찬가지로, 빌드 시스템도 데스크톱 애플리케이션 빌드의 복잡성을 감추기 위해 만들어졌습니다. wails build을 실행하면 내부적으로 많은 작업이 수행됩니다.

  • 바인딩 생성을 위한 백엔드 바이너리를 빌드하고 바인딩을 생성합니다.

  • 프런트엔드 종속성을 설치합니다.

  • 프런트엔드 애셋을 빌드합니다.

  • 애플리케이션 아이콘이 있는지 확인하고, 있으면 포함합니다.

  • 최종 바이너리를 빌드합니다.

  • darwin/universal용 빌드인 경우 2 바이너리를 빌드합니다. darwin/amd64용과 darwin/arm64용을 각각 하나씩 빌드한 다음, lipo을 사용하여 팻 바이너리를 생성합니다.

  • 압축이 필요한 경우 UPX로 바이너리를 압축합니다.

  • 이 바이너리를 패키징해야 하는지 확인하고, 필요한 경우 다음 작업을 수행합니다.

    • 아이콘과 애플리케이션 매니페스트가 바이너리에 컴파일되어 포함되도록 합니다(Windows).
    • 애플리케이션 번들을 구성하고 아이콘 번들을 생성한 뒤, 아이콘 번들, 바이너리 및 Info.plist를 애플리케이션 번들에 복사합니다(Mac).
  • NSIS 설치 프로그램이 필요한 경우 이를 빌드합니다.

이 전체 프로세스는 매우 강력하지만 그만큼 불투명하기도 합니다. 사용자 지정이 매우 어렵고 디버깅도 매우 어렵습니다.

v3에서는 이 문제를 해결하기 위해 Wails 외부에 존재하는 빌드 시스템으로 전환하고자 합니다. Task를 한동안 사용해 본 결과, 저는 이 도구를 무척 선호하게 되었습니다. 빌드 시스템을 구성하기에 훌륭한 도구이며 Makefile을 사용해 본 사람이라면 비교적 익숙하게 사용할 수 있을 것입니다.

빌드 시스템은 지원되는 모든 템플릿에서 기본적으로 생성되는 Taskfile.yml 파일을 사용해 구성합니다. 이 파일에는 애플리케이션 빌드나 패키징 등 현재의 모든 작업을 수행하는 데 필요한 단계가 모두 포함되므로 쉽게 사용자 지정할 수 있습니다.

이 도구는 Wails CLI의 일부로 제공되므로 별도로 설치해야 할 외부 도구는 없습니다. 즉, 계속해서 wails build을 사용할 수 있으며 지금과 동일한 모든 작업을 수행합니다. 하지만 빌드 프로세스를 사용자 지정하려면 Taskfile.yml 파일을 편집하면 됩니다. 또한 빌드 단계를 쉽게 파악할 수 있으며 원한다면 자체 빌드 시스템을 사용할 수도 있습니다.

빌드 체계에서 빠진 조각은 아이콘 생성, 압축, 패키징과 같은 빌드 프로세스의 단위 작업입니다. 개발자가 수많은 외부 도구를 설치하도록 요구하면 좋은 개발 경험을 제공할 수 없습니다. 이를 해결하기 위해 Wails CLI는 이러한 기능을 모두 CLI의 일부로 제공합니다. 따라서 별도의 외부 도구 없이도 빌드가 계속 예상대로 작동하며, 원하는 경우 빌드의 어느 단계든 원하는 도구로 대체할 수 있습니다.

이를 통해 빌드 시스템이 훨씬 투명해지고 사용자 지정이 쉬워지며, 그동안 제기된 많은 관련 문제도 해결할 수 있습니다.

기대 효과

이러한 긍정적인 변화는 프로젝트에 막대한 이점을 가져다줄 것입니다:

  • 새 API는 훨씬 직관적이며 더 복잡한 애플리케이션을 구축할 수 있게 해 줍니다.
  • 바인딩 생성에 정적 분석을 사용하면 속도가 훨씬 빨라지고 현재 프로세스의 많은 복잡성이 줄어듭니다.
  • 검증된 외부 빌드 시스템을 사용하면 빌드 프로세스가 완전히 투명해져 강력하게 사용자 지정할 수 있습니다.

프로젝트 유지관리자가 얻는 이점은 다음과 같습니다:

  • 새 API는 유지관리하기가 훨씬 쉬우며 새로운 기능과 플랫폼에도 더 쉽게 맞출 수 있습니다.
  • 새 빌드 시스템은 유지관리하고 확장하기가 훨씬 쉬워집니다. 이를 계기로 커뮤니티가 주도하는 빌드 파이프라인 생태계가 새롭게 형성되기를 바랍니다.
  • 프로젝트 내부의 관심사를 더 명확하게 분리할 수 있습니다. 이를 통해 새로운 기능과 플랫폼을 더 쉽게 추가할 수 있습니다.

계획

이를 위한 실험은 이미 상당 부분 진행되었으며 결과도 좋습니다. 현재 이 작업에 정해진 일정은 없지만, 2023년 1분기 말까지 커뮤니티가 테스트하고 실험하며 피드백을 제공할 수 있도록 Mac용 알파 릴리스를 내놓기를 바랍니다.

요약

  • v2 API는 선언적이고 개발자에게 많은 부분을 감추며 다중 창과 같은 기능에는 적합하지 않습니다. 더 단순하고 직관적이며 강력한 새 API를 만들 것입니다.
  • 빌드 시스템은 불투명하고 사용자 지정하기 어려우므로 모든 과정을 투명하게 공개하는 외부 빌드 시스템으로 전환할 것입니다.
  • 바인딩 생성은 느리고 복잡하므로 현재 방식의 많은 복잡성을 없앨 수 있는 정적 분석으로 전환할 것입니다.

v2의 내부에는 많은 노력이 투입되었으며 견고하게 구축되어 있습니다. 이제 그 위의 계층을 개선해 개발자 경험을 훨씬 향상할 때입니다.

여러분도 저만큼 이 소식에 기대를 느끼시기를 바랍니다. 여러분의 의견과 피드백을 기다리겠습니다.

감사합니다,

‐ Lea

추신: 여러분이나 여러분의 회사에서 Wails를 유용하게 사용하고 있다면 프로젝트 후원을 고려해 주세요. 감사합니다!

추신 2: 네, 저것은 Wails로 구축한 다중 창 애플리케이션의 실제 스크린샷입니다. 목업이 아닙니다. 실제로 작동합니다. 정말 멋집니다. 곧 공개됩니다.