본문 바로가기
IT

파이썬 인덱스 오류 (IndexError: list index out of range) 원인과 해결

by 샤나엘 2026. 7. 7.
반응형

파이썬 인덱스 오류 (IndexError: list index out of range) 원인과 해결

리스트를 다루다 보면 유독 "마지막"에서 자꾸 걸린다. 앞의 요소들은 멀쩡히 출력되다가, 딱 한 바퀴를 더 돌거나 한 칸을 더 짚는 순간 "IndexError: list index out of range"가 뜬다. 리스트에 분명히 값이 들어 있는데도 "범위를 벗어났다"니 억울하다. 하지만 이 에러는 사실 파이썬에서 가장 정직한 에러 중 하나다. 리스트의 정해진 범위 밖을 가리켰으니 그렇다고 알려 줄 뿐이다. 핵심은 딱 하나, 인덱스는 0부터 세고 길이 N인 리스트의 마지막 자리는 N번이 아니라 N-1번이라는 사실이다. 이 한 칸의 어긋남(off-by-one)만 이해하면 IndexError는 대부분 몇 초 만에 잡힌다. 이 글은 인덱스가 어떻게 세어지는지부터, 언제 경계를 넘는지, 그리고 안전하게 접근하는 법까지 정리한다.

파이썬 인덱스 오류

 

미리 안심할 사실 하나. 이 에러는 로직이 복잡해서가 아니라 "경계 계산"이 한 칸 어긋나서 나는 경우가 대부분이다. 그래서 리스트의 길이와 지금 짚는 인덱스, 이 두 숫자만 나란히 놓고 보면 원인이 바로 드러난다.

이 글의 순서

 

📏인덱스는 0부터 센다 — 마지막은 왜 N-1인가
🎯딱 한 칸의 문제 — 언제 경계를 넘나
🔍두 숫자로 좁히기 — 길이와 인덱스
✂️슬라이싱은 왜 안 터지나 (중요한 차이)
🛡️안전하게 접근하는 다섯 가지 방법

📏 인덱스는 0부터 센다

파이썬 리스트는 첫 번째 요소를 1번이 아니라 0번으로 센다. 그래서 요소가 세 개인 리스트의 자리 번호는 0, 1, 2다. 3번은 없다. 길이가 3인데 마지막 인덱스가 2라는, 이 "하나 차이"가 IndexError의 거의 모든 뿌리다. 아래 지도를 보면 한눈에 들어온다.

fruits = ["사과", "바나나", "체리"]  ·  길이 3

사과
[0]
바나나
[1]
체리
[2]
없음 ✗
[3]

여기에 파이썬만의 편리한 장치가 하나 더 있다. 음수 인덱스다. -1은 마지막, -2는 뒤에서 두 번째를 가리킨다. 그래서 fruits[-1]은 항상 마지막 요소인 "체리"다. 다만 음수에도 경계는 있다. 요소가 세 개면 -1, -2, -3까지가 유효하고, -4는 다시 범위를 벗어나 IndexError가 난다.

한 줄 요약

길이 N인 리스트에서 쓸 수 있는 인덱스는 0부터 N-1까지, 음수로는 -1부터 -N까지다. 이 범위를 딱 한 칸이라도 벗어나면 IndexError가 난다. 그러니 에러를 만나면 리스트의 길이와 짚은 인덱스, 두 숫자부터 비교한다.


🎯 딱 한 칸의 문제 — 언제 경계를 넘나

전형적인 상황은 반복문의 경계를 하나 크게 잡았을 때다. 마지막 한 바퀴가 리스트 밖으로 나간다.

fruits = ["사과", "바나나", "체리"]   # 길이 3, 유효 인덱스 0~2
for i in range(len(fruits) + 1):     # 0,1,2,3 을 돈다 ← 한 칸 많음
    print(fruits[i])                # i=3 에서 리스트 밖
# IndexError: list index out of range

range(len(fruits))는 0, 1, 2를 주는데, 여기에 +1을 붙여 3까지 돌게 만든 것이 화근이다. len으로 반복할 때는 +1 같은 보정을 붙이지 않는 게 기본이다. 이 밖에도 경계를 넘는 단골 상황이 몇 가지 더 있다.

