서버 빌드
네이티브 GUI 창 없이 Wails 애플리케이션을 HTTP 서버로 실행
Wails v3는 서버 모드를 지원하므로 네이티브 창을 생성하거나 GUI 종속성을 요구하지 않고 애플리케이션을 순수 HTTP 서버로 실행할 수 있습니다. 따라서 동일한 Wails 애플리케이션을 서버와 컨테이너에 배포하고 웹 브라우저에서 사용할 수 있습니다.
서버 모드는 다음과 같은 용도에 유용합니다.
- Docker/컨테이너 배포 - X11/Wayland 종속성 없이 실행
- 서버 측 애플리케이션 - 브라우저에서 액세스할 수 있는 웹 서버로 배포
- 웹 전용 액세스 - 데스크톱과 웹에서 동일한 코드베이스 공유
- CI/CD 테스트 - 디스플레이 서버 없이 통합 테스트 실행
- 마이크로서비스 - 헤드리스 백엔드 서비스에서 Wails 바인딩 사용
빠른 시작
서버 모드는 server 빌드 태그로 활성화합니다. 애플리케이션 코드는 그대로 유지되며, 이 태그를 지정하여 빌드하기만 하면 됩니다.
# Using Taskfile (recommended)
wails3 task build:server
wails3 task run:server
# Or build directly with Go
go build -tags server -o myapp-server .
다음은 최소 구성 예제입니다.
package main
import (
"embed"
"log"
"github.com/wailsapp/wails/v3/pkg/application"
)
//go:embed frontend/dist
var assets embed.FS
func main() {
app := application.New(application.Options{
Name: "My App",
// Server options are used when built with -tags server
Server: application.ServerOptions{
Host: "localhost",
Port: 8080,
},
Services: []application.Service{
application.NewService(&MyService{}),
},
Assets: application.AssetOptions{
Handler: application.AssetFileServerFS(assets),
},
})
log.Println("Starting application...")
if err := app.Run(); err != nil {
log.Fatal(err)
}
}동일한 코드를 데스크톱 모드(태그 없이) 또는 서버 모드(-tags server 사용)로 빌드할 수 있습니다.
구성
ServerOptions
ServerOptions을 사용하여 HTTP 서버를 구성합니다.
Server: application.ServerOptions{
// Host to bind to. Default: "localhost"
// Use "0.0.0.0" to listen on all interfaces
Host: "localhost",
// Port to listen on. Default: 8080
Port: 8080,
// Request read timeout. Default: 30s
ReadTimeout: 30 * time.Second,
// Response write timeout. Default: 30s
WriteTimeout: 30 * time.Second,
// Idle connection timeout. Default: 120s
IdleTimeout: 120 * time.Second,
// Graceful shutdown timeout. Default: 30s
ShutdownTimeout: 30 * time.Second,
// Additional origins allowed to open WebSocket connections.
// Same-origin connections are always allowed.
WebSocketOriginPatterns: []string{"app.example.com"},
// Disable WebSocket origin checks. Unsafe; default: false.
WebSocketAllowAllOrigins: false,
// TLS configuration (optional)
TLS: &application.TLSOptions{
CertFile: "/path/to/cert.pem",
KeyFile: "/path/to/key.pem",
},
},기능
상태 확인 엔드포인트
/health에서 상태 확인 엔드포인트를 자동으로 사용할 수 있습니다.
curl http://localhost:8080/health
# {"status":"ok"}
이 엔드포인트는 다음 용도에 유용합니다.
- Kubernetes 라이브니스/레디니스 프로브
- 로드 밸런서 상태 확인
- 모니터링 시스템
서비스 바인딩
모든 서비스 바인딩은 데스크톱 모드와 동일하게 작동합니다.
type GreetService struct{}
func (g *GreetService) Greet(name string) string {
return "Hello, " + name + "!"
}
// Register in options
Services: []application.Service{
application.NewService(&GreetService{}),
},프런트엔드는 표준 Wails 런타임을 사용하여 이러한 바인딩을 호출할 수 있습니다.
const greeting = await wails.Call.ByName('main.GreetService.Greet', 'World');이벤트
서버 모드에서 이벤트는 양방향으로 작동합니다.
- 프런트엔드에서 백엔드로: 브라우저에서 발생한 이벤트는 HTTP를 통해 전송되며 Go 이벤트 핸들러에서 수신됩니다.
- 백엔드에서 프런트엔드로: Go에서 발생한 이벤트는 WebSocket을 통해 연결된 모든 브라우저에 브로드캐스트됩니다.
각 브라우저 탭은 고유한 이름(browser-1, browser-2 등)을 가진 “창"으로 표현되며 event.Sender을 통해 액세스할 수 있습니다.
// Listen for events from browsers
app.Event.On("user-action", func(event *application.CustomEvent) {
log.Printf("Event from %s: %v", event.Sender, event.Data)
// event.Sender will be "browser-1", "browser-2", etc.
})
// Emit events to all connected browsers
app.Event.Emit("server-update", data)프런트엔드에서는 다음과 같이 사용합니다.
// Emit event to server (and all other browsers)
await wails.Events.Emit('user-action', { action: 'click' });
// Listen for events from server
wails.Events.On('server-update', (event) => {
console.log('Update from server:', event.data);
});정상 종료
서버는 SIGINT 및 SIGTERM 신호를 정상적으로 처리합니다.
- 새 연결 수락 중지
- 활성 요청이 완료될 때까지 대기(최대
ShutdownTimeout) OnShutdown훅 실행- 서비스를 역순으로 종료
데스크톱 모드와의 차이점
| 기능 | 데스크톱 모드 | 서버 모드 |
|---|---|---|
| 네이티브 창 | 생성됨 | 브라우저 창(browser-N) |
| 시스템 트레이 | 사용 가능 | 사용 불가 |
| 네이티브 대화 상자 | 사용 가능 | 사용 불가 |
| 애플리케이션 메뉴 | 사용 가능 | 사용 불가 |
| 화면 정보 | 사용 가능 | 오류 반환 |
| 서비스 바인딩 | 작동함 | 작동함 |
| 이벤트 | 작동함 | 작동함(WebSocket 사용) |
| 애셋 | 웹뷰를 통해 제공 | HTTP를 통해 제공 |
| CGO 필요 | 예 | 아니요 |
Window API 동작
서버 모드에서는 창 관련 API가 안전하게 처리됩니다.
app.Window.NewWithOptions()- 경고를 기록하고 nil 반환app.Hide()/app.Show()- 아무 작업도 하지 않음app.Screen.GetPrimary()- 오류 반환
따라서 창을 참조하는 코드가 충돌 없이 실행될 수 있지만, 창 작업은 아무 효과가 없습니다.
프로덕션용 빌드
Task 사용(권장)
wails3 init로 생성한 프로젝트에는 build:server task가 포함됩니다:
# Build for server mode
wails3 task build:server
# Build and run
wails3 task run:server
수동 빌드
# Build with server mode
go build -tags server -o myapp-server .
Docker
Wails 프로젝트에는 바로 사용할 수 있는 Docker 설정이 포함되어 있습니다. 컨테이너에서 애플리케이션을 빌드하고 실행하려면 다음과 같이 하세요:
# Build the Docker image
wails3 task build:docker
# Run it
wails3 task run:docker
이것으로 끝입니다! 애플리케이션은 http://localhost:8080에서 사용할 수 있습니다.
몇 가지 옵션으로 빌드를 맞춤 설정할 수 있습니다:
# Use a custom image tag
wails3 task build:docker TAG=myapp:v1.0.0
# Run on a different port
wails3 task run:docker PORT=3000
생성된 Dockerfile.server는 distroless 기반의 최소 이미지를 만듭니다. 네트워크 바인딩을 자동으로 처리하므로 컨테이너 외부에서도 애플리케이션에 접근할 수 있습니다.
Docker Compose
더 복잡한 배포를 위해 상태 확인이 포함된 Docker Compose 설정은 다음과 같습니다:
services:
app:
build: .
ports:
- "8080:8080"
environment:
- WAILS_SERVER_HOST=0.0.0.0
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3사용자 지정 Dockerfile
더 세밀하게 제어해야 한다면 자체 Dockerfile을 만들 수 있습니다. 서버가 컨테이너 외부의 연결을 수락하도록 WAILS_SERVER_HOST=0.0.0.0를 설정해야 한다는 점이 핵심입니다:
# Build stage
FROM golang:alpine AS builder
WORKDIR /app
RUN apk add --no-cache git
COPY . .
RUN go mod tidy
RUN go build -tags server -ldflags="-s -w" -o server .
# Runtime stage
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/server /server
COPY --from=builder /app/frontend/dist /frontend/dist
EXPOSE 8080
ENV WAILS_SERVER_HOST=0.0.0.0
ENTRYPOINT ["/server"]보안 고려 사항
서버 모드 애플리케이션을 배포할 때는 다음 사항을 따르세요:
- 기본적으로 localhost에 바인딩 - 필요한 경우에만
0.0.0.0를 사용하세요 - 프로덕션에서 TLS 사용 -
ServerOptions.TLS를 구성하세요 - 리버스 프록시 뒤에 배치 - 보안을 강화하려면 nginx/traefik을 사용하세요
- WebSocket을 동일 출처로 유지 -
WebSocketOriginPatterns로 신뢰할 수 있는 출처만 추가하고WebSocketAllowAllOrigins는 사용하지 마세요 - 모든 입력 검증 - 일반 웹 애플리케이션과 동일한 보안 관행을 적용하세요
예제
전체 예제는 v3/examples/server/에서 확인할 수 있습니다:
cd v3/examples/server
# Using Taskfile
task dev
# Or run directly
go run -tags server .
# Open http://localhost:8080 in browser
환경 변수
코드를 변경하지 않고 서버 구성을 재정의해야 하는 배포 환경을 위해 Wails는 다음 환경 변수를 인식합니다:
| 변수 | 설명 | 기본값 |
|---|---|---|
WAILS_SERVER_HOST |
바인딩할 네트워크 인터페이스 | localhost |
WAILS_SERVER_PORT |
수신 대기할 포트 | 8080 |
이 환경 변수는 코드의 ServerOptions보다 우선합니다. 따라서 Docker 예제에서는 WAILS_SERVER_HOST=0.0.0.0를 설정합니다. 이를 통해 애플리케이션을 변경하지 않고도 컨테이너가 외부 연결을 수락할 수 있습니다.
함께 보기
- 사용자 지정 전송 방식 - 고급 IPC 맞춤 설정
- 서비스 - 서비스 바인딩 문서
- 이벤트 - 이벤트 시스템 문서
런타임 요청 크기
/wails/runtime에 대한 요청은 JSON 처리 전에 64 MiB로 제한됩니다. Content-Length가 없는 요청을 포함하여 이 제한을 초과하는 일반 요청에는 HTTP 413가 반환됩니다. 청크 방식의 런타임 업로드에는 청크당 1 MiB 및 조합된 페이로드당 64 MiB라는 별도의 제한이 그대로 적용됩니다. 필요한 경우 애플리케이션 미들웨어 또는 리버스 프록시를 사용하여 더 낮은 제한을 적용하세요.