Devin.KR

AI 개발 · 기본

바이브 코딩 시대의 기본서 - 처음 AI 와 함께 만드는 프로그램

빨간 글씨 읽는 법 - 오류 메시지와 친해지기

traceback 을 아래에서 위로 읽기, 흔한 오류 다섯 가지(SyntaxError·NameError·TypeError·IndexError·FileNotFoundError), 오류 메시지를 AI 에게 그대로 붙여 넣을 때 함께 줄 정보, 완성 코드는 다섯 오류를 일부러 일으키고 잡아서 종류·원인·고치는 방향을 표로 출력

개발자KR · 원고 갱신

이 장에서 배우는 것

앞 장에서 코드를 한 줄씩 따라 읽었다면, 이제 실행이 멈춘 자리에서 무엇을 읽어야 하는지 살펴본다. 코드를 실행했는데 예상한 결과 대신 빨간 글씨가 길게 나오면, 어디부터 봐야 할지 막막할 수 있다. 그러나 그 안에는 어떤 문제가 생겼는지, 어느 파일의 몇 번째 줄을 살펴봐야 하는지 알려 주는 단서가 들어 있다.

오류 메시지는 프로그램이 실패했다는 판정문으로만 볼 것이 아니다. 다음에 무엇을 확인할지 알려 주는 관찰 기록이다. 색은 실행 도구의 표시 방식일 뿐이다. 같은 오류가 검은 글씨로 나와도 읽는 순서는 같다. 이 장에서는 오류를 의도적으로 일으킨 뒤 종류와 원인, 고치는 방향을 표로 정리하는 작은 프로그램을 만든다.

  • 오류 추적 기록을 아래에서 위로 읽고 오류 종류와 발생 위치를 찾는다.
  • 자주 만나는 다섯 가지 오류를 구별하고 확인할 대상을 정한다.
  • AI에게 오류 메시지와 함께 전달할 실행 정보를 고른다.
  • 오류를 잡는 코드와 원인을 고치는 코드의 차이를 설명한다.
  • AI가 수정한 코드를 다시 실행하고 변경된 부분을 확인한다.

문제 상황

AI에게 “준비물 목록에서 첫 번째 항목을 출력하는 프로그램을 만들어 줘”라고 요청했다고 하자. 받은 코드를 파일로 저장하고 실행했는데 목록 대신 긴 글이 나온다. 마지막 줄에는 IndexError: list index out of range가 적혀 있다. 파일이 망가진 것인지, Python을 다시 설치해야 하는지부터 고민할 수 있다.

이 상황에서 먼저 볼 대상은 설치 상태가 아니라 메시지에 표시된 코드다. 준비물 목록이 비어 있는데 첫 항목을 꺼내려 했을 수도 있다. AI가 예제에서는 항목을 넣어 두었지만, 실제 코드에서는 빈 목록으로 시작하게 만들었을 수도 있다. 오류 이름만으로 둘 중 어느 경우인지 확정할 수는 없다. 메시지와 실제 값을 함께 살펴봐야 한다.

여기서 “오류가 나니 알아서 고쳐 줘”라고만 말하면 AI는 부족한 정보를 추측해야 한다. 목록에 임의의 준비물을 넣어 오류를 없앨 수도 있고, 아무것도 출력하지 않게 바꿀 수도 있다. 둘 다 실행은 끝나지만 원래 바라던 동작과 다를 수 있다. 먼저 오류가 알려 주는 사실을 읽고, 확인한 내용을 전달하는 습관이 필요하다.

이번 프로그램은 이런 연습을 위해 다섯 오류를 일부러 만든다. 오류를 하나씩 확인한 뒤에도 다음 사례를 살펴볼 수 있도록, 예상한 오류만 잡아서 표의 한 행으로 바꾼다. 실습을 마치면 오류 이름을 외우는 데서 그치지 않고, 그 이름을 보고 어디를 확인해야 하는지 말할 수 있게 된다.

오류 기록은 마지막 줄부터 읽는다

실행 도중 문제가 생겼을 때 Python이 보여 주는 호출 경로와 오류 정보를 오류 추적 기록(traceback)이라고 한다. 여기서 호출은 어떤 작업을 실행하도록 부르는 일이다. 함수에서 다른 함수를 부르다가 문제가 생겼다면, 기록에는 그 작업들이 이어진 경로가 나타난다.

