엑셀 VBA 디버깅 (오류 처리) 모든 방법 - 핵심 정리
오류는 발생 시점으로 종류가 갈리고, F8 로 한 줄씩 짚어가며 지역창과 조사식창으로 변수를 확인하면 원인은 대부분 몇 분 안에 좁혀집니다.
매크로를 짜다 보면 오류 메시지는 반드시 만나게 됩니다. 중요한 것은 오류를 피하는 게 아니라 어디서 무엇 때문에 멈췄는지 빠르게 짚어내는 것이고, 그 과정을 디버깅이라고 부릅니다.
VBA 오류는 세 종류입니다
오류마다 발생하는 시점이 다릅니다. 언제 걸렸는지만 봐도 원인의 절반은 좁혀집니다.
| 오류 종류 | 언제 발생하나 |
|---|---|
| Syntax Error (구문 오류) |
코드를 입력하는 중. 한 줄에 빠진 요소가 있으면 그 줄에서 바로 알려 줍니다. |
| Compilation Error (컴파일 오류) |
코드를 실행하거나 컴파일할 때. If·For 처럼 짝이 맞아야 하는 구문이 어긋난 경우입니다. |
| Run-time Error (실행 중 오류) |
코드가 돌아가는 도중. 파일이 없거나 값의 형식이 다른 것처럼, 문법이 아니라 상황이 원인입니다. |
Syntax Error — 쓰는 도중에 잡힙니다
한 줄을 다 쓰고 넘어가는 순간 문법을 검사합니다. 예를 들어 If 문에 Then 을 빼고 다음 줄로 넘어가면 '필요한 요소: Then 또는 Goto' 라는 메시지가 즉시 뜹니다.
Sub SyntaxErrorTest() If ThisWorkbook.Name = "통합문서1" ' Then 이 없어 이 줄에서 바로 오류가 납니다 End Sub

안내창이 번번이 뜨는 게 성가시다면 편집기의 [도구] - [옵션] - [편집기] - '자동 구문 검사' 를 꺼 둘 수 있습니다. 메시지창은 사라지지만 잘못된 줄은 여전히 빨간색으로 표시됩니다.
매크로 편집기를 처음 여는 방법은 개발 도구 활성화 방법에서 확인하세요.
Compilation Error — 실행할 때 잡힙니다
구문 오류가 '한 줄'의 문제라면, 컴파일 오류는 '짝'의 문제입니다. 아래처럼 End If 가 없어도 작성 중에는 아무 말이 없다가, 실행하는 순간 "End If가 없는 If 블록 문" 이라며 멈춥니다.
Sub CompilationErrorTest()
If ThisWorkbook.Name = "통합문서1" Then
MsgBox "현재 파일의 이름은 통합문서1 입니다." ' End If 가 없습니다
End Sub

자주 만나는 컴파일 오류는 대개 다음과 같습니다.
- If 문에 End If 를 빠뜨린 경우
- For 문에 Next 가 없는 경우
- Do While 문에 Loop 가 없는 경우
- Select 문에 End Select 가 없는 경우
- 같은 프로젝트 안에 이름이 같은 프로시저를 두 번 만든 경우
- Option Explicit 을 선언해 두고 변수를 Dim 으로 선언하지 않은 경우
Run-time Error — 돌아가는 도중에 멈춥니다
가장 자주 만나고, 종류도 가장 많은 오류입니다. 코드 문법은 멀쩡한데 바깥 사정이 예상과 달라서 생깁니다. 아래 코드는 문법상 아무 문제가 없지만, 해당 경로에 파일이 없으면 '1004' 오류로 멈춥니다.
Sub OpenFile() Dim Path As String Path = "C:\Test\Test.xlsx" Application.Workbooks.Open Path End Sub

이런 오류는 미리 조건을 확인해 막습니다. Dir 함수로 파일이 있는지 먼저 확인한 뒤, 없으면 안내 메시지를 띄우고 코드를 끝내면 됩니다.
Sub OpenFile() Dim Path As String Path = "C:\Test\Test.xlsx" If Dir(Path) = "" Then MsgBox Path & " 경로에 파일이 존재하지 않습니다.": Exit Sub Application.Workbooks.Open Path End Sub

실행 전에 미리 걸러내기
매크로 편집기에서 [디버그] - [VBAProject 컴파일] 을 클릭하면 코드를 실행하지 않고도 구문 오류와 컴파일 오류를 먼저 찾아 줍니다.

