🔬 과학·테크/🔥 AutoHotkey v2 입문 가이드

AutoHotkey v2 입문 가이드 #15: 디버깅과 팁 - 문제 해결의 기술

_eNKI 2025. 12. 18. 19:53
반응형

🎯 이 글에서 배우는 것: 디버깅 기법, 에러 처리, 성능 최적화, 고급 팁


🐛 디버깅이란?

디버깅(Debugging)은 코드의 버그(오류)를 찾아 고치는 과정입니다. 스크립트가 예상대로 동작하지 않을 때 필수적인 기술이죠!


🔍 기본 디버깅 기법

1. MsgBox 디버깅 (가장 간단!)

#Requires AutoHotkey v2.0

ProcessData(data) {
    MsgBox("1. 함수 시작, data = " data)  ; 체크포인트 1

    result := data * 2
    MsgBox("2. 계산 완료, result = " result)  ; 체크포인트 2

    if (result > 100) {
        MsgBox("3. 조건문 진입")  ; 체크포인트 3
        result := 100
    }

    MsgBox("4. 함수 종료, 반환값 = " result)  ; 체크포인트 4
    return result
}

2. ToolTip 디버깅 (비침습적)

MsgBox는 실행을 멈추지만, ToolTip은 계속 진행하면서 정보 표시:

^j::{
    Loop 10 {
        ToolTip("현재 반복: " A_Index "`n값: " A_Index * 2)
        Sleep(500)
    }
    ToolTip()  ; 툴팁 제거
}

3. 파일 로깅

실행 기록을 파일로 저장:

#Requires AutoHotkey v2.0

LogFile := A_ScriptDir "\debug.log"

Log(message) {
    timestamp := FormatTime(, "yyyy-MM-dd HH:mm:ss")
    FileAppend(timestamp " - " message "`n", LogFile)
}

; 사용 예시
^j::{
    Log("핫키 ^j 실행됨")

    try {
        result := SomeFunction()
        Log("결과: " result)
    } catch as e {
        Log("에러 발생: " e.Message)
    }
}

4. OutputDebug + DebugView

Windows Sysinternals의 DebugView와 함께 사용:

OutputDebug("변수 x의 값: " x)
OutputDebug("함수 진입: ProcessData()")

⚠️ 에러 처리 (Try-Catch)

기본 구조

try {
    ; 에러가 발생할 수 있는 코드
    result := FileRead("없는파일.txt")
} catch as e {
    ; 에러 처리
    MsgBox("에러 발생!`n" e.Message)
}

에러 객체 속성

try {
    result := 10 / 0  ; 0으로 나누기
} catch as e {
    MsgBox(
        "에러 타입: " Type(e) "`n"
        "메시지: " e.Message "`n"
        "발생 위치: " e.File " (Line " e.Line ")`n"
        "추가 정보: " e.Extra
    )
}

Finally 블록

에러 발생 여부와 관계없이 항상 실행:

file := FileOpen("test.txt", "w")
try {
    file.WriteLine("테스트")
    ; ... 작업 수행
} catch as e {
    MsgBox("에러: " e.Message)
} finally {
    file.Close()  ; 항상 파일 닫기
}

사용자 정의 에러 던지기

ValidateAge(age) {
    if (age < 0)
        throw ValueError("나이는 음수일 수 없습니다", -1, age)
    if (age > 150)
        throw ValueError("나이가 너무 큽니다", -1, age)
    return true
}

try {
    ValidateAge(-5)
} catch as e {
    MsgBox(e.Message)
}

🚀 성능 최적화

1. SetBatchLines 대신 Critical

v2에서는 SetBatchLines가 제거됨. 대신 Critical 사용:

^j::{
    Critical  ; 인터럽트 방지, 성능 향상

    Loop 10000 {
        ; 빠른 처리가 필요한 작업
    }

    Critical("Off")  ; 다시 일반 모드
}

2. 변수 캐싱

반복적인 함수 호출 피하기:

; 나쁜 예 - 매번 함수 호출
Loop 1000 {
    if (StrLen(myString) > 10)  ; 매번 길이 계산
        ; ...
}

; 좋은 예 - 한 번만 계산
len := StrLen(myString)
Loop 1000 {
    if (len > 10)
        ; ...
}

3. 문자열 연결 최적화

