Windows 트레이(system tray)에 애플리케이션 아이콘을 표시하는 것은 백그라운드 애플리케이션의 사용성을 크게 향상시킨다. 하지만 Go에서 Windows 트레이를 구현할 때 macOS와 달리 ICO 포맷만 지원된다는 제약이 있다. 이 글에서는 이 차이점을 설명하고, PNG 이미지를 ICO로 변환하는 실용적인 솔루션을 소개한다.
Windows와 macOS의 아이콘 포맷 차이
Go에서 트레이 아이콘을 다루는 라이브러리들(예: github.com/getlantern/systray)을 사용할 때 중요한 차이점이 있다:
- macOS:
.ico,.jpg,.png이미지 포맷 지원 - Windows:
.ico포맷만 지원
Windows가 ICO 포맷만을 지원하는 이유는 Windows API의 레거시 설계와 시스템 수준의 아이콘 관리 방식에 있다. 트레이 아이콘은 16x16, 24x24, 32x32 등 여러 해상도의 이미지를 포함해야 하는데, ICO 포맷은 이러한 다중 해상도 이미지를 효율적으로 하나의 파일에 패킹할 수 있도록 설계되었다.
PNG 파일을 사용할 때의 문제점
실수로 PNG 파일(예: happy.png)을 아이콘으로 지정하면 다음과 같은 결과를 경험하게 된다:
ERROR systray: systray_windows.go:845 Unable to set icon: The operation completed successfully. [error=Unable to set icon: %v error_location=github.com/getlantern/systray.SetIcon (systray_windows.go:845) error_op= error_text=Unable to set icon: The operation completed successfully. error_type=errors.Error]
ERROR systray: systray_windows.go:845 at github.com/getlantern/systray.SetIcon (systray_windows.go:845)
ERROR systray: systray_windows.go:845 at main.onReady (main.go:18)
ERROR systray: systray_windows.go:845 at github.com/getlantern/systray.Register.func2 (systray.go:94)
ERROR systray: systray_windows.go:845 at runtime.goexit (asm_amd64.s:1693)
ERROR systray: systray_windows.go:845 Caused by: The operation completed successfully.
이러한 에러 메시지는 여러 이유로 혼동을 야기한다:
- "operation completed successfully" 메시지의 모순: Windows API가 반환한 에러 코드를 오역한 것으로, 실제로는 작업이 실패했다.
- 시각적 결과: 트레이에 아이콘 자리에 빈 칸이 표시되거나 깨진 이미지가 표시된다.
- 원인 파악의 어려움: PNG 포맷이 지원되지 않는다는 명확한 메시지가 없어 사용자가 원인을 파악하기 어렵다.
PNG에서 ICO로 변환하기
PNG 이미지가 있다면 ICO 포맷으로 변환해야 한다. 두 가지 실용적인 방법을 소개한다.
1. 온라인 도구: CloudConvert
장점:
- 설치 불필요
- 웹 브라우저에서 즉시 사용 가능
- 일괄 변환 지원
사용 방법:
- https://cloudconvert.com/png-to-ico에 접속
- PNG 파일을 업로드하거나 드래그 앤 드롭
- ICO 포맷으로 자동 변환
- 변환된 파일 다운로드
적합한 경우:
- 일회성 변환 필요
- 여러 파일 한 번에 처리
- 온라인 도구 사용 선호
2. 다운로드 도구: SimplyIcon
특징:
- Windows 전용 데스크톱 애플리케이션
- .NET Framework 2.0 기반으로 가벼움
- 드래그 앤 드롭 방식의 직관적 인터페이스
- 인터넷에 파일을 올리기 꺼림직할 때 유용
자동 생성 해상도:
- 32x32 (필수)
- 24x24
- 16x16
- 128x128 (원본 이미지가 128x128 이상일 경우)
사용 방법:
- https://qrli.github.io/simplyicon/에서 다운로드
- 프로그램 실행
- PNG 이미지를 프로그램 윈도우로 드래그 앤 드롭
- ICO 파일이 자동으로 생성
적합한 경우:
- 빈번한 변환 작업
- 오프라인 환경에서 작업
- 빠른 처리 속도 필요
- 다중 해상도 자동 생성 활용
Go 코드에서의 활용
Go의 embed 패키지를 사용하면 아이콘 파일을 바이너리에 직접 포함시킬 수 있다. 이는 배포 시 별도의 파일 관리가 필요 없어 매우 편리하다.
package main
import (
_ "embed" // For embedding the icon
"log"
"github.com/getlantern/systray"
)
//go:embed happy.ico
var iconData []byte
func main() {
systray.Run(onReady, onExit)
}
func onReady() {
systray.SetIcon(iconData)
systray.SetTitle("Happy Icon")
systray.SetTooltip("My happy icon application")
mQuit := systray.AddMenuItem("Quit", "Quit the whole app")
go func() {
<-mQuit.ClickedCh
systray.Quit()
}()
}
func onExit() {
// clean up here
log.Println("Exiting application")
}
코드 설명:
_ "embed": embed 패키지를 명시적으로 임포트한다.//go:embed happy.ico: 컴파일 타임에happy.ico파일을iconData변수에 포함시킨다. 반드시 `.ico` 파일을 사용해야 한다.systray.SetIcon(iconData): 임베드된 아이콘 데이터를 트레이 아이콘으로 설정한다.
중요한 점:
happy.ico는 프로젝트 디렉토리에 위치해야 하며, 컴파일 시점에 접근 가능해야 한다.- PNG 파일을 직접 사용할 수 없다. 반드시 ICO 포맷으로 변환되어야 한다.
- 바이너리에 아이콘이 포함되므로 실행 파일의 크기가 증가하지만, 배포 시 외부 파일을 관리할 필요가 없다.
- 프로덕션 환경에서는 이 방식이 매우 안정적이다.
아이콘 넣기 성공!
워크플로우 정리
- PNG 이미지 준비: 웹 프로젝트나 원본 아트웍에서 PNG 사용
- ICO로 변환: CloudConvert 또는 SimplyIcon을 사용하여
.ico파일 생성 (필수!) - Go 프로젝트에 추가: 변환한
.ico파일을 프로젝트 디렉토리에 복사 - embed로 바이너리화:
//go:embed디렉티브로 빌드 시점에 포함 (반드시.ico파일 지정) - 배포: 단일 실행 파일로 배포 (외부 파일 불필요)
권장사항
이미지 준비:
- 원본 PNG는 최소 32x32 이상의 해상도 권장
- 최적 해상도는 128x128 이상 (다양한 DPI 대응)
- 투명도가 필요한 경우 PNG의 알파 채널 활용
포맷 변환:
- 중요: Windows 트레이는 ICO 포맷만 지원한다. PNG 파일을 사용하면 에러가 발생한다.
- 변환 선택:
- 빠른 일회성 작업: CloudConvert
- 반복적 변환: SimplyIcon
- 자동화 필요: 명령줄 도구(ImageMagick, ffmpeg 등) 고려
배포 전략:
- embed 패키지를 사용하면 단일 바이너리로 배포 가능
- 아이콘 업데이트 시 코드 재컴파일 필요 (단순하고 버전 관리 용이)
- ICO 포맷 확인: embed 시에는 반드시
.ico확장자를 확인
결론
Windows 트레이 아이콘은 ICO 포맷만 지원하며, PNG 파일을 사용하면 에러가 발생하고 트레이에 빈 칸이 표시된다. 이는 제약이 아니라 Windows 시스템 설계의 일부이며, CloudConvert나 SimplyIcon 같은 간단한 도구를 통해 쉽게 해결할 수 있다. Go의 embed 패키지와 함께 사용하면 배포도 간단해지며, 프로덕션 환경에서 안정적인 아이콘 관리 방식을 구축할 수 있다.
Happy coding! 😊