저는 Ubuntu Desktop을 메인 OS로 사용하고 있는데, 게임을 하나 즐기고 싶어졌습니다. 바로 Path of Exile (패스 오브 엑자일, POE) — 한국 서비스는 카카오(다음)가 맡고 있습니다. 문제는 공식 클라이언트가 Windows 전용이라는 것. 거기다 G HUB 같은 마우스 소프트웨어도 Windows 전용이라 오토클리커도 직접 만들어야 했습니다.
삽질을 꽤 했지만 결국 완전히 돌아가는 환경을 만들었고, 이 글에 그 과정을 정리합니다.
✅ 완성된 구성
- Lutris + Wine-GE-8-26으로 카카오 POE 실행
- fakeDaumgameStarter.py로 Kakao CDN 인증 자동 처리
- Awakened PoE Trade, Path of Building 동시 실행
- pynput + xdotool 기반 오토클리커 (G HUB 없이)
🛠 기술 스택
- OS: Ubuntu 24.04 Desktop
- 게임 런처: Lutris
- Wine: wine-ge-8-26-x86_64 (GE Custom 빌드)
- 인증 우회: Python 3 스크립트 (fakeDaumgameStarter.py)
- 매크로: pynput (버튼 감지) + xdotool (클릭 발생)
📋 왜 이렇게 복잡한가? — 카카오 CDN 인증 구조
일반적인 Steam POE와 달리, 한국 카카오 버전은 카카오 웹 로그인 → 게임 시작 → daumgamestarter:// 프로토콜 핸들러 순서로 실행됩니다.
이 핸들러가 daumgamestarter://poe|env|launcher|token1|token2 형태의 URL을 받아 카카오 CDN(poe.gdn.gamecdn.net)에서 토큰을 검증한 뒤 게임을 실행합니다. 토큰 없이 CDN에 접근하면 403이 반환되고, 이 경우 게임 내에서 Corrupt data from patching server 오류가 발생합니다.
📌 Wine 버전 문제, winhttp/TLS 설정 문제가 아닙니다. 항상 웹 로그인으로 토큰을 획득해야 합니다.
📁 Step 1: Lutris 및 Wine-GE 설치
먼저 Lutris를 설치합니다. (터미널 단축키 : Ctrl + Alt + T)
sudo apt install lutrisWine GE Custom 빌드는 일반 Wine보다 게임 호환성이 훨씬 좋습니다. GitHub Releases에서 wine-ge-8-26-x86_64를 다운로드하고 압축을 풉니다.
mkdir -p ~/.local/share/lutris/runners/wine/
tar -xf wine-ge-8-26-x86_64.tar.xz -C ~/.local/share/lutris/runners/wine/📁 Step 2: POE 설치
Lutris에서 수동으로 Wine 게임을 추가합니다.
- Wine runner:
wine-ge-8-26-x86_64선택 - WINEPREFIX:
/home/사용자명/Games/path-of-exile - Architecture: win64
카카오 POE 설치 파일은 아래 CDN에서 직접 다운로드할 수 있습니다.
http://poe.gdn.gamecdn.net/kg_live/Game/poe/Install/PathOfExile_Setup.exeWine으로 Setup.exe를 실행하면 기본 경로에 설치됩니다. 설치 후 실행 파일은 drive_c/Daum Games/Path of Exile/PathOfExile_KG.exe (73MB 짜리)를 사용합니다. x64_KG 버전(529KB)은 stub이라 실제 실행 불가입니다.
Winetricks로 필수 컴포넌트도 설치합니다.
WINEPREFIX=/home/사용자명/Games/path-of-exile winetricks riched20 usp10Lutris 실행 파일을 클릭해서 왼쪽 상담 + 버튼을 통해서 직접 검색 및 설치고 가능!


