콘텐츠로 이동

Wails의 작동 원리

Wails는 백엔드에 Go프론트엔드에 웹 기술을 사용하여 데스크탑 애플리케이션을 구축하기 위한 프레임워크입니다. 하지만 Electron과 달리 Wails는 브라우저를 번들링하지 않으며, 운영 체제의 네이티브 WebView를 사용합니다.

Diagram

Electron과의 주요 차이점:

측면WailsElectron
브라우저OS 제공 WebView번들링된 Chromium (~100MB)
백엔드Go (컴파일됨)Node.js (인터프리터)
통신인메모리 브리지IPC (프로세스 간 통신)
번들 크기~15MB~150MB
메모리~10MB~100MB+
시작 시간<0.5s2-3s

Wails는 운영 체제의 내장 웹 렌더링 엔진을 사용합니다.

WebView2 (Microsoft Edge WebView2)

  • Chromium 기반 (Edge 브라우저와 동일)
  • Windows 10/11에 사전 설치됨
  • Windows Update를 통한 자동 업데이트
  • 최신 웹 표준 전체 지원

이것이 중요한 이유:

  • 번들링된 브라우저 없음 → 더 작은 애플리케이션 크기
  • OS 네이티브 → 더 나은 통합 및 성능
  • 자동 업데이트 → OS 업데이트를 통한 보안 패치
  • 익숙한 렌더링 → 시스템 브라우저와 동일

브리지는 Wails의 핵심으로, Go와 JavaScript 간의 직접 통신을 가능하게 합니다.

Diagram

작동 방식:

  1. 프론트엔드가 Go 메서드 호출 (자동 생성 바인딩을 통해)
  2. 브리지가 호출을 JSON으로 인코딩 (메서드 이름 + 인수)
  3. 라우터가 등록된 서비스에서 Go 메서드 찾기
  4. Go 메서드 실행 및 값 반환
  5. 브리지가 결과를 디코딩하여 프론트엔드로 전송
  6. JavaScript에서 Promise가 해결되며 결과 반환

성능 특성:

  • 인메모리: 네트워크 오버헤드 없음, HTTP 없음
  • 가능한 경우 제로 복사 (대용량 데이터용)
  • 기본 비동기: 양쪽 모두 차단되지 않음
  • 타입 안전: TypeScript 정의 자동 생성

서비스는 Go 기능을 프론트엔드에 노출하는 권장 방법입니다.

// Define a service (just a regular Go struct)
type GreetService struct {
prefix string
}
// Methods with exported names are automatically available
func (g *GreetService) Greet(name string) string {
return g.prefix + name + "!"
}
func (g *GreetService) GetTime() time.Time {
return time.Now()
}
// Register the service
app := application.New(application.Options{
Services: []application.Service{
application.NewService(&GreetService{prefix: "Hello, "}),
},
})

서비스 발견:

  • Wails는 시작 시 구조체를 스캔합니다.
  • 내보낸 메서드가 프론트엔드에서 호출 가능해집니다.
  • 타입 정보가 TypeScript 바인딩을 위해 추출됩니다.
  • 오류 처리가 자동화됩니다 (Go 오류 → JS 예외).

생성된 TypeScript 바인딩:

// Auto-generated in frontend/bindings/GreetService.ts
export function Greet(name: string): Promise<string>
export function GetTime(): Promise<Date>

서비스를 사용하는 이유:

  • 타입 안전: 전체 TypeScript 지원
  • 자동 발견: 메서드 수동 등록 불필요
  • 구성: 관련 기능 그룹화
  • 테스트 가능: 서비스는 단순 Go 구조체

서비스에 대해 더 알아보기 →

이벤트는 구성 요소 간 pub/sub 통신을 가능하게 합니다.

Diagram