상황 왜 터지나
빈 리스트 접근 데이터가 안 들어와 []인데 [0]을 짚음
반복문 off-by-one range(len+1), while i <= len 처럼 한 칸 초과
split 조각 수 가정 쉼표가 예상보다 적어 [2]가 없음
빈 리스트에 pop .pop() / .pop(0) 을 빈 리스트에 호출
중첩 리스트 길이 불일치 matrix[i][j] 에서 어떤 행이 더 짧음

특히 split은 조용한 함정이다. "김코딩,30"처럼 쉼표가 하나뿐인 문자열을 split(",")하면 조각이 두 개("김코딩", "30")뿐이라, [2]를 짚는 순간 범위를 벗어난다. 외부에서 들어온 데이터는 늘 예상보다 짧을 수 있다고 보고 조각 수를 확인하는 습관이 필요하다.


🔍 두 숫자로 좁히기 — 길이와 인덱스

진단은 단순하다. 에러가 난 접근 바로 위에서 리스트의 길이(len)와 지금 짚는 인덱스를 함께 찍어 보면, 둘의 관계가 곧장 드러난다.

# 접근 직전에 길이와 인덱스를 함께 확인
print("len =", len(fruits), "/ i =", i)
value = fruits[i]
# 예: len = 3 / i = 3  →  i가 len과 같거나 크면 무조건 초과

규칙은 명확하다. 인덱스가 len과 같거나 크면(또는 음수로 -len보다 작으면) 반드시 IndexError다. 빈 리스트라면 len이 0이라, 0번을 포함해 어떤 양수 인덱스도 다 벗어난다. 그래서 "혹시 이 리스트가 비어 있나?"를 가장 먼저 의심하는 것이 빠른 길이다.


✂️ 슬라이싱은 왜 안 터지나

여기서 파이썬의 중요한 특성 하나를 알아 두면 해결의 폭이 넓어진다. 하나를 콕 집는 인덱싱(fruits[i])은 범위를 벗어나면 에러를 내지만, 범위를 잘라 오는 슬라이싱(fruits[i:j])은 벗어나도 에러 없이 있는 만큼만 돌려준다.

nums = [10, 20]

print(nums[5])      # ✗ IndexError (범위 밖 한 칸 집기)
print(nums[5:9])    # ✓ []      — 안 터진다
print(nums[1:9])    # ✓ [20]    — 있는 만큼만

이 차이는 실무에서 유용하게 쓰인다. "있으면 가져오고 없으면 넘어가고 싶을 때"는 슬라이싱으로 받아 빈 리스트인지 확인하면, 조건문 없이도 IndexError를 피할 수 있다. 뒤의 안전 접근에서 이 트릭을 다시 쓴다.


🛡️ 안전하게 접근하는 다섯 가지

해결의 방향은 둘이다. 하나는 경계 계산을 바로잡는 것(반복문의 +1 제거 등), 다른 하나는 접근하기 전에 범위를 확인하는 것이다. 상황에 맞게 아래에서 고른다.

# ✓ 1) 비었는지 먼저 확인 — 가장 흔한 방어
if fruits:
    print(fruits[0])

# ✓ 2) 인덱스가 범위 안인지 확인
if i < len(fruits):
    print(fruits[i])

# ✓ 3) 마지막 요소는 음수 인덱스로 (빈 경우 대비 포함)
last = fruits[-1] if fruits else None

# ✓ 4) 슬라이스 트릭 — 없으면 빈 리스트, 터지지 않음
picked = fruits[i:i+1]      # [] 또는 [값]

# ✓ 5) 수동 인덱스 대신 반복 — 경계 계산 자체를 없앰
for fruit in fruits:
    print(fruit)

가장 강력한 예방은 다섯 번째다. 요소를 하나씩 처리할 뿐이라면 인덱스를 직접 세지 말고 for 문으로 리스트를 그대로 순회하면, off-by-one이 끼어들 자리 자체가 사라진다. 인덱스 번호가 꼭 필요하면 enumerate를 쓰면 번호와 값을 함께 안전하게 받을 수 있다.

상황별 선택

 

