기여하기

이 문서 편집

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

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

Wails의 작동 방식

Wails 아키텍처와 네이티브 성능을 구현하는 방식 이해하기

Wails는 백엔드에 Go를 사용하고 프런트엔드에 웹 기술을 사용하여 데스크톱 애플리케이션을 빌드하는 프레임워크입니다. 하지만 Electron과 달리 Wails는 브라우저를 번들로 포함하지 않고 운영 체제의 네이티브 WebView를 사용합니다.

Wails 앱, 프런트엔드, Go 백엔드, 운영 체제, 초기화, 정적 웹 앱 제공, OS 네이티브 WebView로 사이트 렌더링, 일반 통신, API 방식으로 호출, 서비스가 요청 처리, 응답 생성, 응답 처리

Electron과의 주요 차이점:

항목 Wails Electron
브라우저 OS에서 제공하는 WebView 번들로 포함된 Chromium(~100MB)
백엔드 Go(컴파일 방식) Node.js(인터프리트 방식)
통신 인메모리 브리지 IPC(프로세스 간 통신)
번들 크기 ~15MB ~150MB
메모리 ~10MB ~100MB+
시작 시간 <0.5초 2-3초

핵심 구성 요소

1. 네이티브 WebView

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

WebView2(Microsoft Edge WebView2)

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

이 점이 중요한 이유:

  • 브라우저를 번들로 포함하지 않음 → 더 작은 앱 크기
  • OS 네이티브 → 더 나은 통합과 성능
  • 자동 업데이트 → OS 업데이트를 통해 보안 패치 적용
  • 익숙한 렌더링 → 시스템 브라우저와 동일

2. Wails 브리지

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

프런트엔드(JavaScript), Wails 브리지, JSON 인코더, 메서드 라우터, JSON 디코더, 백엔드(Go), 등록된 서비스

작동 방식:

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

성능 특성:

  • 인메모리: 네트워크 오버헤드와 HTTP가 없음
  • 가능한 경우 제로 카피 적용(대용량 데이터)
  • 기본적으로 비동기: 양쪽 모두 논블로킹 방식
  • 타입 안전성: TypeScript 정의 자동 생성

3. 서비스 시스템

서비스는 Go 기능을 프런트엔드에 노출할 때 권장되는 방식입니다.

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 바인딩:

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

서비스를 사용하는 이유

  • 타입 안전성: TypeScript 완전 지원
  • 자동 검색: 메서드를 수동으로 등록할 필요 없음
  • 체계적인 구성: 관련 기능을 그룹화
  • 테스트 가능: 서비스는 일반 Go 구조체일 뿐임

서비스에 대해 자세히 알아보기 →

4. 이벤트 시스템

이벤트를 사용하면 컴포넌트 간에 게시/구독 통신을 수행할 수 있습니다.

Wails 이벤트 시스템, 창 1, 창 2, Go 백엔드, 이벤트 드라이버, 'data-updated' 이벤트 구독, 'data-updated' 이벤트 구독, 앱에서 Emit('data-updated', data) 호출, 구독자가 On('data-updated', handler) 처리, 구독자가 On('data-updated', handler) 처리

사용 사례:

  • 창 간 통신: 한 창에서 다른 창에 알림
  • 백그라운드 작업: Go 서비스에서 UI에 진행 상황 알림
  • 상태 동기화: 여러 창의 상태를 동기화
  • 느슨한 결합: 컴포넌트 간 직접 참조가 필요 없음

예시:

go
// Go: Emit an event
app.Event.Emit("user-logged-in", user)
javascript
// JavaScript: Listen for event
import { Events } from '@wailsio/runtime'

Events.On('user-logged-in', (user) => {
    console.log('User logged in:', user)
})

이벤트에 대해 자세히 알아보기 →

애플리케이션 수명 주기

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

애플리케이션 시작, 초기화, 애플리케이션 생성, 서비스 등록, 창/메뉴 설정, 이벤트 루프, 이벤트 처리, 메시지 처리, UI 업데이트, 종료, 리소스 정리, 상태 저장, 애플리케이션 종료

수명 주기 훅:

go
app := application.New(application.Options{
    Name: "My App",

    // Cleanly intercept quit requests (e.g. unsaved changes).
    ShouldQuit: func() bool { return true },

    // Called when the app is confirmed to be quitting — save state, close connections, etc.
    OnShutdown: func() {},
})

application.Options에는 OnStartup 필드가 없습니다. 시작 작업은 서비스의 ServiceStartup(ctx, options), app.Event.OnApplicationEvent(events.Common.ApplicationStarted, ...)을 통해 등록한 콜백 또는 단순히 app.Run() 이전에 배치해야 합니다.

수명 주기에 대해 자세히 알아보기 →

빌드 프로세스

Wails가 애플리케이션을 빌드하는 방식을 알아봅니다.

소스 코드, Go 코드 (main.go, 서비스), 프런트엔드 코드 (HTML/CSS/JS), 빌드 프로세스, Go 코드 분석, 바인딩 생성, 프런트엔드 빌드, Go 컴파일, 에셋 임베드, 출력, 네이티브 바이너리 (myapp.exe/.app)