사용 사례:

  • 창 간 통신: 한 창이 다른 창에 알림
  • 백그라운드 작업: Go 서비스가 UI에 진행 상황 알림
  • 상태 동기화: 여러 창을 동기화 상태로 유지
  • 느슨한 결합: 구성 요소가 직접 참조할 필요 없음

예제:

// Go: Emit an event
app.Event.Emit("user-logged-in", user)
// JavaScript: Listen for event
import { Events } from '@wailsio/runtime'
Events.On('user-logged-in', (user) => {
console.log('User logged in:', user)
})

이벤트에 대해 더 알아보기 →

수명 주기를 이해하면 리소스를 초기화하고 정리해야 할 시기를 알 수 있습니다.

Diagram

Lifecycle hooks:

app := application.New(application.Options{
Name: "My App",
// Called before windows are created
OnStartup: func(ctx context.Context) {
// Initialise database, load config, etc.
},
// Called when app is about to quit
OnShutdown: func() {
// Save state, close connections, etc.
},
})

Learn more about lifecycle →

Understanding how Wails builds your application:

Diagram

Build steps:

  1. Analyse Go code

    • Scan services for exported methods
    • Extract parameter and return types
    • Generate method signatures
  2. Generate TypeScript bindings

    • Create .ts files for each service
    • Include full type definitions
    • Add JSDoc comments
  3. Build frontend

    • Run your bundler (Vite, webpack, etc.)
    • Minify and optimise
    • Output to frontend/dist/
  4. Compile Go

    • Compile with optimisations (-ldflags="-s -w")
    • Include build metadata
    • Platform-specific compilation
  5. Embed assets

    • Embed frontend files into Go binary
    • Compress assets
    • Create single executable

Result: A single native executable with everything embedded.

Learn more about building →

Wails behaves differently in development and production:

Characteristics:

  • Hot reload: Frontend changes reload instantly
  • Source maps: Debug with original source
  • DevTools: Browser DevTools available
  • Logging: Verbose logging enabled
  • External frontend: Served from dev server (Vite)

How it works:

Diagram

Benefits:

  • Instant feedback on changes
  • Full debugging capabilities
  • Faster iteration

Understanding memory usage helps you build efficient applications.

Memory regions:

  1. Go Heap

    • Your services and application state
    • Managed by Go garbage collector
    • Typically 5-10MB for simple apps
  2. WebView Memory

    • DOM, JavaScript heap, CSS
    • Managed by WebView’s engine
    • Typically 10-20MB for simple apps
  3. Bridge Memory

    • Message buffers for communication
    • Minimal overhead (<1MB)
    • Zero-copy for large data where possible

Optimisation tips:

  • Avoid large data transfers: Pass IDs, fetch details on demand
  • Use events for updates: Don’t poll from frontend
  • Stream large files: Don’t load entirely into memory
  • Clean up listeners: Remove event listeners when done

Learn more about performance →

Wails provides a secure-by-default architecture:

Diagram

Security features:

  1. Method whitelisting

    • Only exported methods are callable
    • Private methods are inaccessible
    • Explicit service registration required
  2. Type validation

    • Arguments checked against Go types
    • Invalid types rejected
    • Prevents injection attacks
  3. No eval()

    • Frontend can’t execute arbitrary Go code
    • Only predefined methods callable
    • No dynamic code execution
  4. Context isolation

    • Each window has its own context
    • Services can check caller context
    • Permissions per window possible

Best practices:

  • Validate user input in Go (don’t trust frontend)
  • Use context for authentication/authorisation
  • Sanitise file paths before file operations
  • Rate limit expensive operations

Learn more about security →

Application Lifecycle - Understand startup, shutdown, and lifecycle hooks
Learn More →

Go-Frontend Bridge - Deep dive into how the bridge works
Learn More →

Build System - Understand how Wails builds your application
Learn More →

Start Building - Apply what you’ve learned in a tutorial Tutorials →


아키텍처에 대해 질문이 있으신가요? Discord에서 문의하거나 API 레퍼런스를 확인하세요.