; 나쁜 예 - 매번 새 문자열 생성
result := ""
Loop 1000 {
    result := result . A_Index . "`n"  ; 느림
}

; 좋은 예 - 배열 사용 후 한 번에 결합
parts := []
Loop 1000 {
    parts.Push(A_Index)
}
result := ""
for item in parts
    result .= item "`n"

4. Sleep 적절히 사용

; CPU 과부하 방지
Loop {
    ; 작업 수행
    Sleep(10)  ; 적절한 대기
}

5. 핫키 범위 제한 (#HotIf)

; 전역 핫키 - 항상 메모리 사용
^j::MsgBox("어디서든")

; 조건부 핫키 - 필요할 때만 활성화
#HotIf WinActive("ahk_exe notepad.exe")
^j::MsgBox("메모장에서만")
#HotIf

🔧 자주 발생하는 문제와 해결

문제 1: 핫키가 작동하지 않음

원인과 해결:

; 1. 스크립트가 실행 중인지 확인
; → 트레이 아이콘 확인

; 2. 관리자 권한 필요할 수 있음
; → 우클릭 → 관리자 권한으로 실행

; 3. 다른 프로그램이 핫키 사용 중
; → 다른 키 조합 시도

; 4. 핫키 문법 확인
^j::MsgBox("OK")   ; 올바름
Ctrl+j::MsgBox()   ; 잘못됨!

문제 2: Send가 제대로 입력 안 됨

; 1. 대상 프로그램이 특수한 경우
Send("Hello")      ; 일반
SendInput("Hello") ; 더 빠름, 보통 권장
SendEvent("Hello") ; 호환성 좋음
SendPlay("Hello")  ; 게임용 (관리자 권한 필요)

; 2. 타이밍 문제
Send("^c")
Sleep(100)         ; 클립보드 복사 대기
Send("^v")

; 3. 특수문자 문제
Send("{Enter}")    ; 올바름
Send("Enter")      ; "Enter" 문자가 입력됨!

; 4. 텍스트 그대로 입력
SendText("^!#")    ; 특수 키로 해석 안 함

문제 3: 창을 찾지 못함

; Window Spy로 정확한 제목/클래스 확인!

; 부분 일치
SetTitleMatchMode(2)  ; 제목에 포함되면 OK
WinActivate("메모장")

; 정규식 사용
SetTitleMatchMode("RegEx")
WinActivate(".*메모장.*")

; 클래스로 찾기 (더 정확)
WinActivate("ahk_class Notepad")

; 실행 파일로 찾기
WinActivate("ahk_exe notepad.exe")

문제 4: 한글 입력 문제

; SendText로 해결
SendText("안녕하세요")  ; Send 대신 SendText

; 또는 클립보드 이용
A_Clipboard := "안녕하세요"
Send("^v")

문제 5: 무한 루프

; 탈출 키 항상 준비!
Esc::ExitApp

; 또는 안전장치
count := 0
Loop {
    count++
    if (count > 1000) {
        MsgBox("무한 루프 방지!")
        break
    }
    ; 작업
}

💡 고급 팁과 트릭

1. 조건부 컴파일

#Requires AutoHotkey v2.0

DEBUG := true  ; false로 바꾸면 디버그 출력 비활성화

DebugLog(msg) {
    if DEBUG
        ToolTip(msg)
}

^j::{
    DebugLog("핫키 실행됨")
    ; 실제 작업
}

2. 설정 파일 사용 (INI)

settingsFile := A_ScriptDir "\settings.ini"

; 설정 저장
IniWrite("value1", settingsFile, "Section", "Key1")
IniWrite("value2", settingsFile, "Section", "Key2")

; 설정 읽기
val1 := IniRead(settingsFile, "Section", "Key1", "default")
val2 := IniRead(settingsFile, "Section", "Key2", "default")

3. 스크립트 자동 시작

; 시작프로그램에 바로가기 생성
startupFolder := A_Startup
shortcutPath := startupFolder "\MyScript.lnk"

if !FileExist(shortcutPath) {
    FileCreateShortcut(A_ScriptFullPath, shortcutPath)
    MsgBox("시작프로그램에 등록됨!")
}

4. 트레이 메뉴 커스터마이징

; 기본 메뉴 제거하고 커스텀 메뉴 생성
A_TrayMenu.Delete()

A_TrayMenu.Add("설정", ShowSettings)
A_TrayMenu.Add("도움말", ShowHelp)
A_TrayMenu.Add()  ; 구분선
A_TrayMenu.Add("새로고침", (*) => Reload())
A_TrayMenu.Add("종료", (*) => ExitApp())

ShowSettings(*) {
    MsgBox("설정 화면")
}

ShowHelp(*) {
    Run("https://www.autohotkey.com/docs/v2/")
}

5. 핫키 동적 생성/해제

; 핫키 동적 생성
Hotkey("^j", MyFunc)

MyFunc(*) {
    MsgBox("동적 핫키!")
}

; 핫키 비활성화
Hotkey("^j", "Off")

; 핫키 다시 활성화
Hotkey("^j", "On")

; 핫키 재할당
Hotkey("^j", AnotherFunc)

6. 타이머 활용

; 5초마다 실행
SetTimer(MyTimer, 5000)

MyTimer() {
    ToolTip("5초 경과!")
    SetTimer(() => ToolTip(), -1000)  ; 1초 후 툴팁 제거
}

; 타이머 중지
; SetTimer(MyTimer, 0)

📝 체크리스트: 스크립트 배포 전 확인사항

□ #Requires AutoHotkey v2.0 선언됨
□ #SingleInstance Force 추가됨
□ 모든 경로가 절대경로 또는 A_ScriptDir 기준
□ 에러 처리 (try-catch) 추가됨
□ 디버그용 MsgBox 제거됨
□ 탈출 키 (Esc::ExitApp 등) 설정됨
□ 주석으로 코드 설명 추가됨
□ 다른 PC에서 테스트됨

🛠️ 유용한 도구들

도구 용도
Window Spy 창 제목, 클래스, 좌표 확인 (AHK 설치 시 포함)
VS Code + AHK v2 확장 코드 편집, 문법 강조, 자동완성
SciTE4AutoHotkey AHK 전용 에디터
DebugView OutputDebug 메시지 확인
AHK v2 공식 문서 함수 레퍼런스

🎓 더 배우려면

공식 리소스

추천 학습 순서

  1. 공식 튜토리얼 완독
  2. 포럼의 Scripts and Functions 섹션 탐색
  3. 다른 사람 스크립트 분석
  4. 자신만의 프로젝트 시작

🏁 시리즈를 마치며

15회에 걸쳐 AutoHotkey v2의 기초부터 실전까지 함께했습니다!

우리가 배운 것들

회차 주제
1-2 설치, 첫 스크립트
3-4 핫키, 핫스트링
5-6 Send/Click, Run/창 관리
7-8 변수/데이터타입, 제어문
9-10 함수, 키 리매핑
11-12 GUI, 파일 다루기
13-14 문자열 처리, 실전 예제
15 디버깅과 팁

앞으로의 여정

이제 기초는 끝났습니다. 진짜 실력은 직접 만들어보면서 늡니다!

  1. 불편한 것을 발견하면 → "이거 자동화할 수 있을까?" 생각하기
  2. 작은 스크립트부터 시작
  3. 조금씩 기능 추가
  4. 다른 사람 코드 참고
  5. 포럼에서 질문하고 답변하기

💬 마지막 팁

"완벽한 스크립트는 없습니다. 작동하는 스크립트가 최고입니다!"

처음엔 지저분해도 괜찮습니다. 일단 돌아가게 만들고, 나중에 다듬으세요.

AutoHotkey와 함께 더 효율적인 컴퓨터 생활을 즐기시길 바랍니다! 🎉


📚 전체 시리즈 목록

  1. AutoHotkey v2 소개 및 설치
  2. 첫 스크립트 작성하기
  3. 핫키(Hotkey) 기초
  4. 핫스트링(Hotstring)
  5. 키보드/마우스 입력 보내기
  6. 프로그램 실행과 창 관리
  7. 변수와 데이터 타입
  8. 제어문
  9. 함수 기초
  10. 키 리매핑
  11. GUI 기초
  12. 파일 다루기
  13. 문자열 처리
  14. 실전 예제 모음
  15. 디버깅과 팁 ← 현재 글

이전 글: [#14 실전 예제 모음]

시리즈 완결! 🎊

반응형