PyAutoGUI 창 기준 상대 좌표 구현, pygetwindow로 창 위치 찾고 마우스 이동 자동화 가이드
🧭 창 좌표를 기준점으로 잡아 해상도와 위치가 달라도 정확히 클릭·드래그하는 방법을 소개합니다
프로그램 창을 기준으로 정확히 버튼을 눌러야 하는데, 매번 화면 해상도나 창 위치가 달라지면 클릭이 빗나가는 일이 잦습니다.
스크린 절대 좌표만 믿고 자동화를 만들면 모니터가 바뀌거나 창을 옮기는 순간 모든 좌표가 어긋나며 유지보수 비용이 커집니다.
그래서 많은 분들이 “창의 좌상단을 원점으로 삼아 상대 좌표로 제어할 수 없을까”를 고민하게 되죠.
이 글은 그 궁금증에 초점을 맞춥니다.
불필요한 복잡함 없이 창의 위치와 크기를 얻고, 그 값을 바탕으로 상대 좌표를 절대 좌표로 변환해 언제 어디서나 안정적으로 클릭·드래그·스크롤을 실행하는 흐름을 한 번에 정리했습니다.
개념 설명뿐 아니라 실무에서 부딪히는 예외 상황까지 고려해 재사용 가능한 습관을 만들 수 있도록 돕겠습니다.
핵심은 두 가지입니다.
첫째, pygetwindow로 목표 창의 위치와 크기를 정확히 파악하는 것.
둘째, PyAutoGUI에서 요구하는 화면 절대 좌표로 변환해 입력 이벤트를 보내는 것입니다.
이때 좌표계의 기준을 창의 좌상단으로 고정하면 해상도가 바뀌거나 듀얼 모니터 환경에서도 동일한 상대 좌표만으로 버튼과 컨트롤을 정확히 겨냥할 수 있습니다.
마우스 이동, 클릭, 드래그, 스크린샷 캡처까지 확장 가능한 패턴을 다루며, 코드 재사용을 염두에 둔 함수화 팁과 안정성 체크리스트도 함께 준비했습니다.
📋 목차
🔗 PyAutoGUI 창 기준 상대 좌표란?
PyAutoGUI는 기본적으로 화면 전체를 기준으로 한 절대 좌표를 사용합니다.
즉 (0,0)은 항상 메인 모니터의 좌상단이고, x는 오른쪽으로, y는 아래로 증가합니다.
하지만 자동화 대상이 특정 애플리케이션 창일 때는 창이 이동하거나 다른 모니터로 옮겨가면 절대 좌표가 바뀌어 클릭이 빗나가곤 합니다.
이 문제를 해결하는 개념이 바로 “창 기준 상대 좌표”입니다.
창의 좌상단을 원점(0,0)으로 삼고 버튼, 입력칸, 탭과 같은 UI 요소까지의 상대적 거리만 기억해 두면, 창 위치가 변해도 동일한 상대 좌표로 안정적으로 조작할 수 있습니다.
핵심 아이디어는 간단합니다.
pygetwindow로 대상 창의 left, top, width, height를 얻고, 우리가 사용하려는 상대 좌표(rel_x, rel_y)를 절대 좌표로 변환합니다.
변환 공식은 직관적입니다.
창 기준에서의 포인트를 화면 기준으로 옮기려면, abs_x = left + rel_x, abs_y = top + rel_y를 적용하면 됩니다.
이렇게 얻은 절대 좌표를 PyAutoGUI의 moveTo, click, dragTo 등에 전달하면 창 위치와 해상도가 바뀌어도 동일한 지점을 정확히 누를 수 있습니다.
이 접근은 다음과 같은 장점이 있습니다.
좌표 유지보수 비용이 낮아지고, 멀티 모니터·노트북 도킹처럼 환경이 자주 바뀌는 상황에서도 스크립트가 깨지지 않습니다.
또한 창 내부 특정 영역만 캡처하거나 색상 검출을 할 때도 동일한 원리를 적용할 수 있어, 테스트 자동화와 반자동 매크로를 폭넓게 구성할 수 있습니다.
반대로, 전체 화면을 기준으로 한 스크린샷 매칭(템플릿 매칭)을 쓰는 경우에는 창이 가려지거나 크기가 달라지면 실패 확률이 높아집니다.
창 기준 상대 좌표는 이런 취약점을 피하도록 도와줍니다.
# 개념 예시: 창 기준 상대 좌표를 화면 절대 좌표로 변환하는 흐름
# 파이썬 PyAutoGUI 창 기준 상대 좌표: pygetwindow로 창 위치→상대 이동 구현
import pygetwindow as gw
import pyautogui as pag
win = gw.getWindowsWithTitle("대상 프로그램 제목")[0] # 대상 창 찾기
left, top = win.left, win.top # 창의 좌상단 픽셀 좌표
rel_x, rel_y = 120, 64 # 창 기준 상대 좌표 예시
abs_x, abs_y = left + rel_x, top + rel_y # 변환 공식 적용
pag.moveTo(abs_x, abs_y, duration=0.15)
pag.click()
💎 핵심 포인트:
창의 좌상단을 원점으로 삼아 상대 좌표를 기록하고, 실행 시점에 pygetwindow로 얻은 left·top을 더해 절대 좌표로 변환합니다.
이 패턴만 지켜도 창 이동, 해상도 변경, 듀얼 모니터 등 변수에 흔들리지 않는 자동화를 만들 수 있습니다.
⚠️ 주의: Windows의 DPI 스케일링이 125%·150%처럼 설정되어 있으면 좌표 불일치가 생길 수 있습니다.
가능하면 동일한 스케일 비율을 유지하거나, PyAutoGUI의 size(), position()으로 실제 좌표를 확인해 보정하세요.
또한 PyAutoGUI의 FAILSAFE 기능이 활성화되어 있으면 화면 좌상단 모서리로 커서를 옮길 때 예외가 발생할 수 있으니 의도적으로 사용 여부를 검토하세요.
- 🧭대상 창의 제목 또는 고유 패턴을 정해 getWindowsWithTitle로 안정적으로 찾기.
- 📐상대 좌표는 창 기준 픽셀 단위로 기록하고, 변환은 left/top + rel 공식을 사용하기.
- 🖼️캡처·색상 검출도 창 내부 영역에 한정해 성능과 정확성을 동시에 확보하기.
- 🧪멀티 모니터, DPI 스케일링, 창 최대화/복원 상태에서 교차 테스트로 신뢰성 점검하기.
🧭 pygetwindow로 창 위치와 크기 얻기
창 기준 상대 좌표를 활용하려면, 먼저 대상 창의 위치와 크기를 정확히 알아야 합니다.
이때 유용한 모듈이 바로 pygetwindow입니다.
이 라이브러리는 현재 시스템에서 열려 있는 모든 창의 제목, 좌표, 크기 정보를 가져올 수 있으며, Windows·macOS·Linux 모두 지원합니다.
PyAutoGUI와 함께 사용하면 창의 위치를 기준점으로 삼아 자동화 동작의 정밀도를 크게 높일 수 있습니다.
기본적인 사용법은 단순합니다.
우선 pip install pygetwindow 명령으로 설치하고, getWindowsWithTitle() 함수를 이용해 특정 프로그램 창을 찾습니다.
이 함수는 창 제목 문자열을 포함하는 리스트를 반환하기 때문에, 보통 첫 번째 요소 [0]을 선택해 창 객체를 가져옵니다.
이 객체에는 left, top, width, height 속성이 포함되어 있어, 창의 위치와 크기를 한 번에 얻을 수 있습니다.
import pygetwindow as gw
# '메모장' 창 정보를 가져오는 예시
windows = gw.getWindowsWithTitle("메모장")
if windows:
win = windows[0]
print("창 제목:", win.title)
print("위치 (left, top):", win.left, win.top)
print("크기 (width, height):", win.width, win.height)
else:
print("해당 제목의 창을 찾을 수 없습니다.")
이 정보를 얻으면, 창의 절대 좌표계를 파악할 수 있습니다.
예를 들어, 메모장의 left=200이고 top=150이라면, 화면의 (0,0)에서 200px 오른쪽, 150px 아래에 창의 좌상단이 위치한다는 뜻입니다.
이 좌표를 기준점으로 삼으면, 상대 좌표만으로 창 내부의 모든 컨트롤을 찾아갈 수 있습니다.
💡 TIP: 창 제목이 매번 달라지는 프로그램(예: 문서 이름 포함)의 경우, in 키워드를 활용해 특정 패턴을 검색하는 것이 좋습니다.
예: [w for w in gw.getAllTitles() if “메모장” in w]
pygetwindow는 또한 창의 상태를 조정하는 기능도 제공합니다.
예를 들어 win.activate()로 창을 앞으로 가져오거나, win.restore()로 최소화된 창을 복원할 수 있습니다.
이는 PyAutoGUI의 입력 동작이 백그라운드 창에는 영향을 주지 않기 때문에 필수적인 전처리 과정입니다.
또한 win.moveTo(x, y)를 사용하면 창을 특정 위치로 강제로 이동시킬 수도 있습니다.
이렇게 하면 모든 테스트 환경에서 동일한 위치에 창을 고정해 일관된 상대 좌표 제어가 가능합니다.
💬 pygetwindow는 창의 좌표, 크기, 활성화 상태를 쉽게 제어할 수 있어 PyAutoGUI 자동화의 정확도를 높이는 핵심 도구입니다.
이처럼 창 정보를 정확히 얻는 과정은 이후의 상대 좌표 계산과 마우스 제어의 기초가 됩니다.
다음 단계에서는 이렇게 얻은 좌표 데이터를 이용해 실제로 상대 좌표를 절대 좌표로 변환하는 공식을 다루어 보겠습니다.
🖱️ 상대 좌표를 절대 좌표로 변환하는 공식
창의 위치 정보를 얻었다면 이제 실제 마우스 이동이나 클릭에 사용할 수 있도록 상대 좌표를 절대 좌표로 바꿔야 합니다.
PyAutoGUI는 항상 화면 전체 기준 좌표를 사용하기 때문에, pygetwindow로 얻은 창의 left와 top 값을 기준으로 변환해 주어야 합니다.
이 방식이 바로 “창 기준 상대 좌표”를 절대 좌표로 매핑하는 핵심 원리입니다.
📐 상대 → 절대 변환의 기본 공식
상대 좌표(rel_x, rel_y)를 절대 좌표로 바꾸는 공식은 다음과 같습니다.
이 식은 매우 단순하지만, 모든 PyAutoGUI 기반 자동화의 신뢰도를 결정짓는 핵심입니다.
# 창 기준 상대 좌표 → 화면 절대 좌표 변환
abs_x = win.left + rel_x
abs_y = win.top + rel_y
예를 들어, 창의 좌상단이 (left=300, top=200)에 있고, 창 내부에서 (rel_x=150, rel_y=80) 지점을 클릭하고 싶다면, 변환된 절대 좌표는 (450, 280)이 됩니다.
이 절대 좌표를 PyAutoGUI의 moveTo()나 click() 함수에 전달하면 정확히 해당 위치를 클릭하게 됩니다.
🧩 코드 예시로 살펴보기
import pygetwindow as gw
import pyautogui as pag
import time
# 대상 창 찾기
target = gw.getWindowsWithTitle("메모장")[0]
target.activate()
time.sleep(0.5)
# 상대 좌표 지정
rel_x, rel_y = 100, 50
# 변환
abs_x = target.left + rel_x
abs_y = target.top + rel_y
# 이동 후 클릭
pag.moveTo(abs_x, abs_y, duration=0.2)
pag.click()
이처럼 단 두 줄의 변환 코드만으로 어떤 해상도나 위치에서도 동일한 상대적 버튼을 클릭할 수 있습니다.
또한 창이 이동하더라도 pygetwindow가 새 좌표를 즉시 반영하기 때문에 매번 정확한 위치를 계산할 수 있습니다.
이는 특히 UI 테스트 자동화나 반복 입력 작업에서 매우 유용합니다.
💎 핵심 포인트:
상대 좌표를 사용할 때는 반드시 win.left와 win.top 값을 실시간으로 가져와야 합니다.
창이 이동하거나 최소화된 뒤 복원될 경우 좌표가 달라질 수 있기 때문입니다.
⚠️ 변환 시 주의할 점
1. 일부 운영체제에서는 창의 외곽선(Border) 두께를 포함한 좌표가 반환되므로, 클릭 지점이 약간 어긋날 수 있습니다.
이 경우에는 창 내부 컨텐츠의 시작점을 보정하기 위해 5~10px 정도의 오프셋을 추가하는 것이 안전합니다.
2. maximized 상태의 창은 해상도에 따라 좌표가 다르게 잡히므로, 자동화 전에 restore() 후 정해진 크기로 맞추는 것이 좋습니다.
이 원리만 확실히 이해하면, 이후에 마우스 이동·드래그·스크린샷 등 어떤 기능을 추가하더라도 모든 동작이 ‘창 기준’으로 안정적으로 작동합니다.
⚙️ PyAutoGUI로 클릭과 드래그 자동화 구현
이제 pygetwindow로 얻은 좌표를 활용해 PyAutoGUI를 통해 실제 동작을 구현해보겠습니다.
상대 좌표 변환만 잘 처리하면, 클릭·더블클릭·드래그·스크롤 같은 모든 GUI 자동화 동작을 안정적으로 재현할 수 있습니다.
PyAutoGUI는 사용법이 단순하면서도, 매개변수를 통해 속도·정확도·지연시간 등을 세밀하게 조정할 수 있는 강력한 도구입니다.
🖱️ 기본 클릭 및 이동
기본적인 클릭 구현은 다음과 같습니다.
창의 상대 좌표를 절대 좌표로 변환한 뒤, PyAutoGUI의 moveTo()와 click()을 차례로 호출하면 됩니다.
속도 제어를 위해 duration 인수를 함께 주면 부드럽게 이동하는 효과를 얻을 수 있습니다.
import pygetwindow as gw
import pyautogui as pag
import time
win = gw.getWindowsWithTitle("메모장")[0]
win.activate()
time.sleep(0.3)
# 상대 좌표 → 절대 좌표 변환
rel_x, rel_y = 120, 80
abs_x, abs_y = win.left + rel_x, win.top + rel_y
# 마우스 이동 및 클릭
pag.moveTo(abs_x, abs_y, duration=0.2)
pag.click() # 기본 왼쪽 클릭
오른쪽 클릭을 하려면 button=’right’을 추가하면 됩니다.
또한 click(clicks=2)로 더블클릭을 수행할 수도 있습니다.
PyAutoGUI는 키보드 입력(typewrite(), press())과 조합하면 복잡한 자동화 시나리오를 손쉽게 만들 수 있습니다.
🎯 드래그와 선택 구현
PyAutoGUI의 dragTo() 함수는 드래그 동작을 구현할 때 유용합니다.
상대 좌표 변환 후, 시작점과 끝점을 지정하면 실제 사용자가 마우스로 드래그하는 것처럼 작동합니다.
# 창 내부에서 드래그 동작 수행
start_x, start_y = win.left + 100, win.top + 120
end_x, end_y = win.left + 300, win.top + 120
pag.moveTo(start_x, start_y, duration=0.2)
pag.dragTo(end_x, end_y, duration=0.5, button='left')
텍스트 영역을 드래그해 선택하거나, 그래픽 프로그램에서 객체를 이동시키는 등 다양한 상황에 활용할 수 있습니다.
이때 드래그 속도가 너무 빠르면 UI 반응이 늦어질 수 있으므로, duration 값을 약간 늘려 자연스러운 동작을 유지하는 것이 좋습니다.
💎 핵심 포인트:
PyAutoGUI의 모든 좌표 입력은 ‘절대좌표 기준’이라는 점을 명심하세요.
상대 좌표를 사용할 때마다 pygetwindow에서 창 정보를 새로 가져와 변환해야 정확도가 유지됩니다.
⚠️ 주의: PyAutoGUI의 FAILSAFE 모드가 켜져 있으면, 마우스가 화면 좌상단으로 이동할 때 프로그램이 강제로 중단됩니다.
장시간 자동화 작업을 수행할 때는 예외 처리로 방어 코드를 두는 것이 안전합니다.
이제 클릭과 드래그 동작을 모두 구현했다면, 환경에 따라 발생할 수 있는 오차나 멀티 모니터 환경에서도 일관성을 유지하기 위한 안정성 점검이 필요합니다.
다음 단계에서는 이 점검 방법과 테스트 팁을 다뤄보겠습니다.
🧪 해상도·다중 모니터 대응과 안정성 체크리스트
PyAutoGUI 자동화를 실제 환경에서 운용할 때는, 단순히 코드가 잘 돌아가는 것만으로는 부족합니다.
해상도가 다르거나 노트북을 도킹한 상태, 혹은 듀얼 모니터처럼 창이 여러 화면 사이를 이동할 때 예상치 못한 좌표 오차가 발생할 수 있습니다.
이 문제를 최소화하려면 pygetwindow로 창 좌표를 얻는 시점을 조정하고, DPI 설정과 모니터 해상도를 점검해야 합니다.
🖥️ 해상도와 DPI 스케일링 문제 해결
Windows에서는 화면 배율(DPI)이 125%, 150% 등으로 설정되어 있을 경우 좌표 계산이 어긋나는 경우가 많습니다.
이럴 때는 PyAutoGUI.size()를 사용해 실제 픽셀 단위를 확인하거나, win32api의 GetSystemMetrics()를 이용해 스케일링된 해상도를 직접 가져오는 것이 좋습니다.
또한 Windows의 “디스플레이 → 배율 및 레이아웃”에서 100%로 맞춰 테스트하면 기본 좌표 체계로 동작합니다.
💡 TIP: PyAutoGUI의 position()으로 마우스 실제 좌표를 출력해, 예상 좌표와 비교 테스트를 수행하면 DPI 문제를 손쉽게 확인할 수 있습니다.
🧩 다중 모니터 환경 대응
듀얼 모니터 이상 환경에서는 각 모니터의 해상도와 좌표 범위가 서로 다르기 때문에, 창이 어떤 모니터에 있는지에 따라 좌표 계산이 달라집니다.
예를 들어, 메인 모니터가 1920×1080이고 보조 모니터가 왼쪽에 연결되어 있다면 보조 모니터의 좌표는 음수 영역(-1920,0)부터 시작할 수 있습니다.
따라서 pygetwindow가 반환하는 win.left 값이 음수일 수도 있다는 점을 고려해야 합니다.
# 다중 모니터 환경에서 창 위치 로그 확인
import pygetwindow as gw
for w in gw.getAllWindows():
print(w.title, w.left, w.top)
이 출력을 보면 각 창이 어느 모니터 좌표계에 위치했는지 바로 확인할 수 있습니다.
만약 자동화하려는 창이 음수 좌표에 걸쳐 있다면, 절대 좌표 계산 시 음수 값을 그대로 더해야 정확히 클릭됩니다.
즉, abs_x = win.left + rel_x에서 win.left가 음수여도 정상입니다.
- 🧭창의 좌표를 매번 pygetwindow로 새로 갱신하기
- 🧩윈도우 배율(DPI)이 자동으로 변경되는 환경에서는 100% 고정 테스트
- 🖥️모니터가 여러 개일 때는 음수 좌표 여부를 반드시 로그로 확인
- ⚙️창이 최소화되거나 다른 창 뒤로 가려지지 않도록 activate()로 전면 활성화
- 🧪자동화 스크립트 실행 전 pag.position()으로 좌표 검증 테스트 수행
이러한 점검 과정을 습관화하면, 어떤 해상도나 모니터 구성이 바뀌어도 PyAutoGUI 자동화 스크립트가 안정적으로 작동합니다.
즉, “창 기준 상대 좌표” 개념을 활용해 만든 코드는 환경 독립적인 자동화의 핵심이 됩니다.
❓ 자주 묻는 질문 (FAQ)
PyAutoGUI의 좌표는 왜 화면 전체 기준인가요?
따라서 창 기준으로 작업하려면 pygetwindow를 통해 창 위치를 보정해줘야 합니다.
pygetwindow로 창을 못 찾는 경우는 왜 생기나요?
제목 일부를 포함하는 문자열 검색(in 키워드)로 유연하게 처리하면 대부분 해결됩니다.
상대 좌표를 기록할 때 어떤 기준으로 잡아야 하나요?
이후 각 버튼이나 필드의 상대적 픽셀 거리만 저장하면 됩니다.
창을 최소화하면 좌표 계산이 달라지나요?
따라서 자동화 전에 반드시 win.restore()로 복원 후 작업해야 합니다.
좌표가 간헐적으로 틀어질 때는 어떻게 해야 하나요?
pygetwindow로 얻은 좌표에 소량의 보정값(예: +5, +8)을 더해 정확도를 높일 수 있습니다.
Mac이나 Linux에서도 동일하게 작동하나요?
Linux에서는 X11 환경에서 정상 동작하며 Wayland에서는 일부 기능이 제한될 수 있습니다.
pygetwindow 없이 PyAutoGUI만으로도 가능한가요?
따라서 상대 좌표를 구현하려면 반드시 pygetwindow나 win32gui 같은 보조 모듈이 필요합니다.
스크립트 실행 시 마우스가 갑자기 움직이는 게 불편합니다.
pag.PAUSE를 설정해 각 동작 사이에 휴식 시간을 줄 수 있습니다.
🧭 PyAutoGUI 창 기준 자동화를 위한 정리
PyAutoGUI와 pygetwindow를 함께 사용하면, 해상도나 모니터 구성이 달라져도 흔들리지 않는 견고한 자동화를 구현할 수 있습니다.
핵심은 단순합니다.
창의 좌상단 좌표(left, top)를 기준으로 모든 좌표를 상대값으로 계산하고, 실행 시점마다 이를 절대 좌표로 변환해주는 것입니다.
이 원리만 지키면 창의 위치, 크기, 배율 설정이 달라져도 정확히 동일한 지점을 클릭하거나 드래그할 수 있습니다.
또한 pygetwindow의 activate(), restore() 함수로 창을 전면으로 가져온 뒤 작업하면 실패율을 크게 줄일 수 있습니다.
PyAutoGUI는 GUI 자동화에 필요한 거의 모든 기능을 제공하지만, 창의 위치를 직접 알 수 없기 때문에 pygetwindow의 보조가 필수적입니다.
이 두 라이브러리를 조합하면 실제 사용자처럼 움직이되, 환경 독립적인 자동화를 구현할 수 있습니다.
💎 핵심 정리:
1️⃣ pygetwindow로 창의 좌표와 크기를 파악한다.
2️⃣ 창의 좌상단을 원점으로 삼아 상대 좌표를 계산한다.
3️⃣ 실행 시 abs_x = left + rel_x, abs_y = top + rel_y로 변환한다.
4️⃣ PyAutoGUI의 moveTo(), click(), dragTo()로 동작을 실행한다.
이 네 단계로 환경에 구애받지 않는 정확한 창 자동화를 만들 수 있습니다.
🏷️ 관련 태그 : PyAutoGUI, pygetwindow, 파이썬자동화, 상대좌표, 절대좌표, GUI스크립트, 창기준좌표, 마우스자동화, 프로그래밍팁, Python스크립트