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.

이러한 에러 메시지는 여러 이유로 혼동을 야기한다:

  1. "operation completed successfully" 메시지의 모순: Windows API가 반환한 에러 코드를 오역한 것으로, 실제로는 작업이 실패했다.
  2. 시각적 결과: 트레이에 아이콘 자리에 빈 칸이 표시되거나 깨진 이미지가 표시된다.
  3. 원인 파악의 어려움: PNG 포맷이 지원되지 않는다는 명확한 메시지가 없어 사용자가 원인을 파악하기 어렵다.

PNG에서 ICO로 변환하기

PNG 이미지가 있다면 ICO 포맷으로 변환해야 한다. 두 가지 실용적인 방법을 소개한다.

1. 온라인 도구: CloudConvert

장점:

  • 설치 불필요
  • 웹 브라우저에서 즉시 사용 가능
  • 일괄 변환 지원

사용 방법:

  1. https://cloudconvert.com/png-to-ico에 접속
  2. PNG 파일을 업로드하거나 드래그 앤 드롭
  3. ICO 포맷으로 자동 변환
  4. 변환된 파일 다운로드

적합한 경우:

  • 일회성 변환 필요
  • 여러 파일 한 번에 처리
  • 온라인 도구 사용 선호

2. 다운로드 도구: SimplyIcon

특징:

  • Windows 전용 데스크톱 애플리케이션
  • .NET Framework 2.0 기반으로 가벼움
  • 드래그 앤 드롭 방식의 직관적 인터페이스
  • 인터넷에 파일을 올리기 꺼림직할 때 유용

자동 생성 해상도:

  • 32x32 (필수)
  • 24x24
  • 16x16
  • 128x128 (원본 이미지가 128x128 이상일 경우)

사용 방법:

  1. https://qrli.github.io/simplyicon/에서 다운로드
  2. 프로그램 실행
  3. PNG 이미지를 프로그램 윈도우로 드래그 앤 드롭
  4. 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 포맷으로 변환되어야 한다.
  • 바이너리에 아이콘이 포함되므로 실행 파일의 크기가 증가하지만, 배포 시 외부 파일을 관리할 필요가 없다.
  • 프로덕션 환경에서는 이 방식이 매우 안정적이다.

아이콘 넣기 성공!

아이콘 넣기 성공!

워크플로우 정리

  1. PNG 이미지 준비: 웹 프로젝트나 원본 아트웍에서 PNG 사용
  2. ICO로 변환: CloudConvert 또는 SimplyIcon을 사용하여 .ico 파일 생성 (필수!)
  3. Go 프로젝트에 추가: 변환한 .ico 파일을 프로젝트 디렉토리에 복사
  4. embed로 바이너리화: //go:embed 디렉티브로 빌드 시점에 포함 (반드시 .ico 파일 지정)
  5. 배포: 단일 실행 파일로 배포 (외부 파일 불필요)

권장사항

이미지 준비:

  • 원본 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! 😊

참고

  1. https://pkg.go.dev/github.com/getlantern/systray
  2. Smile icons created by Illosalz - Flaticon