익숙해지면 잘 쓰지 않게 되는 기능이지만, 시작 단계에서는 코드를 어느 정도 쓸 때마다 한 번씩 눌러 보는 습관이 도움이 됩니다.
오류에서 멈추는 기준 바꾸기
편집기는 어떤 오류에서 코드를 멈출지 고를 수 있습니다. [도구] - [옵션] - [일반] 탭의 '오류 잡기' 항목입니다.

- 오류 발생 시 무조건 중단 — 편집기가 오류로 판단하는 모든 지점에서 멈춥니다. On Error 로 처리해 둔 곳에서도 멈추기 때문에 잘 쓰지 않습니다.
- 클래스 모듈에서 중단 — 처리되지 않은 오류에 더해, 클래스 모듈과 유저폼 안에서 난 오류에서도 멈춥니다. 유저폼을 쓰는 프로젝트라면 이 설정이 원인 지점을 훨씬 정확히 보여 줍니다.
- 처리되지 않은 오류 발생 시 중단 — 기본값입니다. 아직 처리하지 않은 오류에서만 멈추고, 그 지점을 노란색으로 표시합니다.

다만 이 설정은 어느 정도 익숙해진 뒤에 손대는 것이 좋습니다. 입문 단계에서는 기본값인 '처리되지 않은 오류 발생 시 중단'을 그대로 두세요.
On Error 로 오류 처리하기
오류는 크게 둘로 나뉩니다. 예상할 수 있는 오류는 If 문으로 미리 막고, 예상하기 어려운 오류는 On Error 구문으로 처리합니다. 특히 남에게 배포하는 파일이라면 내 컴퓨터에서 나지 않던 오류가 반드시 나옵니다.
| On Error 구문 | 동작 |
|---|---|
| On Error Goto 0 | 오류가 나면 그 지점에서 멈추고 오류 메시지를 띄웁니다. (기본 동작) |
| On Error Resume Next | 오류를 무시하고 다음 줄로 넘어갑니다. |
| On Error Goto 레이블 | 오류가 나면 지정한 레이블로 이동합니다. 오류 메시지는 뜨지 않습니다. |
| On Error Goto -1 | 지금까지 발생한 오류 상태를 초기화합니다. |
디버깅 따라 해 보기
일부러 오류가 나는 코드로 순서를 익혀 봅니다.
- 아래 코드를 복사해 새 모듈에 붙여넣습니다. 활성 시트의 값을 모두 지우고 A1:A10 에 값을 넣은 뒤 글자색을 빨간색으로 바꾸는 코드입니다.
Sub RowNumbers() Dim i As Long ActiveSheet.UsedRange.Delete For i = 1 To 10 Range("A" & i).Value = i Next For i = 1 To 10 Range("A" & i).Value = "A" + i ' "A"는 문자, i는 숫자인데 덧셈으로 묶여 오류가 납니다 Next ActiveSheet.UsedRange.Font.Color = vbRed End Sub - 편집기 위쪽의 재생 버튼(▶)을 누르거나 F5 로 실행합니다. 도중에 '런타임 오류 13: 형식이 일치하지 않습니다' 라는 메시지가 뜹니다.

실행하면 '형식이 일치하지 않습니다' 오류가 납니다. - 메시지창의 [디버그] 를 누르면 문제가 된 줄이 노란색으로 표시됩니다.

[디버그]를 누르면 오류가 난 지점이 노란색으로 강조됩니다. - 강조된 줄을 보면 문자 "A" 와 숫자 i 를 덧셈(+)으로 묶은 것이 원인입니다. + 를 & 로 바꿉니다.

+ 기호를 & 기호로 바꿉니다. - 다시 F5 로 실행하면 A1:A10 에 값이 빨간 글씨로 채워집니다.