다음은 main.py의 첫 줄에서 빈 목록을 만들고, 둘째 줄에서 첫 항목을 꺼내려 했을 때 볼 수 있는 기록의 핵심 부분이다. 실행 환경에 따라 코드 아래에 위치 표시가 더 붙거나, 파일 경로가 길게 나올 수 있다.

Traceback (most recent call last):
  File "/work/main.py", line 2, in <module>
    print(items[0])
IndexError: list index out of range

읽는 순서는 세 단계다. 먼저 맨 아래에서 IndexError라는 오류 종류와 그 뒤의 설명을 읽는다. 이 설명은 목록에서 꺼내려는 위치가 범위를 벗어났다는 뜻이다. 다음으로 바로 위의 파일 이름과 줄 번호를 찾는다. 마지막으로 그 줄 주변의 코드를 열어, 목록에 무엇이 들어 있는지 확인한다.

오류 기록은 아래의 종류와 설명부터 읽고 위쪽의 위치와 주변 코드로 올라간다

여러 파일이 등장하면 아래쪽부터 올라가며 자신이 작성하거나 AI에게 받은 파일의 위치를 찾는다. 다만 표시된 줄을 곧바로 원인이라고 단정하지는 않는다. 그 줄은 문제가 드러난 자리일 수 있다. 목록을 비운 코드가 그보다 앞에 있다면, 원인을 찾으려면 그곳까지 살펴봐야 한다.

line 2는 파일의 두 번째 줄이라는 뜻이다. <module>은 여기서는 함수 안이 아닌 파일의 바깥 부분을 실행 중이었다는 표시로 이해하면 된다. 처음부터 기록의 모든 단어를 해석할 필요는 없다. 오류 종류, 파일, 줄 번호, 해당 줄의 실제 값을 먼저 찾으면 된다.

문법 오류는 조금 다르게 나타날 수 있다. 코드를 실행하기 전에 문장의 구조를 검사하다가 발견되므로, 일반적인 실행 중 오류와 같은 호출 기록이 없을 수도 있다. 이때도 아래의 오류 종류를 읽고, 위에 표시된 파일과 줄, 위치 표시를 확인하는 흐름은 유효하다. 오류가 표시된 줄뿐 아니라 바로 앞줄의 괄호나 따옴표도 함께 살펴본다.

다섯 오류는 확인할 대상이 다르다

프로그램에서 발생한 문제를 코드가 처리할 수 있는 형태로 나타낸 것을 예외(exception)라고 한다. 이 장에서 다루는 다섯 이름은 모두 예외의 종류다. 이름을 보면 처음 확인할 대상을 좁힐 수 있지만, 고칠 방법까지 하나로 정해지는 것은 아니다.

다섯 오류의 뜻과 처음 확인할 대상
종류뜻먼저 확인할 것
SyntaxError코드의 문장 구조가 맞지 않는다.콜론, 괄호, 따옴표와 표시된 줄 주변
NameError현재 위치에서 이름을 찾을 수 없다.철자와 값을 넣은 순서
TypeError값의 종류에 맞지 않는 작업을 했다.계산이나 함수에 전달한 값의 종류
IndexError순서가 있는 자료에서 없는 위치를 골랐다.항목 수와 꺼내려는 위치 번호
FileNotFoundError지정한 경로의 파일이나 폴더를 찾지 못했다.경로, 파일 이름, 실행 위치

SyntaxError는 Python 문장의 모양이 규칙에 맞지 않을 때 나타난다. 예를 들어 조건을 적는 if 문에는 조건 뒤에 콜론이 필요하다. 코드 안에 잘못된 문장을 직접 넣으면 파일 전체가 실행되기 전에 멈출 수 있다. 따라서 완성 코드에서는 잘못된 문장을 문자열로 보관하고, 별도의 검사에 넘긴다.

NameError는 아직 값을 연결하지 않은 이름을 사용했을 때 자주 만난다. message에 글을 넣고 mesage를 출력하는 경우가 그렇다. 컴퓨터는 비슷한 철자를 같은 이름으로 보지 않는다. 철자가 같아도 값을 넣는 줄보다 먼저 사용하면 문제가 생길 수 있다.

TypeError의 핵심은 값의 종류다. 따옴표로 둘러싼 "3"은 글자이고, 따옴표 없는 3은 정수다. 글자와 정수를 그대로 더하면 어떤 작업을 하려는지 맞지 않아 오류가 난다. 숫자 계산이 목적이면 글자를 숫자로 바꾸고, 문장을 만드는 목적이면 숫자를 글자로 바꾸는 식으로 의도를 먼저 정해야 한다.