🐍 Step 3: fakeDaumgameStarter.py 작성
Linux에는 daumgamestarter:// 프로토콜 핸들러가 없습니다. 대신 이 Python 스크립트가 그 역할을 대신합니다. 웹 로그인 후 발급된 URL을 인수로 받아 토큰을 파싱하고 Wine으로 POE를 실행합니다.
#!/usr/bin/python3
import sys, os, subprocess
POE_PATH = "drive_c/Daum Games/Path of Exile/"
POE_CLIENT = POE_PATH + "PathOfExile_KG.exe"
def parse_url(url):
without_proto = url[18:] # 'daumgamestarter://' 제거
parts = without_proto.split("|")
if len(parts) == 1:
parts = without_proto.split("%7C") # URL 인코딩된 경우
return parts
def run_poe(data):
poe_root = "/home/사용자명/Games/path-of-exile/"
wine_path = "/home/사용자명/.local/share/lutris/runners/wine/wine-ge-8-26-x86_64/bin/wine"
env = os.environ.copy()
env["WINEPREFIX"] = poe_root
env["WINEFSYNC"] = "1"
env["WINEESYNC"] = "1"
# token1 = data[3], token2 = data[4]
cmd = [wine_path, poe_root + POE_CLIENT,
"--waitforpreload", "--nologo", "--nodx9ex", "--gc2",
"--kakao", data[3], data[4]]
subprocess.check_call(cmd, env=env, cwd=poe_root + POE_PATH)
def main():
if len(sys.argv) < 2:
print("Usage: fakeDaumgameStarter.py 'daumgamestarter://poe|env|launcher|token1|token2'")
return
parsed = parse_url(sys.argv[1])
if parsed[0] == "poe":
run_poe(parsed)
if __name__ == "__main__":
main()🌐 Step 4: xdg-open 프로토콜 핸들러 등록
daumgamestarter:// URL이 브라우저에서 클릭되면 자동으로 스크립트가 실행되도록 등록합니다.
~/.local/share/applications/daumgamestarter.desktop 파일을 생성합니다.
[Desktop Entry]
Name=Daum Game Starter (POE)
Exec=/usr/bin/python3 /home/사용자명/Games/path-of-exile/fakeDaumgameStarter.py %u
Type=Application
MimeType=x-scheme-handler/daumgamestarter;
NoDisplay=true이후 아래 명령으로 등록합니다.
xdg-mime default daumgamestarter.desktop x-scheme-handler/daumgamestarter
update-desktop-database ~/.local/share/applications/🚀 Step 5: 실행 방법
- 브라우저에서 https://poe.game.daum.net 접속
- 카카오 로그인 후 게임 시작 클릭
- 브라우저가
daumgamestarter://poe|...|token1|token2URL을 감지 - 등록된 핸들러가
fakeDaumgameStarter.py를 자동 실행 - Wine으로
PathOfExile_KG.exe --kakao token1 token2실행
📌 브라우저에서 “외부 앱 열기” 팝업이 뜨면 허용을 눌러야 합니다. Firefox 기준으로 about:config에서 network.protocol-handler.expose.daumgamestarter를 false로 설정하면 매번 물어봅니다.
🖱 G HUB 없이 마우스 매크로 만들기
로지텍 G HUB는 Linux를 지원하지 않습니다. 하지만 Python으로 충분히 대체할 수 있습니다. 핵심은 pynput으로 버튼을 감지하고, xdotool로 클릭을 발생시키는 것입니다.
⚠️ 중요한 함정: pynput의 mouse_ctrl.click()은 X11 이벤트 체인 외부에서 synthetic event를 생성하기 때문에 Ctrl, Shift 등 modifier가 전달되지 않습니다. xdotool을 사용해야 정상적으로 동작합니다.
필요한 패키지 설치
pip install pynput
sudo apt install xdotool버튼 이름 먼저 확인하기 (detect_button.py)
G502 같은 멀티버튼 마우스는 사이드 버튼이 Button.x1, Button.x2가 아니라 Button.button8 같은 이름으로 잡힐 수 있습니다. 먼저 확인합니다.
#!/usr/bin/env python3
from pynput import mouse, keyboard
def on_mouse_click(x, y, button, pressed):
if pressed:
print(f"[MOUSE] {button} (이름: {button.name})")
def on_key_press(key):
print(f"[KEYBOARD] {key}")
with mouse.Listener(on_click=on_mouse_click) as m,
keyboard.Listener(on_press=on_key_press) as k:
m.join()오토클리커 본체 (auto_clicker.py)
특정 버튼을 누르고 있는 동안 좌클릭을 반복합니다. 랜덤 간격을 줘서 패턴 감지를 회피합니다.
#!/usr/bin/env python3
import time, random, threading, subprocess
from pynput import mouse, keyboard
from pynput.mouse import Button
# ── 설정 ────────────────────────────────────────
TRIGGER_TYPE = "mouse" # "mouse" 또는 "key"
TRIGGER = Button.button8 # detect_button.py로 확인한 버튼 이름
MIN_MS = 80 # 최소 클릭 간격 (밀리초)
MAX_MS = 130 # 최대 클릭 간격 (밀리초)
# ────────────────────────────────────────────────
_clicking = False
_lock = threading.Lock()
def _click_loop():
while True:
with _lock:
if not _clicking:
return
# xdotool 사용 — modifier(Ctrl 등) 정상 전달됨
subprocess.run(['xdotool', 'click', '1'], check=False)
time.sleep(random.uniform(MIN_MS / 1000, MAX_MS / 1000))
def _start():
global _clicking
with _lock:
if _clicking:
return
_clicking = True
threading.Thread(target=_click_loop, daemon=True).start()
def _stop():
global _clicking
with _lock:
_clicking = False
def on_mouse_click(x, y, button, pressed):
if TRIGGER_TYPE == "mouse" and button == TRIGGER:
_start() if pressed else _stop()
def on_key_press(key):
if TRIGGER_TYPE == "key" and key == TRIGGER:
_start()
def on_key_release(key):
if TRIGGER_TYPE == "key" and key == TRIGGER:
_stop()
print(f"오토클리커 실행중 | 트리거: [{TRIGGER_TYPE}] {TRIGGER} | 간격: {MIN_MS}~{MAX_MS}ms")
print("Ctrl+C로 종료")
m = mouse.Listener(on_click=on_mouse_click)
k = keyboard.Listener(on_press=on_key_press, on_release=on_key_release)
m.start()
k.start()
try:
m.join()
except KeyboardInterrupt:
_stop()
m.stop()
k.stop()💡 POE 실행 시 자동 시작
fakeDaumgameStarter.py에서 POE 실행 시 오토클리커도 함께 띄우고, POE 종료 시 같이 종료되도록 연동할 수 있습니다.
import subprocess
# POE 실행 전
auto_proc = subprocess.Popen(['python3', '/path/to/auto_clicker.py'])
# POE 실행 (blocking)
subprocess.check_call(poe_cmd, env=env)
# POE 종료 후 자동 클리너
auto_proc.terminate()💡 자주 발생하는 오류 해결
- “Corrupt data from patching server” → 카카오 토큰 없이 실행한 것. 반드시 웹 로그인 후 게임 시작 버튼 클릭으로 토큰을 받아야 함.
- 화면이 검게만 나옴 →
WINEFSYNC=1 WINEESYNC=1환경변수 확인 - 한글이 깨짐 →
winetricks cjkfonts또는 Windows 한글 폰트 복사 - 오토클리커가 Ctrl+클릭이 안 됨 → pynput click 대신 xdotool 사용 필수
- xdotool click이 전경 앱에 전달 안 됨 →
DISPLAY=:0환경변수 설정 확인
🏁 마치며
처음엔 “그냥 Windows 깔면 되지” 싶었지만, 한 번 세팅해두니 Ubuntu에서도 POE를 아무 불편함 없이 즐기고 있습니다. 카카오 CDN 인증 구조만 이해하면 나머지는 생각보다 단순합니다.
G HUB 대신 Python 스크립트로 매크로를 만드는 것도 오히려 더 자유롭게 커스텀할 수 있어서 만족스럽습니다. pynput + xdotool 조합은 POE 외에도 다양한 Linux 게임 자동화에 그대로 활용할 수 있습니다.
비슷한 환경에서 시도하시는 분들께 이 글이 도움이 되길 바랍니다. 🎮