수정 후 다시 실행하면 정상 동작합니다.
디버깅 단축키
| 단축키 | 동작 |
|---|---|
| F5 | 커서가 놓인 프로시저를 실행 |
| F8 | 한 줄씩 단계별로 실행 |
| Ctrl + F8 | 커서가 있는 줄까지 한 번에 실행 |
| Ctrl + Shift + F8 | 지금 들어와 있는 프로시저를 끝내고 호출한 쪽으로 복귀 |
| F9 | 중단점 설정/해제 |
| Ctrl + Shift + F9 | 설정된 모든 중단점 해제 |
| Ctrl + G | 직접 실행창 열기 |
F5 · F8 — 통째로 실행할지, 한 줄씩 볼지
F5 는 프로시저 전체를 한 번에 돌립니다. 중간에 중단점이 있으면 그 지점에서 멈춥니다. F8 은 누를 때마다 한 줄씩 실행되고, 지금 실행할 줄이 노란색으로 강조됩니다. 변수 선언(Dim) 줄은 멈추지 않고 그냥 지나갑니다.

Ctrl + F8 · Ctrl + Shift + F8 — 건너뛰기
앞부분은 이미 확인이 끝났다면 굳이 F8 을 반복해서 누를 필요가 없습니다. 보고 싶은 줄에 커서를 두고 Ctrl + F8 을 누르면 거기까지 한 번에 실행됩니다. 반대로 다른 프로시저 안까지 따라 들어갔다가 나머지를 건너뛰고 싶을 때는 Ctrl + Shift + F8 로 그 프로시저를 끝내고 호출한 자리로 돌아옵니다.
F9 — 중단점
멈추고 싶은 줄에 커서를 두고 F9 를 누르면 그 줄이 짙은 빨간색으로 표시되고, 실행이 그 지점에서 멈춥니다. 편집기 왼쪽 회색 여백을 클릭해도 같은 결과이고, 한 번 더 누르면 해제됩니다. 중단점이 여기저기 흩어져 있으면 Ctrl + Shift + F9 로 한 번에 지웁니다.

노란 화살표를 끌어 단계 되돌리기
F8 로 한 줄씩 실행하다 보면 왼쪽 여백에 노란 화살표가 따라옵니다. 이 화살표를 위아래로 끌면 다음에 실행할 줄을 바꿀 수 있습니다. 방금 지나온 줄로 화살표를 올리면 그 줄부터 다시 실행됩니다.
VBA 는 실행 도중에 변수 값을 바꾸거나 코드를 고치는 것도 허용합니다. 그래서 원하는 결과가 안 나오면 멈춘 채로 코드를 고치고 → 화살표를 위로 끌어 올리고 → 다시 F8 하는 식으로, 매크로를 처음부터 다시 돌리지 않고도 몇 번이든 시험해 볼 수 있습니다.
변수 값을 확인하는 5가지 방법
단계별로 실행하다 보면 "지금 이 변수에 뭐가 들어 있지?" 가 궁금해집니다. 가장 간단한 방법은 변수 위에 마우스 커서를 올리는 것으로, 잠시 기다리면 값이 말풍선으로 표시됩니다.

확인할 변수가 많거나 반복문 안에서 값이 계속 바뀐다면 아래 방법이 훨씬 빠릅니다.
1. 직접 실행창
[보기] - [직접 실행창] 또는 Ctrl + G 로 엽니다. ? 를 찍고 뒤에 변수나 식을 적으면 값이 바로 출력됩니다.
?ThisWorkbook.Name

단, 직접 실행창에 한 번에 표시되는 것은 숫자·문자 같은 단순한 값입니다. 배열이나 범위는 통째로 볼 수 없으므로 ?MyArray(0, 0) 처럼 자리를 지정해 하나씩 확인합니다.
2. Debug.Print
코드 안에 Debug.Print 를 끼워 넣으면 실행되는 동안 값이 직접 실행창에 차곡차곡 쌓입니다. 반복문에서 값이 어떻게 변해 가는지 볼 때 가장 편합니다.
Sub DebugPrintTest() Dim i As Long For i = 1 To 10 Debug.Print i Next End Sub

3. 지역창
[보기] - [지역창] 을 열어 두면 지금 실행 중인 프로시저에서 쓰는 모든 변수와 값이 한 번에 나열됩니다. 개체 변수는 앞의 + 를 눌러 속성까지 펼쳐 볼 수 있어, 직접 실행창으로 하나씩 찍어 보는 것보다 빠릅니다.