IndexError를 이해하려면 목록의 위치 번호가 0부터 시작한다는 사실이 필요하다. 항목이 두 개라면 사용할 위치 번호는 0과 1이다. 항목 수가 2라고 해서 2번 위치가 있는 것은 아니다. 빈 목록에는 0번 위치도 없다.

FileNotFoundError는 파일 이름이 맞더라도 실행 위치에 따라 나타날 수 있다. notes.txt처럼 기준 위치를 생략한 경로는 프로그램 파일의 위치가 아니라 현재 작업 폴더를 기준으로 해석된다. 현재 작업 폴더는 명령을 실행하는 기준 폴더다. 이번 예제는 임시 폴더 안의 경로를 직접 만들어 이러한 차이를 줄인다.

AI에게는 오류와 실행 맥락을 함께 준다

오류 메시지를 AI에게 전달할 때는 마지막 줄만 복사하기보다 오류 기록 전체를 보내는 편이 좋다. 호출 경로가 있어야 어느 작업에서 문제가 시작되었는지 추적할 수 있기 때문이다. 여기에 실행한 명령, 관련 코드, 사용한 입력, 기대한 결과를 덧붙인다. 실제로 확인하지 않은 원인을 사실처럼 적지는 않는다.

오류 메시지와 함께 전달하면 도움이 되는 정보
정보적는 예필요한 이유
실행 환경과 명령macOS, Python 3.12, python3 main.py같은 실행 조건을 파악한다.
오류 기록Traceback부터 마지막 오류 설명까지발생 위치와 호출 경로를 확인한다.
관련 코드와 입력목록을 만드는 줄과 항목을 꺼내는 줄, 실제 목록오류 직전의 상태를 확인한다.
기대한 결과목록이 비면 “준비물이 없다”를 출력원래 목적에 맞는 수정 방향을 정한다.

다음은 전달할 정보를 모은 요청 예다. 오류 기록은 설명으로 바꾸지 말고, 화면에 나온 내용을 그대로 붙이는 것이 좋다. 다만 사용자 이름이 들어간 경로나 비공개 내용은 가리고, 경로의 구조와 파일 이름 등 문제를 이해하는 데 필요한 부분은 남긴다.

macOS의 Python 3.12에서 main.py를 실행했다. 실행 명령은 python3 main.py다. items = []로 시작하고 다음 줄에서 print(items[0])을 실행했다. 아래에 오류 기록 전체를 붙였다.

목록이 비어 있으면 “준비물이 없다”를 출력하기를 기대했다. 오류가 뜻하는 내용을 먼저 설명하고, 원인으로 판단한 줄과 바꿀 부분을 알려 달라. 수정 후 내가 확인할 입력도 제안해 달라.

AI가 “목록이 비어서 생긴 문제다”라고 답해도 확인은 남아 있다. 실제 코드가 빈 목록을 만드는지 읽고, 수정 뒤 빈 목록과 항목이 있는 목록을 각각 실행한다. 수정 전후의 차이를 보여 주는 비교(diff)도 살펴본다. 요청하지 않은 파일 읽기나 자료 삭제가 추가되지 않았는지, 필요한 변경이 어디에 들어갔는지 직접 확인하는 것이다.

AI에게 오류 기록과 실행 정보를 전달한 뒤 수정 차이와 재실행 결과를 확인한다

이번 완성 코드는 설명을 위한 관찰 도구다. 일부러 만든 오류를 예상한 종류로 잡아 표로 바꾼다. 오류를 잡았다는 것은 그 상황을 코드가 처리했다는 뜻이지, 잘못된 계산이나 경로가 고쳐졌다는 뜻은 아니다. 표의 고치는 방향을 읽고 실제 수정으로 이어지는 판단을 연습한다.

완성 코드

다음 코드를 main.py로 저장한다. 외부 파일이나 추가 설치는 필요 없다. 파일 오류를 만들 때는 임시 폴더 안에 존재하지 않는 파일 경로를 사용한다. 기존 파일을 지우거나 바꾸지 않으며, 임시 폴더는 작업이 끝나면 정리된다.

from pathlib import Path
from tempfile import TemporaryDirectory


def syntax_case():
    source = "if True print('시작')"
    compile(source, "<문법 연습>", "exec")


