프런트엔드 런타임
프런트엔드 통합을 위한 Wails JavaScript 런타임 패키지
Wails 프런트엔드 런타임은 Wails 애플리케이션용 표준 라이브러리입니다. 애플리케이션에서 사용할 수 있는 다음과 같은 여러 기능을 제공합니다:
- 창 관리
- 대화 상자
- 브라우저 통합
- 클립보드
- 메뉴
- 시스템 정보
- 이벤트
- 상황에 맞는 메뉴
- 화면
- WML(Wails Markup Language)
Go와 프런트엔드를 통합하려면 런타임이 필요합니다. 런타임을 통합하는 방법은 2가지입니다:
@wailsio/runtime패키지 사용- 미리 빌드된 번들 사용
npm 패키지 사용
@wailsio/runtime 패키지는 프런트엔드에서 Wails 런타임에 접근할 수 있게 해 주는 JavaScript 패키지입니다. 모든 표준 템플릿에서 사용되며, 애플리케이션에 런타임을 통합할 때 권장되는 방법입니다. @wailsio/runtime 패키지를 사용하면 런타임에서 실제로 사용하는 부분만 포함됩니다.
이 패키지는 npm에서 제공되며 다음 명령으로 설치할 수 있습니다:
npm install --save @wailsio/runtime
미리 빌드된 번들 사용
일부 프로젝트에서는 JavaScript 번들러를 사용하지 않으므로 미리 빌드된 런타임 번들을 사용하는 편이 나을 수 있습니다. 다음 명령을 사용하여 이 버전을 로컬에서 생성할 수 있습니다:
wails3 generate runtime
이 명령은 현재 디렉터리에 runtime.js 파일과 runtime.debug.js 파일을 출력합니다. 이 파일은 npm 패키지와 마찬가지로 애플리케이션 스크립트에서 가져올 수 있는 ES 모듈입니다. API도 전역 window 객체로 내보내므로 간단한 애플리케이션에서는 다음과 같이 사용할 수 있습니다:
<html>
<head>
<script type="module" src="./runtime.js"></script>
<script>
window.onload = function () {
wails.Window.SetTitle("A new window title");
}
</script>
</head>
<!--- ... -->
</html>초기화
런타임은 API 함수 외에도 상황에 맞는 메뉴와 창 끌기를 지원합니다. 이러한 기능은 런타임이 초기화된 후에만 정상적으로 작동합니다. API를 사용하지 않더라도 프런트엔드 코드 어딘가에 부수 효과를 위한 import 문을 반드시 포함하세요:
import "@wailsio/runtime";번들러는 부수 효과의 존재를 감지하여 필요한 모든 초기화 코드를 빌드에 포함할 것입니다.
타입 지정 이벤트용 Vite 플러그인
런타임에는 개발 중 타입 지정 이벤트에 대한 HMR(Hot Module Replacement)을 지원하는 Vite 플러그인이 포함되어 있습니다.
설정
vite.config.ts에 플러그인을 추가하세요:
import { defineConfig } from 'vite'
import wails from '@wailsio/runtime/plugins/vite'
export default defineConfig({
plugins: [wails()],
})장점
- 자동 다시 로드:
wails3 generate bindings을 실행하면 이벤트 바인딩이 자동으로 다시 생성되고 로드됩니다. - 개발 모드:
wails3 dev와 원활하게 연동되어 변경 사항이 즉시 반영됩니다. - 타입 안전성: 자동 완성과 타입 검사를 포함한 완전한 TypeScript 지원
이벤트 등록과 함께 사용
Go에서 이벤트를 등록하세요:
type UserData struct {
ID string
Name string
}
func init() {
application.RegisterEvent[UserData]("user-updated")
}바인딩을 생성하세요:
wails3 generate bindings
# Or, to include TypeScript definitions
wails3 generate bindings -ts
# For more options, see:
wails3 generate bindings -help
프런트엔드에서 타입 지정 이벤트를 사용하세요:
import { Events } from '@wailsio/runtime'
import { UserUpdated } from './bindings/events'
// Type-safe event with autocomplete
Events.Emit(UserUpdated({
ID: "123",
Name: "John Doe"
}))API 참조
런타임은 각각 특정 기능을 제공하는 모듈로 구성됩니다. 필요한 항목만 가져오세요:
import { Events, Window, Clipboard } from '@wailsio/runtime'이벤트
Go와 JavaScript 간 통신을 위한 이벤트 시스템입니다.
On()
이벤트에 대한 콜백을 등록합니다.
function On(eventName: string, callback: (event: WailsEvent) => void): () => void
function On<T>(eventType: EventType<T>, callback: (event: WailsEvent<T>) => void): () => void반환값: 구독 해제 함수
예:
import { Events } from '@wailsio/runtime'
// Basic event listening
const unsubscribe = Events.On('user-logged-in', (event) => {
console.log('User:', event.data.username)
})
// With typed events (TypeScript)
import { UserLogin } from './bindings/events'
Events.On(UserLogin, (event) => {
// event.data is typed as UserLoginData
console.log('User:', event.data.username)
})
// Later: unsubscribe()Once()
한 번만 실행되는 콜백을 등록합니다.
function Once(eventName: string, callback: (event: WailsEvent) => void): () => void
function Once<T>(eventType: EventType<T>, callback: (event: WailsEvent<T>) => void): () => void예:
import { Events } from '@wailsio/runtime'
Events.Once('app-ready', () => {
console.log('App initialized')
})Emit()
Go 백엔드 또는 다른 창으로 이벤트를 발생시킵니다.
function Emit(name: string, data?: any): Promise<boolean>
function Emit<T>(event: Event<T>): Promise<boolean>반환값: 이벤트가 취소되면 true로, 그렇지 않으면 false로 이행되는 Promise
예:
import { Events } from '@wailsio/runtime'
// Basic event emission
const wasCancelled = await Events.Emit('button-clicked', { buttonId: 'submit' })
// With typed events (TypeScript)
import { UserLogin } from './bindings/events'
const cancelled = await Events.Emit(UserLogin({
UserID: "123",
Username: "john_doe",
LoginTime: new Date().toISOString()
}))
if (cancelled) {
console.log('Login was cancelled by a hook')
}Off()
이벤트 리스너를 제거합니다.
function Off(...eventNames: string[]): void예:
import { Events } from '@wailsio/runtime'
Events.Off('user-logged-in', 'user-logged-out')OffAll()
모든 이벤트 리스너를 제거합니다.
function OffAll(): void창
창 관리 메서드입니다. 기본 내보내기는 현재 창입니다.
import { Window } from '@wailsio/runtime'
// Current window
await Window.SetTitle('New Title')
await Window.Center()
// Get another window
const otherWindow = Window.Get('secondary')
await otherWindow.Show()표시 여부
Show() - 창을 표시합니다.
function Show(): Promise<void>Hide() - 창을 숨깁니다.
function Hide(): Promise<void>Close() - 창을 닫습니다
function Close(): Promise<void>크기 및 위치
SetSize(width, height) - 창 크기를 설정합니다
function SetSize(width: number, height: number): Promise<void>Size() - 창 크기를 가져옵니다
function Size(): Promise<{ width: number, height: number }>SetPosition(x, y) - 절대 위치를 설정합니다
function SetPosition(x: number, y: number): Promise<void>Position() - 절대 위치를 가져옵니다
function Position(): Promise<{ x: number, y: number }>Center() - 창을 화면 중앙에 배치합니다
function Center(): Promise<void>예:
import { Window } from '@wailsio/runtime'
// Resize and center
await Window.SetSize(800, 600)
await Window.Center()
// Get current size
const { width, height } = await Window.Size()창 상태
Minimise() - 창을 최소화합니다
function Minimise(): Promise<void>Maximise() - 창을 최대화합니다
function Maximise(): Promise<void>Fullscreen() - 전체 화면 모드로 전환합니다
function Fullscreen(): Promise<void>Restore() - 최소화, 최대화 또는 전체 화면 상태에서 복원합니다
function Restore(): Promise<void>IsMinimised() - 최소화 상태인지 확인합니다
function IsMinimised(): Promise<boolean>IsMaximised() - 최대화 상태인지 확인합니다
function IsMaximised(): Promise<boolean>IsFullscreen() - 전체 화면 상태인지 확인합니다
function IsFullscreen(): Promise<boolean>창 속성
SetTitle(title) - 창 제목을 설정합니다
function SetTitle(title: string): Promise<void>Name() - 창 이름을 가져옵니다
function Name(): Promise<string>SetBackgroundColour(r, g, b, a) - 배경색을 설정합니다
function SetBackgroundColour(r: number, g: number, b: number, a: number): Promise<void>SetAlwaysOnTop(alwaysOnTop) - 창을 항상 위에 표시합니다
function SetAlwaysOnTop(alwaysOnTop: boolean): Promise<void>SetResizable(resizable) - 창 크기를 조절할 수 있도록 설정합니다
function SetResizable(resizable: boolean): Promise<void>포커스 및 화면
Focus() - 창에 포커스를 설정합니다
function Focus(): Promise<void>IsFocused() - 포커스 상태인지 확인합니다
function IsFocused(): Promise<boolean>GetScreen() - 창이 표시된 화면을 가져옵니다
function GetScreen(): Promise<Screen>콘텐츠
Reload() - 페이지를 다시 로드합니다
function Reload(): Promise<void>ForceReload() - 페이지를 강제로 다시 로드합니다(캐시 삭제)
function ForceReload(): Promise<void>확대/축소
SetZoom(level) - 확대/축소 수준을 설정합니다
function SetZoom(level: number): Promise<void>GetZoom() - 확대/축소 수준을 가져옵니다
function GetZoom(): Promise<number>ZoomIn() - 화면을 확대합니다
function ZoomIn(): Promise<void>ZoomOut() - 화면을 축소합니다
function ZoomOut(): Promise<void>ZoomReset() - 확대/축소 수준을 100%로 재설정합니다
function ZoomReset(): Promise<void>인쇄
Print() - 네이티브 인쇄 대화 상자를 엽니다
function Print(): Promise<void>예:
import { Window } from '@wailsio/runtime'
// Open print dialog for current window
await Window.Print()참고: 네이티브 OS 인쇄 대화 상자를 열어 사용자가 프린터 설정을 선택하고 현재 창의 콘텐츠를 인쇄할 수 있게 합니다. WebView에서 작동하지 않을 수 있는 window.print()와 달리, 이 기능은 플랫폼의 네이티브 인쇄 API를 사용합니다.
클립보드
클립보드 작업입니다.
SetText()
클립보드 텍스트를 설정합니다.
function SetText(text: string): Promise<void>예:
import { Clipboard } from '@wailsio/runtime'
await Clipboard.SetText('Hello from Wails!')Text()
클립보드 텍스트를 가져옵니다.
function Text(): Promise<string>예:
import { Clipboard } from '@wailsio/runtime'
const clipboardText = await Clipboard.Text()
console.log('Clipboard:', clipboardText)시스템
백엔드와 직접 통신하기 위한 저수준 시스템 메서드입니다.
invoke()
원시 메시지를 백엔드로 직접 전송합니다. 이 메시지는 표준 바인딩 시스템을 우회하며 애플리케이션 옵션의 RawMessageHandler에서 처리됩니다.
function invoke(message: any): void예:
import { System } from '@wailsio/runtime'
// Send a raw message to the backend
System.invoke('my-custom-message')
// Send structured data as JSON
System.invoke(JSON.stringify({ action: 'update', value: 42 }))자세한 내용은 원시 메시지 가이드를 참조하세요.
애플리케이션
애플리케이션 수준의 메서드입니다.
Show()
애플리케이션의 모든 창을 표시합니다.
function Show(): Promise<void>Hide()
애플리케이션의 모든 창을 숨깁니다.
function Hide(): Promise<void>Quit()
애플리케이션을 종료합니다.
function Quit(): Promise<void>예:
import { Application } from '@wailsio/runtime'
// Add quit button
document.getElementById('quit-btn').addEventListener('click', async () => {
await Application.Quit()
})브라우저
기본 브라우저에서 URL을 엽니다.
OpenURL()
시스템 브라우저에서 URL을 엽니다.
function OpenURL(url: string | URL): Promise<void>예:
import { Browser } from '@wailsio/runtime'
await Browser.OpenURL('https://wails.io')화면
화면 정보 및 관리 기능입니다.
GetAll()
모든 화면을 가져옵니다.
function GetAll(): Promise<Screen[]>GetPrimary()
기본 화면을 가져옵니다.
function GetPrimary(): Promise<Screen>GetCurrent()
현재 활성 화면을 가져옵니다.
function GetCurrent(): Promise<Screen>Screen 인터페이스:
interface Screen {
ID: string
Name: string
ScaleFactor: number
X: number
Y: number
Size: { Width: number, Height: number }
Bounds: { X: number, Y: number, Width: number, Height: number }
WorkArea: { X: number, Y: number, Width: number, Height: number }
IsPrimary: boolean
Rotation: number
}예:
import { Screens } from '@wailsio/runtime'
// List all screens
const screens = await Screens.GetAll()
screens.forEach(screen => {
console.log(`${screen.Name}: ${screen.Size.Width}x${screen.Size.Height}`)
})
// Get primary screen
const primary = await Screens.GetPrimary()
console.log('Primary screen:', primary.Name)대화 상자
JavaScript에서 네이티브 OS 대화 상자를 사용합니다.
Info()
정보 대화 상자를 표시합니다.
function Info(options: MessageDialogOptions): Promise<string>예:
import { Dialogs } from '@wailsio/runtime'
await Dialogs.Info({
Title: 'Success',
Message: 'Operation completed successfully!'
})Error()
오류 대화 상자를 표시합니다.
function Error(options: MessageDialogOptions): Promise<string>Warning()
경고 대화 상자를 표시합니다.
function Warning(options: MessageDialogOptions): Promise<string>Question()
사용자 지정 버튼이 있는 질문 대화 상자를 표시합니다.
function Question(options: MessageDialogOptions): Promise<string>예:
import { Dialogs } from '@wailsio/runtime'
const result = await Dialogs.Question({
Title: 'Confirm Delete',
Message: 'Are you sure you want to delete this file?',
Buttons: [
{ Label: 'Delete', IsDefault: false },
{ Label: 'Cancel', IsDefault: true }
]
})
if (result === 'Delete') {
// Delete the file
}OpenFile()
파일 열기 대화 상자를 표시합니다.
function OpenFile(options: OpenFileDialogOptions): Promise<string | string[]>예:
import { Dialogs } from '@wailsio/runtime'
const file = await Dialogs.OpenFile({
Title: 'Select Image',
Filters: [
{ DisplayName: 'Images', Pattern: '*.png;*.jpg;*.jpeg' },
{ DisplayName: 'All Files', Pattern: '*.*' }
]
})
if (file) {
console.log('Selected:', file)
}SaveFile()
파일 저장 대화 상자를 표시합니다.
function SaveFile(options: SaveFileDialogOptions): Promise<string>WML(Wails Markup Language)
WML은 일반적인 작업을 위한 선언적 속성을 제공합니다. HTML 요소에 속성을 추가하세요:
속성
wml-event - 클릭할 때 이벤트를 발생시킵니다
<button wml-event="save-clicked">Save</button>wml-window - 창 메서드를 호출합니다
<button wml-window="Close">Close Window</button>
<button wml-window="Minimise">Minimize</button>wml-target-window - wml-window의 대상 창을 지정합니다
<button wml-window="Show" wml-target-window="settings">
Show Settings
</button>wml-openurl - 브라우저에서 URL을 엽니다
<a href="#" wml-openurl="https://wails.io">Visit Wails</a>wml-confirm - 작업 전에 확인 대화 상자를 표시합니다
<button wml-window="Close" wml-confirm="Are you sure you want to close?">
Close
</button>예:
<div>
<button wml-event="save-clicked">Save</button>
<button wml-window="Minimise">Minimize</button>
<button wml-window="Close" wml-confirm="Close window?">Close</button>
<a href="#" wml-openurl="https://github.com/wailsapp/wails">GitHub</a>
</div>전체 예제
import { Events, Window, Clipboard, Dialogs, Screens } from '@wailsio/runtime'
// Listen for events from Go
Events.On('data-updated', (event) => {
console.log('Data:', event.data)
updateUI(event.data)
})
// Window management
document.getElementById('center-btn').addEventListener('click', async () => {
await Window.Center()
})
document.getElementById('fullscreen-btn').addEventListener('click', async () => {
const isFullscreen = await Window.IsFullscreen()
if (isFullscreen) {
await Window.UnFullscreen()
} else {
await Window.Fullscreen()
}
})
// Clipboard operations
document.getElementById('copy-btn').addEventListener('click', async () => {
await Clipboard.SetText('Copied from Wails!')
})
// Dialog with confirmation
document.getElementById('delete-btn').addEventListener('click', async () => {
const result = await Dialogs.Question({
Title: 'Confirm',
Message: 'Delete this item?',
Buttons: [
{ Label: 'Delete' },
{ Label: 'Cancel', IsDefault: true }
]
})
if (result === 'Delete') {
await Events.Emit('delete-item', { id: currentItemId })
}
})
// Screen information
const screens = await Screens.GetAll()
console.log(`Detected ${screens.length} screen(s)`)
screens.forEach(screen => {
console.log(`- ${screen.Name}: ${screen.Size.Width}x${screen.Size.Height}`)
})모범 사례
✅ 권장 사항
- 선택적으로 가져오기 - 필요한 항목만 가져오세요
- 프로미스 처리하기 - 모든 메서드는 프로미스를 반환합니다
- 간단한 작업에는 WML 사용하기 - JavaScript보다 간결합니다
- 반환값 확인하기 - 특히 대화 상자에서 확인하세요
- 이벤트 구독 해제하기 - 작업이 끝나면 정리하세요
❌ 금지 사항
- await를 빠뜨리지 않기 - 대부분의 메서드는 비동기입니다
- UI를 차단하지 않기 - async/await를 올바르게 사용하세요
- 오류를 무시하지 않기 - 거부는 항상 처리하세요
TypeScript 지원
런타임에는 완전한 TypeScript 정의가 포함되어 있습니다:
import { Events, Window } from '@wailsio/runtime'
Events.On('custom-event', (event) => {
// TypeScript knows event.data, event.name, event.sender
console.log(event.data)
})
// All methods are fully typed
const size: { width: number, height: number } = await Window.Size()