결론: 데이터보다 작업 질문으로 고른다
순서 있는 항목을 바꿔 가며 저장하면 list, 고정된 항목 묶음이면 tuple, 중복 없는 구성원과 집합 연산이 중요하면 set, 키로 값을 찾으려면 dict를 먼저 검토한다. ‘어느 것이 항상 빠른가’보다 코드가 표현해야 할 작업이 무엇인지가 선택의 출발점이다.
구조 | 순서·중복 | 변경 | 주요 접근·용도 |
|---|---|---|---|
list | 순서 보존, 중복 허용 | 가능 | 정수 인덱스·슬라이스, 항목 모음 |
tuple | 순서 보존, 중복 허용 | 항목 교체 불가 | 정수 인덱스·언패킹, 고정 레코드 |
set | 순서 미보장, 중복 제거 | 가능 | membership·합/교/차집합 |
dict | 삽입 순서 보존, 키 고유 | 가능 | hashable 키로 값 조회 |
list: 순서 있는 가변 데이터
list는 항목의 순서와 중복을 유지하며 인덱싱·슬라이싱·항목 교체를 지원한다. 수집 중인 행, 처리 단계, 시간 순 이벤트처럼 항목이 늘거나 줄고 순서가 의미 있는 데이터에 적합하다.
events = ["login", "view", "login"]
events.append("logout")
events[1] = "click"
print(events)
print(events[1:3])
['login', 'click', 'login', 'logout']
['click', 'login']
CPython은 list를 동적 배열 형태로 구현한다. 공식 튜토리얼은 끝의 append·pop은 빠르고 앞쪽 insert·pop은 나머지 항목 이동 때문에 느리다고 설명한다. 앞뒤 양쪽에서 자주 넣고 빼는 큐라면 다음 글의 collections.deque가 의도를 더 잘 표현한다.
tuple: 고정된 항목 묶음과 언패킹
tuple도 list와 같은 sequence라서 순서·중복·인덱싱을 지원하지만, 생성 후 tuple이 가리키는 항목을 교체하거나 추가할 수 없다. 좌표, 색상 채널, 함수의 여러 반환값처럼 항목 수와 의미가 고정된 작은 레코드에 잘 맞는다.
point = (37.5, 127.0)
latitude, longitude = point
print(latitude, longitude)
record = (1, ["raw"])
record[1].append("clean")
print(record)
37.5 127.0
(1, ['raw', 'clean'])
tuple의 불변성은 내부 객체까지 얼리지 않는다. 위에서는 두 번째 항목을 다른 객체로 교체할 수는 없지만, 그 항목이 가리키는 list 자체는 변경 가능하다.
tuple을 dict 키나 set 원소로 쓰려면 tuple 자체만 불변이면 되는 것이 아니라 포함한 모든 요소가 hashable이어야 한다. list를 품은 위 record는 hash할 수 없다. ‘immutable이면 언제나 hashable’도 일반 규칙이 아니다.
set: membership·중복 제거·집합 연산
set은 hashable한 원소를 중복 없이 보관한다. 특정 값이 허용 목록에 있는지 검사하거나 두 집합의 공통·차이 항목을 구할 때 목적이 선명하다. 정수 인덱스로 접근할 수 없고 순회·출력 순서를 보장하지 않으므로 화면이나 파일의 순서가 필요하면 sorted()처럼 명시적으로 정렬한다.
allowed = {"A", "B", "C"}
observed = {"B", "C", "X", "X"}
print(sorted(observed))
print(sorted(allowed & observed))
print(sorted(observed - allowed))
print("X" in allowed)
['B', 'C', 'X']
['B', 'C']
['X']
False
set은 membership 중심으로 설계된 해시 기반 구조지만, 이를 모든 상황에서 절대 상수 시간이라고 단정하지 않는다. 해시 계산 비용·충돌·입력 특성과 구현이 영향을 준다. 먼저 중복 없는 구성원 집합이라는 의미가 맞는지 판단한다.
dict: hashable 키를 값에 연결한다
dict는 고유한 hashable 키를 임의의 값에 매핑한다. ID로 행을 찾거나 열 이름에 값을 연결하는 작업에 적합하다. 존재하지 않는 키를 data[key]로 읽으면 KeyError가 발생하고, 없을 수 있다면 get()이나 membership 검사를 선택한다.
rows_by_id = {
101: {"name": "Ada"},
102: {"name": "Linus"},
}
rows_by_id[101] = {"name": "Ada Lovelace"}
print(rows_by_id[101]["name"])
print(list(rows_by_id))
print(rows_by_id.get(999, "missing"))
Ada Lovelace
[101, 102]
missing
dict는 현재 Python 언어에서 삽입 순서를 보존한다. 기존 키의 값을 갱신해도 위치는 그대로이며, 키를 삭제한 뒤 다시 추가하면 끝에 들어간다. 다만 정렬 순서와 삽입 순서는 다르므로 크기·이름 순 정렬이 필요하면 sorted()를 사용한다.
dict 키와 set 원소의 정확한 조건은 ‘immutable’이라는 말보다 hashable이다. hash 값이 수명 동안 변하지 않고 비교 규칙을 만족해야 한다. list·dict·set은 보통 hashable하지 않아 키나 set 원소로 쓸 수 없다.
같은 데이터로 네 구조 만들기
events = ["login", "view", "login"]
fixed_events = tuple(events)
unique_events = set(events)
counts = {}
for event in events:
counts[event] = counts.get(event, 0) + 1
print(events)
print(fixed_events)
print(sorted(unique_events))
print(counts)
['login', 'view', 'login']
('login', 'view', 'login')
['login', 'view']
{'login': 2, 'view': 1}
원본 list는 발생 순서와 중복을 보존한다. tuple은 같은 항목을 고정된 sequence로 표현한다. set은 어떤 이벤트가 있었는지만 남기고, dict는 이벤트별 횟수라는 key-value 관계를 표현한다. 변환은 가능하지만 각 구조가 보존하거나 버리는 정보가 다르다.
선택 의사결정 체크리스트
☐ 항목의 순서가 의미 있고 추가·삭제·교체하는가? list를 검토한다.
☐ 항목 수와 위치의 의미가 고정되고 언패킹하는가? tuple을 검토한다.
☐ 중복을 제거하고 membership·합집합·교집합을 묻는가? set을 검토한다.
☐ 고유한 키로 관련 값을 찾아야 하는가? dict를 검토한다.
☐ 키·set 원소·tuple 전체가 필요한 경우 hashable 조건을 확인한다.
흔한 실수
빈 set은 set()으로 만든다. {}는 빈 dict다.
중복 제거를 위해 list를 set으로 바꾸면 원래 순서 정보에 의존할 수 없다. 원래 순서대로 고유 항목이 필요하면 dict의 삽입 순서를 활용한 list(dict.fromkeys(items)) 같은 의도가 다른 방법을 검토한다.
하나의 값만 가진 tuple은 (value,)처럼 쉼표가 필요하다. 괄호만 쓴 (value)는 단순한 그룹 표현식이다.
dict에서 같은 키를 다시 저장하면 항목이 두 개 생기지 않고 기존 값이 교체된다. 중복된 기록을 모두 보존해야 한다면 키 하나에 list를 값으로 두는 구조 등을 사용한다.
데이터 분석에서의 대표 배치
행을 순서대로 수집하는 동안에는 list, 위도·경도처럼 위치가 고정된 작은 값 묶음에는 tuple, 허용 코드와 관측 코드의 차이를 찾을 때는 set, ID를 행이나 메타데이터에 연결할 때는 dict가 자연스럽다. 표 전체가 커지고 열 단위 연산이 필요해지면 이후에 다룰 pandas·Polars 같은 표 전용 구조를 검토한다.
다음 글: collections로 데이터 집계하기
기본 자료구조로 의도를 표현하기 어려운 패턴도 있다. 다음 글에서는 양쪽 끝 큐인 deque, 누락 키 초기화를 돕는 defaultdict, 빈도를 세는 Counter와 우선순위·정렬 위치를 다루는 heapq·bisect를 비교한다.
참고 자료
Python 데이터 구조 공식 튜토리얼 — list 메서드, set 연산, dict 키와 삽입 순서의 기초 (2026-08-03 확인)
Python sequence types 공식 문서 — list·tuple 공통 연산, 가변·불변 sequence와 hash 조건 (2026-08-03 확인)
Python set types 공식 문서 — 중복 없는 원소, membership와 집합 연산 (2026-08-03 확인)
Python mapping types 공식 문서 — hashable 키, key-value 연산과 삽입 순서 보장 (2026-08-03 확인)
Python data model의 hash 공식 문서 — 동등성·hash 값과 hashable 컬렉션의 요구조건 (2026-08-03 확인)
댓글 0
댓글을 불러오는 중…