def name_case():
    values = {}
    return eval("unknown_word", {"__builtins__": {}}, values)


def type_case():
    text = "3"
    return text + 2


def index_case():
    words = ["봄", "여름"]
    return words[2]


def file_case(folder):
    path = folder / "missing.txt"
    return path.read_text(encoding="utf-8")


def collect_rows(folder):
    cases = [
        (syntax_case, SyntaxError,
         "조건문에 콜론이 없음", "콜론과 줄바꿈을 넣기"),
        (name_case, NameError,
         "정의하지 않은 이름 사용", "철자와 정의 순서 확인"),
        (type_case, TypeError,
         "문자열과 정수를 더함", "계산 목적에 맞게 변환"),
        (index_case, IndexError,
         "두 항목에서 2번 선택", "항목 수와 위치 확인"),
        (lambda: file_case(folder), FileNotFoundError,
         "없는 파일을 읽으려 함", "경로와 파일 존재 확인"),
    ]
    rows = []
    for action, error_type, cause, direction in cases:
        try:
            action()
        except error_type as error:
            rows.append((type(error).__name__, cause, direction))
        else:
            raise RuntimeError("예상한 오류가 발생하지 않았다.")
    return rows


def main():
    with TemporaryDirectory() as temp_dir:
        rows = collect_rows(Path(temp_dir))
    print("| 종류 | 원인 | 고치는 방향 |")
    print("| --- | --- | --- |")
    for name, cause, direction in rows:
        print(f"| {name} | {cause} | {direction} |")


if __name__ == "__main__":
    main()

이 파일 자체에는 잘못된 Python 문장이 없다. 문법 오류를 만드는 내용도 따옴표 안의 글자다. 파일을 정상적으로 읽은 뒤 그 글자를 검사하는 순간에만 SyntaxError가 발생한다. 따라서 완성 코드 전체는 문법 검사를 통과하면서도 다섯 오류를 관찰할 수 있다.

줄별 해설

빈 줄을 포함해 위 코드는 64줄이다. 빈 줄은 기능을 나누어 보기 쉽게 하는 역할을 한다. 다음 표는 실행에 관여하는 모든 줄을 묶어서 설명한다. 줄 번호를 코드에 덧붙여 저장하지는 않는다.

완성 코드의 줄과 각 부분이 하는 일
줄코드의 역할읽을 때 확인할 점
1~2경로와 임시 폴더를 다루는 도구를 가져온다.둘 다 Python 표준 라이브러리에 들어 있다.
5~7문법 오류를 만드는 작업을 정의한다.잘못된 문장은 문자열이며 compile이 검사한다.
10~12이름 오류를 만드는 작업을 정의한다.빈 이름 공간에서 unknown_word를 찾는다.
15~17글자와 정수를 더한다.서로 다른 종류를 그대로 더하므로 오류가 난다.
20~22항목 두 개의 목록에서 2번 위치를 읽는다.있는 위치는 0과 1뿐이다.
25~27임시 폴더 안의 없는 파일을 읽는다.파일을 만들지 않았으므로 읽기에 실패한다.
30~42실행할 작업과 예상 오류, 설명을 묶는다.표에 나오는 원인 설명은 사람이 적은 것이다.
43~44결과 목록을 만들고 사례를 차례로 꺼낸다.각 사례의 네 값을 서로 다른 이름으로 받는다.
45~46예외를 관찰할 작업을 실행한다.action 뒤의 괄호가 실제 실행을 뜻한다.
47~48예상한 예외를 잡고 표의 행을 저장한다.실제 예외의 종류 이름을 기록한다.
49~51오류가 없으면 알리고, 수집한 행을 돌려준다.예상과 다른 정상 종료도 조용히 넘기지 않는다.
54~56임시 폴더를 열고 다섯 사례를 실행한다.들여쓴 작업이 끝나면 폴더가 정리된다.
57~60표 머리와 결과 다섯 행을 출력한다.임시 경로나 환경에 따른 오류 문구는 출력하지 않는다.
63~64이 파일을 직접 실행할 때 main을 부른다.프로그램의 시작점을 정하는 관례다.

def는 이름 붙인 작업인 함수를 정의한다. 그 아래 들여쓴 줄들이 한 작업에 속한다. return은 계산한 값을 돌려주는 문장이다. 다만 이번 오류 사례에서는 값을 돌려주기 전에 오류가 발생하므로 정상적인 반환까지 도달하지 않는다.

