Python 딕셔너리 뷰는 실시간이며 (코드가 깨질 수 있음)

발행: (2026년 1월 11일 오전 04:16 GMT+9)
4 min read
원문: Dev.to

Source: Dev.to

Quick Quiz

d = {"a": 1, "b": 2}
keys = d.keys()
print(keys)

d["c"] = 3
print(keys)

만약 다음과 같이 기대했다면:

dict_keys(['a', 'b'])
dict_keys(['a', 'b'])

틀렸습니다. 실제 출력은:

dict_keys(['a', 'b'])
dict_keys(['a', 'b', 'c'])  # ← 자동으로 업데이트됨!

Dictionary Views

.keys(), .values(), 그리고 .items()는 복사본을 반환하지 않습니다.
이들은 view 객체—딕셔너리를 실시간으로 비추는 창—이며, 딕셔너리가 변하면 자동으로 업데이트됩니다.

person = {"name": "Alice", "age": 30}
k = person.keys()
print(k)                     # dict_keys(['name', 'age'])

person["city"] = "NYC"       # 키 추가
print(k)                     # dict_keys(['name', 'age', 'city'])
  • 뷰는 데이터를 복사하지 않기 때문에 메모리 효율적입니다.
  • 하지만 동기화된 상태를 기대하지 않으면 버그를 일으킬 수 있습니다.

Modifying While Iterating

실시간 뷰를 순회하면서 딕셔너리를 변형하면 오류가 발생합니다:

config = {"debug": True, "verbose": False, "temp_flag": True}

# True인 모든 플래그 제거
for key in config.keys():
    if config[key] is True:
        del config[key]   # 💥 RuntimeError!

오류

RuntimeError: dictionary changed size during iteration

뷰가 순회 도중에 변하고, 파이썬은 예외를 발생시켜 이를 방지합니다.

Safe Way: Iterate Over a Snapshot

변형하기 전에 뷰를 리스트(또는 다른 정적 컨테이너)로 변환합니다:

config = {"debug": True, "verbose": False, "temp_flag": True}

# 리스트로 변환 – 스냅샷 생성
for key in list(config.keys()):
    if config[key] is True:
        del config[key]

print(config)  # {'verbose': False}

list(config.keys())는 그 순간의 키들을 캡처하므로 원래 딕셔너리를 안전하게 수정할 수 있습니다.

Powerful Uses of Live Views

실시간 뷰는 딕셔너리 변화를 실시간으로 감시해야 할 때 유용합니다:

cache = {}
cache_keys = cache.keys()

# ... 코드의 다른 부분에서 ...
cache["user_123"] = data
cache["user_456"] = more_data

# cache_keys는 모든 추가를 자동으로 반영
print(f"Cached: {len(cache_keys)} items")  # 항상 최신 상태

매번 .keys()를 다시 호출할 필요가 없으며, 뷰가 딕셔너리와 동기화된 상태를 유지합니다.

Conclusion

딕셔너리 뷰 객체는 실시간이며 메모리 효율적이고 강력하지만, 정적이라고 가정하면 미묘한 버그의 원인이 될 수 있습니다. 뷰와 스냅샷(list(dict.keys()))을 언제 사용해야 할지 알면 더 안전하고 예측 가능한 코드를 작성할 수 있습니다.

다음 책 Zero to AI Engineer: Python Foundations에서 발췌한 내용입니다.
원본은 Substack에 처음 공유되었습니다 →

Back to Blog

관련 글

더 보기 »