GDGoC/Python

[Python] Basic #06: 자료구조

Opal1031 2026. 8. 12. 17:11

Python에서 자주 사용하는 자료구조인 리스트, 튜플, 집합, 딕셔너리의 특징과 활용 방법을 다룹니다.

 

자료구조는 여러 데이터를 저장하고 관리하는 방법입니다.

같은 데이터를 저장하더라도 어떤 자료구조를 선택하는지에 따라 코드를 더 간결하고 효율적으로 만들 수 있습니다.


1. 리스트(List)

리스트는 여러 값을 순서대로 저장하는 자료구조입니다.

 

값의 추가, 삭제, 수정이 가능하며 같은 값이 여러 번 들어갈 수 있습니다.

numbers = [10, 20, 30]

numbers.append(40)
numbers[0] = 5
numbers.remove(20)

print(numbers)  # [5, 30, 40]

 

리스트는 다음과 같은 상황에 적합합니다.

  • 데이터의 순서가 중요할 때
  • 값을 추가하거나 삭제해야 할 때
  • 같은 값의 중복을 허용해야 할 때
  • 인덱스로 특정 위치의 값에 접근해야 할 때

 

자주 사용하는 메서드는 다음과 같습니다.

numbers = [3, 1, 2]

numbers.append(4)     # 마지막에 추가
numbers.insert(1, 5)  # 특정 위치에 추가
numbers.pop()         # 마지막 값 제거 후 반환
numbers.sort()        # 오름차순 정렬

print(numbers)

2. 튜플(Tuple)

튜플도 여러 값을 순서대로 저장하지만, 생성한 뒤에는 값을 변경할 수 없습니다.

point = (3, 5)

print(point[0])  # 3
print(point[1])  # 5

 

튜플의 값을 각각의 변수로 분리할 수 있습니다.

x, y = point

print(x)  # 3
print(y)  # 5

이를 튜플 언패킹이라고 합니다.

 

함수에서 여러 값을 반환할 때도 튜플이 사용됩니다.

def calculate(a, b):
    return a + b, a * b

total, product = calculate(3, 4)

print(total)    # 7
print(product)  # 12

 

튜플은 다음과 같은 상황에 적합합니다.

  • 좌표처럼 서로 관련된 값을 하나로 묶을 때
  • 저장한 값을 변경하면 안 될 때
  • 함수에서 여러 값을 반환할 때
  • 딕셔너리의 key나 집합의 요소로 사용할 때

 

요소가 하나인 튜플은 쉼표를 함께 작성해야 합니다.

single = (1,)

print(type(single))  # <class 'tuple'>

3. 집합(Set)

집합은 중복되지 않는 값들을 저장하는 자료구조입니다.

 

순서를 기준으로 데이터를 관리하지 않으며, 특정 값의 존재 여부를 빠르게 확인할 수 있습니다.

numbers = {1, 2, 2, 3, 3, 3}

print(numbers)  # {1, 2, 3}

 

리스트의 중복을 제거할 때 집합으로 변환할 수 있습니다.

names = ["Alice", "Bob", "Alice", "Charlie"]
unique_names = set(names)

print(unique_names)

 

집합에는 값을 추가하거나 제거할 수 있습니다.

fruits = {"apple", "banana"}

fruits.add("orange")
fruits.remove("banana")

print(fruits)

 

remove()는 값이 없으면 오류가 발생하지만, discard()는 값이 없어도 오류가 발생하지 않습니다.

fruits.discard("grape")

4. 집합 연산

집합을 사용하면 합집합, 교집합, 차집합을 쉽게 구할 수 있습니다.

A = {1, 2, 3, 4}
B = {3, 4, 5, 6}

print(A | B)  # 합집합: {1, 2, 3, 4, 5, 6}
print(A & B)  # 교집합: {3, 4}
print(A - B)  # 차집합: {1, 2}
print(A ^ B)  # 대칭 차집합: {1, 2, 5, 6}


두 목록에서 공통으로 등장하는 값을 찾을 때 교집합을 활용할 수 있습니다.

python_members = {"Alice", "Bob", "Charlie"}
algorithm_members = {"Bob", "Charlie", "Dave"}

both = python_members & algorithm_members

print(both)  # {'Bob', 'Charlie'}

5. 딕셔너리(Dictionary)

딕셔너리는 key:value 형태로 데이터를 저장합니다.

 

리스트가 위치를 나타내는 인덱스로 값에 접근한다면, 딕셔너리는 직접 지정한 key로 값에 접근합니다.

student = {
    "name": "Alice",
    "score": 90
}

print(student["name"])  # Alice

student["score"] = 95
student["grade"] = "A"

 

딕셔너리를 순회할 때는 keys(), values(), items()를 사용할 수 있습니다.

scores = {
    "Alice": 90,
    "Bob": 75,
    "Charlie": 85
}

for name, score in scores.items():
    print(name, score)

 

값이 없는 key에 안전하게 접근하려면 get()을 사용할 수 있습니다.

print(scores.get("Dave", 0))  # 0

6. 빈도수 세기

딕셔너리는 각 값의 등장 횟수를 셀 때 자주 사용됩니다.

text = "banana"
counts = {}

for char in text:
    counts[char] = counts.get(char, 0) + 1

print(counts)
# {'b': 1, 'a': 3, 'n': 2}

 

collections.Counter를 사용하면 같은 작업을 더 간단하게 처리할 수 있습니다.

from collections import Counter

counts = Counter("banana")

print(counts)
  • 직접 딕셔너리로 구현하는 방법을 이해한 뒤 Counter를 사용하면 동작 원리를 더 쉽게 이해할 수 있습니다.

7. 스택과 큐

리스트와 deque를 이용해 스택과 큐를 만들 수도 있습니다.

 

스택

스택은 마지막에 들어온 값이 가장 먼저 나오는 LIFO 구조입니다.

stack = []

stack.append(1)
stack.append(2)
stack.append(3)

print(stack.pop())  # 3

 

큐는 먼저 들어온 값이 먼저 나오는 FIFO 구조입니다.

from collections import deque

queue = deque()

queue.append(1)
queue.append(2)
queue.append(3)

print(queue.popleft())  # 1
  • 리스트의 pop(0)은 앞의 값을 제거한 뒤 나머지 값을 이동해야 합니다.
  • 큐의 앞에서 값을 자주 제거해야 한다면 deque.popleft()를 사용하는 것이 더 효율적입니다.

8. 자료구조 선택하기

상황에 맞는 자료구조를 선택하는 것이 중요합니다.

필요한 기능 적합한 자료구조
순서를 유지하고 값을 수정 리스트
순서를 유지하지만 값을 변경하지 않음 튜플
중복 제거 또는 빠른 존재 여부 확인 집합
key와 value를 연결하여 저장 딕셔너리
마지막에 넣은 값부터 제거 리스트를 이용한 스택
먼저 넣은 값부터 제거 deque를 이용한 큐

 

예를 들어 회원 번호가 이미 등록되었는지 확인해야 한다면 리스트보다 집합이 자연스럽습니다.

registered = {101, 102, 103}
member_id = 102

if member_id in registered:
    print("이미 등록된 회원입니다.")

 

학생 이름으로 점수를 찾아야 한다면 딕셔너리가 적합합니다.

scores = {
    "Alice": 90,
    "Bob": 80
}

print(scores["Alice"])

9. 자주 하는 실수/주의점

  • 빈 집합은 {}가 아니라 set()으로 생성합니다. {}는 빈 딕셔너리입니다.
  • 집합은 순서를 보장하는 용도로 사용하지 않습니다.
  • 리스트와 딕셔너리를 집합의 요소로 넣을 수 없습니다.
  • 딕셔너리에 없는 key를 dict[key]로 조회하면 KeyError가 발생합니다.
  • 튜플은 생성한 뒤 요소를 수정할 수 없습니다.
  • 큐를 구현할 때 리스트의 pop(0)을 반복해서 사용하는 것은 비효율적입니다.
  • 중복을 제거한 뒤 기존 순서도 유지해야 한다면 단순히 set()으로 변환해서는 안 됩니다.

10. 종합 요약

  • 리스트: 순서가 있고 수정 가능한 데이터
  • 튜플: 순서가 있지만 수정할 수 없는 데이터
  • 집합: 중복 없는 데이터와 집합 연산
  • 딕셔너리: key와 value의 연결
  • 스택: LIFO, 리스트의 append()pop()
  • 큐: FIFO, dequeappend()popleft()
  • 자료구조를 선택할 때는 순서, 중복, 수정 여부, 접근 방법을 먼저 확인