compile은 문자열을 Python 코드로 해석할 수 있는 형태로 바꾸면서 문법을 검사한다. 여기서는 검사할 글자, 오류에 표시할 이름, 검사 방식을 차례로 전달한다. 이름으로 넣은 <문법 연습>은 실제 파일 경로가 아니다. "exec"는 여러 문장으로 된 코드를 다룰 수 있는 방식이다. 이번 예제는 문법 검사에서 멈추며, 변환된 코드를 따로 실행하지 않는다.

eval은 문자열에 적힌 식을 평가한다. 이번에는 항상 같은 이름 오류를 만들기 위해 고정된 글자 "unknown_word"만 사용한다. values = {}는 이름과 값을 묶어 둘 빈 사전이다. 여기에 해당 이름이 없으므로 오류가 발생한다. 사용자 입력을 받아 eval에 넣는 형태로 바꾸지 않는다. 기본 이름을 비우는 설정도 임의의 코드를 안전하게 실행해 주는 장치는 아니다.

cases는 다섯 사례를 담은 목록이다. 각 사례 안에는 작업, 예상 오류 종류, 원인, 고치는 방향이 들어 있다. lambda는 짧은 함수를 만드는 표현이다. 여기서는 폴더가 필요한 file_case도 다른 사례와 똑같이 action()으로 부를 수 있도록 감싼다. 목록에 넣는 시점이 아니라 차례가 왔을 때 파일 읽기를 실행한다.

try 아래에는 시도할 작업을 쓰고, except 뒤에는 처리할 오류 종류를 쓴다. as error는 발생한 오류를 error라는 이름으로 읽게 한다. type(error).__name__은 그 오류의 종류 이름을 얻는다. append는 목록 끝에 항목을 추가한다. 따라서 실제로 잡힌 오류의 이름과 사람이 적은 설명이 한 행으로 쌓인다.

여기서 else는 try의 작업에서 예외가 발생하지 않았을 때 실행된다. 오류를 일부러 만드는 실습이므로 오류 없이 끝나는 것도 예상과 다르다. 그 경우 raise로 새로운 오류를 발생시켜 알린다. 예상한 종류와 다른 오류가 생겨도 해당 except가 잡지 않으므로 실행이 멈춘다. 이것이 다섯 사례를 확인하는 작은 검사 장치다.

with는 정리가 필요한 자원을 정해진 범위에서 사용하게 한다. 임시 폴더를 사용하는 두 줄이 끝나면 폴더가 정리된다. 결과 행은 이미 메모리에 남아 있으므로 이후 출력할 수 있다. 마지막 출력문의 f가 붙은 문자열은 중괄호 자리에 값을 넣는다. 이때 name, cause, direction이 각각 표의 세 칸을 채운다.

실행 결과

터미널에서 main.py를 저장한 폴더로 이동한 뒤 다음 명령을 실행한다.

python3 main.py

예상 출력은 다음과 같다. 경로와 오류 설명의 원문은 출력하지 않으므로 임시 폴더 이름이 달라져도 결과는 같다. 세로선은 표의 칸을 구별하기 위한 문자다. 터미널에서 열 너비가 가지런하지 않아도 각 행의 내용으로 확인하면 된다.

| 종류 | 원인 | 고치는 방향 |
| --- | --- | --- |
| SyntaxError | 조건문에 콜론이 없음 | 콜론과 줄바꿈을 넣기 |
| NameError | 정의하지 않은 이름 사용 | 철자와 정의 순서 확인 |
| TypeError | 문자열과 정수를 더함 | 계산 목적에 맞게 변환 |
| IndexError | 두 항목에서 2번 선택 | 항목 수와 위치 확인 |
| FileNotFoundError | 없는 파일을 읽으려 함 | 경로와 파일 존재 확인 |

확인할 것은 제목 두 줄 다음에 사례 다섯 줄이 같은 순서로 나오는지다. 오류 기록 없이 표만 나온다고 해서 오류가 발생하지 않은 것은 아니다. 예상한 다섯 오류가 각각 발생했고, 코드가 잡아서 이름을 기록했기 때문에 여기까지 진행한 것이다.

검사가 실제로 작동하는지도 확인할 수 있다. 먼저 원본을 보관하고 return words[2]를 return words[1]로 바꿔 실행한다. 이제 해당 사례는 정상 값을 반환하므로 “예상한 오류가 발생하지 않았다.”라는 오류가 나야 한다. 확인 뒤 원래 코드로 되돌리고 다시 실행한다. 수정 전후의 차이가 위치 번호 하나인지 확인하면, 어떤 변경이 결과를 바꿨는지도 연결해서 볼 수 있다.

실무에서 자주 틀리는 것

따옴표 속 숫자를 바로 계산한다

화면에서 숫자처럼 보인다고 계산 가능한 값인 것은 아니다. 다음 코드는 글자와 정수를 더하므로 TypeError가 난다.

count = "3"
print(count + 2)

목적이 개수 계산이라면 정수로 바꾼다. 아래 코드는 5를 출력한다. 다만 int는 아무 글자나 숫자로 바꾸지는 못한다. 여기서는 입력이 숫자 글자라는 조건이 있다.

count = "3"
print(int(count) + 2)

AI가 무조건 str로 바꾸는 수정을 제안한다면 목적을 다시 확인한다. "3"과 "2"를 이어 붙인 결과 32는 개수 계산의 정답이 아니다. 오류가 사라지는 것과 원하는 결과가 나오는 것은 따로 확인해야 한다.

항목 수를 마지막 위치 번호로 쓴다

다음 목록에는 두 항목이 있지만 2번 위치는 없다. IndexError가 나는 이유다.

words = ["봄", "여름"]
print(words[2])

두 번째 항목을 원했다면 1번 위치를 읽는다. 아래 코드는 여름을 출력한다.

words = ["봄", "여름"]
print(words[1])

이 수정은 두 항목이 있다는 조건에서 맞다. 목록이 비어 있을 수도 있다면 항목이 있는지 확인하는 동작이 필요하다. 오류 메시지만 보고 위치 번호를 줄이는 방식으로는 입력이 달라졌을 때의 문제까지 해결되지 않는다.

파일이 없는데 읽는 위치만 반복해서 바꾼다

다음 코드는 새 임시 폴더에서 아직 만들지 않은 파일을 읽으므로 FileNotFoundError가 난다. 실제 작업에서도 먼저 파일을 만들도록 되어 있었는지, 이미 있는 파일을 읽어야 하는지부터 구별해야 한다.

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "memo.txt"
    print(path.read_text(encoding="utf-8"))

이 예제의 목적이 직접 만든 내용을 읽는 것이라면 읽기 전에 파일을 쓴다. 아래 코드는 연습을 출력한다. 기존 사용자 파일을 다룰 때는 이 수정을 그대로 적용하지 않는다. 쓰기는 이미 있는 파일의 내용을 바꿀 수 있기 때문이다.

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "memo.txt"
    path.write_text("연습", encoding="utf-8")
    print(path.read_text(encoding="utf-8"))

오류를 숨기고 정상 실행으로 생각한다

다음 코드는 이름의 철자가 틀렸는데도 아무 말 없이 끝난다. 종류를 지정하지 않은 except가 오류를 넓게 잡고, pass가 아무 작업도 하지 않기 때문이다. 출력이 없다는 사실만 남아 원인을 찾기 어려워진다.

message = "준비"
try:
    print(mesage)
except:
    pass

이 경우에는 예외 처리를 덧붙일 이유가 없다. 이름을 맞춰 준비를 출력하도록 고친다.

message = "준비"
print(message)

완성 코드가 오류를 잡는 이유는 오류를 관찰하는 것이 프로그램의 목적이기 때문이다. 일반 프로그램에서는 처리할 수 있는 오류만 정해진 방식으로 다룬다. 실행을 조용히 끝내기 위해 오류를 숨기면, AI가 수정한 뒤에도 문제를 발견하기 어려워진다.

한눈에 보기

오류를 만났을 때 따라갈 확인 순서
순서할 일확인할 결과
1기록의 마지막 줄을 읽는다.오류 종류와 설명을 말할 수 있다.
2위로 올라가 파일과 줄을 찾는다.문제가 드러난 코드를 열 수 있다.
3주변 코드와 실제 입력을 확인한다.관찰한 사실과 추측을 구별한다.
4기록과 실행 정보를 AI에게 전달한다.같은 상황을 설명할 정보가 모인다.
5변경 내용을 읽고 다시 실행한다.오류 해소와 기대한 결과를 함께 확인한다.