4. 조사식창
지역창이 '지금 이 프로시저'만 보여 준다면, 조사식창은 내가 지정한 변수를 계속 따라다니며 보여 줍니다. 확인할 변수를 조사식창으로 끌어다 놓거나, 변수를 오른쪽 클릭해 [조사식 추가]를 고르면 등록됩니다.
조사식의 진짜 쓸모는 조건을 만족할 때 멈추게 하는 것입니다. 1부터 100까지 도는 반복문에서 값이 99일 때를 보고 싶다고 F8 을 99번 누를 수는 없으니까요.
- 아래 코드를 새 모듈에 붙여넣습니다.
Sub WatchTest() Dim i As Long For i = 1 To 100 i = i + 1 Next End Sub
- [디버그] - [조사식 추가] 를 선택하고 식에
i = 99를 적은 뒤, 조사식 형식에서 '값이 True 일 때 중단' 을 고르고 [확인]을 누릅니다.

조사식 형식을 '값이 True 일 때 중단'으로 지정합니다. - 조사식창에 식이 등록된 것을 확인합니다.

조사식창에 식이 등록되었습니다. - 코드를 실행하면 i 가 99 가 되는 순간 저절로 멈춥니다.

조건을 만족하는 순간 실행이 중단됩니다.
5. MsgBox
창을 열어 두기 어려운 상황이라면 MsgBox 로 값을 확인할 수도 있습니다. 다만 반복문 안에서는 쓰지 않는 편이 좋습니다. 아래 코드는 메시지창이 열 번 뜨고, 매번 [확인]을 눌러야 다음으로 넘어갑니다.
Sub MsgboxTest() Dim i As Long Dim s As String For i = 1 To 10 s = s & i MsgBox s ' 반복문 안의 MsgBox 는 창이 반복해서 뜹니다 s = s & "," Next End Sub

Debug.Assert — 조건을 벗어나면 멈추기
코드가 복잡해질수록 "여기서는 값이 이 범위 안이어야 하는데" 하는 지점이 생깁니다. Debug.Assert 뒤에 조건을 적어 두면, 그 조건이 거짓이 되는 순간 실행이 멈춥니다. 아래 코드는 i 가 24 를 넘어서는 순간 멈춥니다.
Sub DebugAssertTest()
Dim i As Long
ActiveSheet.UsedRange.Delete
For i = 1 To 30
Debug.Assert i >= 1 And i <= 24
Range("A" & i).Value = i
Next
End Sub

Option Explicit — 오타를 미리 막기
모듈 맨 위에 Option Explicit 을 적어 두면, 그 모듈의 모든 변수를 Dim 으로 선언해야만 실행됩니다. 번거로워 보이지만 변수 이름을 잘못 친 실수를 실행 전에 잡아 준다는 점에서 이득이 훨씬 큽니다.
선언 없이 아래 코드를 실행하면 오류 없이 빈 메시지창이 뜹니다. s 와 i 가 무엇인지 알 수 없어 빈 값으로 처리되기 때문입니다.
Sub OptionExplicitTest() MsgBox s & i ' s 와 i 가 무엇인지 지정하지 않았습니다 End Sub
같은 코드를 Option Explicit 아래에서 실행하면, 이번에는 '변수가 정의되지 않았습니다' 라며 멈춥니다. 오류처럼 보이지만 사실은 도움을 받은 것입니다.
Option Explicit Sub OptionExplicitTest() MsgBox s & i End Sub

변수를 제대로 선언하면 문자와 숫자가 각각 인식되어, 빈 문자와 0 이 합쳐진 0 이 표시됩니다.
Option Explicit Sub OptionExplicitTest() Dim s As String Dim i As Long MsgBox s & i End Sub

참고 문서
- VBA 오류 메시지 목록 — Microsoft Learn
엑셀 VBA &H80004005 (-2147467259) 자동화 오류 해결 방법
2022년 7월 M365 2206 업데이트가 원인이던 오류입니다. 이후 핫픽스로 해결되었으므로 지금은 최신 버전으로 업데이트하는 것이 먼저입니다.
엑셀 매크로를 실행할 수 없습니다 - 상황별 해결법
최신 버전은 파일 속성에서 '차단 해제'를 체크한 뒤 [콘텐츠 사용]을 눌러야 매크로가 실행됩니다. 자주 쓰는 파일은 신뢰할 수 있는 위치에 두면 됩니다.
엑셀 VBA 색상표 및 색상 코드 총정리
ColorIndex 번호를 한글 이름으로 바꾸는 Enum 을 모듈 최상단에 붙여 넣으면, 색을 숫자 대신 '빨강색' 같은 이름으로 지정할 수 있습니다.
감사합니다.