01데이터가 비어 있을 수 있다 → if 리스트: 로 먼저 확인.
02특정 인덱스를 짚어야 한다 → if i < len(리스트): 로 범위 확인.
03마지막 요소가 필요하다 → 리스트[-1] (빈 경우 기본값 처리).
04있으면 가져오고 없으면 넘긴다 → 슬라이스 리스트[i:i+1].
05전체를 순회할 뿐이다 → for 문 직접 순회, 번호 필요하면 enumerate.

💬 자주 묻는 질문

Q1리스트에 값이 있는데 왜 범위를 벗어났다고 하나요?

값의 개수와 인덱스 번호가 다르기 때문입니다. 값이 세 개여도 자리 번호는 0, 1, 2뿐이라 3번은 없습니다. 길이가 3인데 [3]을 짚으면 값이 있고 없고를 떠나 범위를 벗어난 겁니다. len(리스트)와 짚는 인덱스를 비교해 보세요.

Q2슬라이싱은 왜 에러가 안 나나요?

파이썬은 하나를 집는 인덱싱(리스트[i])과 범위를 잘라 오는 슬라이싱(리스트[i:j])을 다르게 다룹니다. 슬라이싱은 범위를 벗어나도 있는 만큼만, 없으면 빈 리스트를 돌려줍니다. 그래서 리스트[5:9]는 짧은 리스트에서도 에러 없이 []를 줍니다. "있으면 가져오기"에 이 성질을 활용할 수 있습니다.

Q3빈 리스트에서 pop을 했더니 같은 에러가 나요.

.pop()이나 .pop(0)은 꺼낼 요소가 없으면 IndexError를 냅니다("pop from empty list"). 반복해서 꺼내는 코드라면 while 리스트: 처럼 비어 있지 않은 동안만 돌게 하거나, 꺼내기 전에 if 리스트: 로 확인하세요.

Q4딕셔너리에서도 IndexError가 나나요?

아니요. 없는 키를 딕셔너리에서 짚으면 IndexError가 아니라 KeyError가 납니다. IndexError는 리스트·튜플·문자열처럼 순서가 있는(정수 인덱스로 접근하는) 자료에서, 정해진 범위를 벗어났을 때 나는 에러입니다.


📌 정리하며

"IndexError: list index out of range"는 리스트의 정해진 범위, 즉 0부터 길이-1까지(음수로는 -1부터 -길이까지)를 벗어난 자리를 짚었을 때 나는 에러다. 값이 있고 없고의 문제가 아니라 "자리 번호"의 문제이고, 대개는 딱 한 칸 어긋난 경계 계산이 원인이다. 그래서 해결의 출발점은 리스트의 길이와 짚는 인덱스, 두 숫자를 나란히 비교하는 것이다.

 

실무 원칙을 세 가지로 남긴다.

📏 인덱스는 0부터다. 길이 N의 마지막은 N-1이다. 반복문에 괜한 +1을 붙이지 않는다.

🔍 길이부터 의심한다. 빈 리스트(len 0)면 어떤 인덱스도 벗어난다. 접근 전에 if 리스트: 로 확인한다.

🛡️ 경계를 없앤다. 순회면 for 문으로 직접 돌고, 번호가 필요하면 enumerate를, "있으면 가져오기"면 슬라이싱을 쓴다.

인덱스 오류 체크리스트

 

01len(리스트)와 짚는 인덱스를 함께 출력해 비교한다.
02인덱스 ≥ 길이거나 리스트가 비어 있지 않은지 확인.
03반복문 경계에 불필요한 +1 이 붙지 않았는지 점검.
04split·외부 데이터의 조각 수를 가정하지 말고 확인.
05가능하면 for 순회·enumerate·슬라이싱으로 경계 계산을 없앤다.

본 글은 파이썬 IndexError의 일반적 원인과 해결 방법을 정리한 자료다. 코드 수정은 영향 범위를 확인한 뒤 신중히 적용한다.

 

#파이썬 #Python #IndexError #listindexoutofrange #파이썬에러 #인덱스 #리스트 #파이썬리스트 #오프바이원 #파이썬디버깅 #파이썬초보 #예외처리 #슬라이싱 #코딩 #프로그래밍

반응형

댓글