오류 종류는 조사할 곳을 좁혀 주는 표지다. 같은 종류라도 원인은 달라질 수 있다. 이번 표에 적힌 원인은 의도적으로 만든 다섯 사례에 대한 설명이며, 다른 프로그램의 모든 오류를 설명하는 규칙은 아니다. 다음 장에서는 이렇게 모은 사실을 바탕으로 수정 요청을 더 분명하게 쓰는 방법을 다룬다.

연습 문제

  1. 완성 코드의 문법 오류 사례만 고친다고 하자. source에 넣을 올바른 문자열을 적어 보라. 그 상태에서 전체 프로그램을 실행하면 왜 표가 나오지 않는지도 설명하라.
  2. message = "출발" 다음 줄이 print(mesage)다. 예상 오류 종류와 고치는 방향을 적고, 두 줄짜리 수정 코드를 작성하라.
  3. 목록이 ["봄", "여름"]일 때 위치 번호 0, 1, 2로 각각 접근하면 무슨 일이 일어나는지 적어 보라. 이어 빈 목록의 0번 위치에 접근하면 어떤 오류가 나는지 설명하라.
  4. AI에게 파일 오류를 전달하려 한다. “파일이 안 열린다”라는 문장을 보완해 요청문을 작성하라. 실행 환경과 명령, 오류 기록, 관련 코드와 경로, 기대한 동작을 포함하되 확인하지 않은 사실을 만들어 쓰지 않는다.

정답과 해설

  1. 올바른 문자열의 한 예는 "if True:\n print('시작')"다. 여기서 \n은 문자열 안의 줄바꿈을 나타내며, 그 뒤의 네 칸은 들여쓰기다. 조건 뒤에 콜론이 들어가고 실행할 문장이 다음 줄로 옮겨졌다.

    이를 source에 넣으면 문법 검사를 통과한다. compile은 이 문장을 실제로 실행하지 않으므로 시작이라는 글자도 출력하지 않는다. 이 실습의 수집 코드는 문법 오류가 생기기를 기대하므로 else로 가서 RuntimeError를 발생시킨다. 표는 수집이 끝난 다음 출력하므로 나오지 않는다. 확인 뒤 원래의 오류 사례로 되돌려야 한다.

  2. 예상 오류는 NameError다. 값을 넣은 이름과 읽는 이름의 철자가 다르다. 다음 코드는 출발을 출력한다.

    message = "출발"
    print(message)

    이름을 고친 다음에는 출력까지 확인한다. 오류가 안 보이는지만 살펴보면 다른 이름으로 잘못 바꾼 경우를 놓칠 수 있다.

  3. 0번은 봄, 1번은 여름을 꺼낸다. 2번은 없는 위치이므로 IndexError가 난다. 빈 목록도 0번 위치가 없으므로 같은 종류의 오류가 난다. 위치가 0 이상인지뿐 아니라 실제 항목 수보다 작은지도 확인해야 한다.

  4. 실제 관찰값을 채우는 요청문의 틀은 다음과 같다. 대괄호 부분은 그대로 보내지 않고 자신의 실행 결과로 바꾼다.

    [운영체제와 Python 버전]에서 [실행 명령]으로 실행했다. 현재 작업 폴더는 [확인한 폴더]다. 읽으려는 경로는 [코드에서 사용한 경로]이며, 파일의 존재 여부는 [확인 결과 또는 아직 확인하지 않음]이다.

    오류 기록 전체와 파일을 읽는 부분의 코드를 아래에 붙였다. 기대한 동작은 [파일을 읽은 뒤 나와야 할 결과]다. 기록에서 확인할 수 있는 사실과 추가로 확인해야 할 내용을 나누어 설명해 달라.

    파일이 실제로 있는지 아직 확인하지 않았다면 그렇다고 적는다. AI의 추측을 줄이는 데는 많은 설명보다 정확한 관찰이 도움이 된다. 수정안을 받으면 바뀐 경로와 파일을 쓰는 작업이 추가되었는지 읽고, 원래 실행 명령으로 다시 확인한다.

오탈자·오류 제보 비공개로 접수되어 원고 수정에 반영됩니다

이메일 등 개인정보는 받지 않습니다. 답변이 필요한 질문은 아래 댓글을 이용해 주세요.

READER FEEDBACK

질문·의견

내용에 관한 질문이나 더 나은 설명을 위한 의견을 남겨 주세요. 오탈자는 위의 제보 양식이 더 빨리 반영됩니다. 이 댓글은 원래 게시글과 같은 자리에 쌓입니다.

댓글 0

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

댓글을 남기려면 로그인이 필요합니다.