빌드 단계:

  1. Go 코드 분석
  • 서비스에서 내보낸 메서드 검색
  • 매개변수 및 반환 타입 추출
  • 메서드 시그니처 생성
  1. TypeScript 바인딩 생성
  • 각 서비스의 .ts 파일 생성
  • 전체 타입 정의 포함
  • JSDoc 주석 추가
  1. 프런트엔드 빌드
  • 번들러 실행(Vite, webpack 등)
  • 축소 및 최적화
  • frontend/dist/에 출력
  1. Go 컴파일
  • 최적화 옵션을 적용하여 컴파일(-ldflags="-s -w")
  • 빌드 메타데이터 포함
  • 플랫폼별 컴파일
  1. 애셋 임베드
  • 프런트엔드 파일을 Go 바이너리에 임베드
  • 애셋 압축
  • 단일 실행 파일 생성

결과: 모든 요소가 임베드된 하나의 네이티브 실행 파일입니다.

빌드에 대해 자세히 알아보기 →

개발 환경과 프로덕션 환경

Wails는 개발 환경과 프로덕션 환경에서 다르게 동작합니다.

특징:

  • 핫 리로드: 프런트엔드 변경 사항을 즉시 다시 로드
  • 소스 맵: 원본 소스로 디버깅
  • DevTools: 브라우저 DevTools 사용 가능
  • 로깅: 상세 로깅 활성화
  • 외부 프런트엔드: 개발 서버(Vite)에서 제공

작동 방식:

Wails 앱, Vite 개발 서버 (localhost:5173), WebView

이점:

  • 변경 사항에 대한 즉각적인 피드백
  • 모든 디버깅 기능 사용 가능
  • 더 빠른 반복 개발

메모리 모델

메모리 사용 방식을 이해하면 효율적인 애플리케이션을 빌드할 수 있습니다.

메모리 영역:

  1. Go 힙
  • 서비스와 애플리케이션 상태
  • Go 가비지 컬렉터에서 관리
  • 간단한 앱의 경우 일반적으로 5-10MB
  1. WebView 메모리
  • DOM, JavaScript 힙, CSS
  • WebView 엔진에서 관리
  • 간단한 앱의 경우 일반적으로 10-20MB
  1. 브리지 메모리
  • 통신용 메시지 버퍼
  • 최소한의 오버헤드(<1MB)
  • 가능한 경우 대용량 데이터를 복사 없이 처리

최적화 팁:

  • 대용량 데이터 전송을 피하세요: ID를 전달하고 필요할 때 세부 정보를 가져오세요.
  • 업데이트에는 이벤트를 사용하세요: 프런트엔드에서 폴링하지 마세요.
  • 대용량 파일을 스트리밍하세요: 파일 전체를 메모리에 로드하지 마세요.
  • 리스너를 정리하세요: 사용을 마치면 이벤트 리스너를 제거하세요.

성능에 대해 자세히 알아보기 →

보안 모델

Wails는 기본적으로 안전한 아키텍처를 제공합니다:

프런트엔드(신뢰할 수 없음), Wails 브리지(검증), 백엔드(신뢰됨)

보안 기능:

  1. 메서드 허용 목록
  • 내보낸 메서드만 호출 가능
  • 비공개 메서드에는 접근 불가
  • 서비스를 명시적으로 등록해야 함
  1. 타입 검증
  • 인수를 Go 타입과 대조하여 검사
  • 유효하지 않은 타입을 거부
  • 인젝션 공격 방지
  1. eval() 없음
  • 프런트엔드에서 임의의 Go 코드를 실행할 수 없음
  • 미리 정의된 메서드만 호출 가능
  • 동적 코드 실행 없음
  1. 컨텍스트 격리
  • 각 창은 자체 컨텍스트를 사용
  • 서비스에서 호출자 컨텍스트를 확인할 수 있음
  • 창별 권한 설정 가능

권장 사항:

  • Go에서 사용자 입력을 검증하세요(프런트엔드를 신뢰하지 마세요).
  • 인증 및 권한 부여에 컨텍스트를 사용하세요.
  • 파일 작업 전에 파일 경로를 정제하세요.
  • 비용이 많이 드는 작업에 속도 제한을 적용하세요.

보안에 대해 자세히 알아보기 →

다음 단계

애플리케이션 수명 주기 - 시작, 종료 및 수명 주기 훅을 이해하세요. 자세히 알아보기 →

Go-프런트엔드 브리지 - 브리지의 작동 방식을 자세히 살펴보세요. 자세히 알아보기 →

빌드 시스템 - Wails가 애플리케이션을 빌드하는 방식을 이해하세요. 자세히 알아보기 →

빌드 시작하기 - 지금까지 배운 내용을 튜토리얼에서 적용해 보세요. 튜토리얼 →


아키텍처에 관해 궁금한 점이 있나요? Discord에서 질문하거나 API 참조 문서를 확인하세요.

페이지 편집

마지막 업데이트: