본문 바로가기
개발/트러블슈팅

Python deque(maxlen)에서 데이터가 사라지는 이유: 자동 삭제와 Queue

by char_lie 2026. 10. 8.
반응형

deque에 넣은 값이 사라졌다면 maxlen을 확인하세요. 가득 찬 deque에 append·appendleft로 새 값을 넣으면 반대쪽 기존 값이 자동으로 빠집니다. 오류 없이 최신 값만 유지하는 동작이므로, 대기 작업이나 BFS 노드를 모두 처리해야 하는 큐에는 주의가 필요합니다.

Python 3.12.14에서 검증했습니다. 같은 실행 환경에서 위에서부터 실행하며, 모든 출력은 짧은 가상 문자열과 작은 그래프를 사용합니다.

가득 찬 양끝 큐에서 새 항목이 들어오며 반대쪽 항목이 나가는 그림
maxlen은 가득 찬 큐의 반대쪽 값을 자동으로 버릴 수 있습니다.

1. 오른쪽 삽입은 왼쪽을, 왼쪽 삽입은 오른쪽을 밀어냅니다

from collections import deque

q = deque(["A", "B", "C"], maxlen=3)
q.append("D")
print(list(q))

q.appendleft("X")
print(list(q))
['B', 'C', 'D']
['X', 'B', 'C']

처음 append 뒤에는 A가 빠지고 B·C·D가 남습니다. 이어서 appendleft를 호출하면 오른쪽 D가 빠져 X·B·C가 됩니다. “최대 세 개”는 새 값을 거절한다는 뜻이 아니라 현재 길이를 제한한다는 뜻입니다.

양끝 큐의 왼쪽 삽입과 오른쪽 제거 방향을 표현한 그림
appendleft는 오른쪽 끝의 기존 항목을 밀어냅니다.

2. 여러 값을 넣을 때도 같은 규칙이 반복됩니다

q = deque(["A", "B"], maxlen=3)
q.extend(["C", "D", "E"])
print(list(q))

q = deque(["A", "B"], maxlen=3)
q.extendleft(["X", "Y"])
print(list(q))
['C', 'D', 'E']
['Y', 'X', 'A']

extend는 오른쪽에 C·D·E를 순서대로 추가해 최근 세 값을 남깁니다. extendleft는 X, 그다음 Y를 왼쪽에 넣으므로 최종 앞부분은 Y·X입니다. 입력 순서가 그대로 보존된다고 가정하면 안 됩니다.

최근 N개 로그나 관측값을 보관하는 창에는 이런 동작이 유용할 수 있습니다. 반대로 모든 입력을 보존해야 한다면 제한 없는 deque와 별도의 보관·처리 정책을 검토하세요.

3. insert는 가득 찼을 때 다르게 반응합니다

q = deque(["A", "B", "C"], maxlen=3)
try:
    q.insert(1, "X")
except IndexError as exc:
    print(type(exc).__name__)
print(list(q))
IndexError
['A', 'B', 'C']

가득 찬 bounded deque에 insert를 적용하면 이 예제처럼 IndexError가 발생하고 원래 값이 유지됩니다. “deque는 용량 초과 시 항상 같은 방법으로 동작한다”는 설명은 정확하지 않습니다. 사용한 메서드를 함께 확인해야 합니다.

4. Queue의 최대 크기는 자동 삭제 정책이 아닙니다

from queue import Queue, Full

tasks = Queue(maxsize=2)
tasks.put_nowait("A")
tasks.put_nowait("B")
try:
    tasks.put_nowait("C")
except Full as exc:
    print(type(exc).__name__)
print(tasks.get_nowait(), tasks.get_nowait())
Full
A B

Queue(maxsize=2)의 put_nowait는 가득 차면 Full을 일으켜 C를 넣지 않습니다. 이미 들어 있던 A·B를 자동 삭제하지 않습니다. 기본 put은 빈 공간이 생길 때까지 기다릴 수 있어, 소비자가 없는 코드에서 무작정 사용하면 대기할 수 있습니다.

용량 초과 항목을 삭제하지 않고 대기시키는 차단 장치 그림
Queue의 제한은 항목을 버리는 deque(maxlen)와 목적이 다릅니다.

Queue는 생산자·소비자 간 동기화를 위한 기능을 제공합니다. 자료구조 이름보다 “최근 값만 남기기”, “새 입력 거절”, “빈 공간까지 대기” 중 필요한 정책을 먼저 선택하세요. 실패한 입력의 재시도·기록 여부도 호출자가 결정해야 합니다.

5. BFS 대기 큐에 maxlen을 넣으면 탐색이 누락될 수 있습니다

graph = {0: [1, 2], 1: [3], 2: [], 3: []}

def bfs(maxlen=None):
    pending = deque([0], maxlen=maxlen)
    visited = {0}
    processed = []
    while pending:
        node = pending.popleft()
        processed.append(node)
        for nxt in graph[node]:
            if nxt not in visited:
                visited.add(nxt)
                pending.append(nxt)
    return processed

print("제한 없음:", bfs())
print("maxlen=1:", bfs(1))
제한 없음: [0, 1, 2, 3]
maxlen=1: [0, 2]

0에서 1과 2를 차례로 넣을 때 maxlen=1은 아직 처리하지 않은 1을 버립니다. visited에는 이미 1이 들어 있는데 1의 이웃 3은 탐색되지 않습니다. 메모리를 줄이려고 대기 큐에 제한을 걸면 알고리즘의 의미를 바꿀 수 있습니다.

분기 탐색에서 기다리는 작업을 모두 보관하는 확장 가능한 큐 그림
BFS에서 아직 처리하지 않은 노드를 자동 삭제하면 탐색이 누락됩니다.

일반적인 BFS 큐는 처리할 노드를 보존해야 합니다. 큰 그래프의 메모리 문제는 그래프 표현, 중복 추가 방지, 문제의 탐색 범위 등으로 따로 검토하세요. 기본 구현은 deque로 구현한 BFS와 최단거리 예제에서 이어서 볼 수 있습니다.

정리: deque의 maxlen과 메서드 확인 → 삭제해도 되는 데이터인지 판단 → 작업 큐라면 거절·대기 정책 선택 → BFS라면 미처리 노드 보존을 검증합니다. 예상 길이만 검사하지 말고 어떤 항목이 남았는지도 함께 확인하세요.

반응형

댓글