04-3 딕셔너리
윤혜민·박현규 · 18 / 30 절딕셔너리는 리스트의 성질을 가지고 있지만 key, value라는 개념을 도입하여 사전의 특징을 결합한 자료형입니다. 사전은 어떤 단어를 찾으면 그 단어의 뜻이 나열되어 있습니다. 딕셔너리도 마찬가지입니다. 딕셔너리의 key가 사전의 찾을 단어이고 value가 사전의 뜻입니다.
[Note] 요즘은 사전을 많이 쓰지는 않습니다만 일상에서 비유하기는 사전만한게 없어서 사전을 비유하였습니다.

딕셔너리의 이런 특징을 사전과 함께 기억하면서 코드를 작성하고 실행하며 딕셔너리를 자세히 알아보겠습니다.
딕셔너리 기초 연습하기
딕셔너리는 중괄호와 "key" : value의 형태로 사용합니다. 기본 형태는 다음과 같습니다.
student = {
"name": "김철수",
"age": 20,
"major": "컴퓨터공학"
}
print(f"딕셔너리: {student}")
print(f"이름: {student['name']}")
print(f"나이: {student['age']}")
print(f"전공: {student['major']}")
[실행 결과]
딕셔너리: {'name': '김철수', 'age': 20, 'major': '컴퓨터공학'}
이름: 김철수
나이: 20
전공: 컴퓨터공학
코드를 보면 중괄호로 열고 닫은 후 그 사이에 "name" : "김철수"와 같이 key-value 쌍을 쉼표로 구분하여 나열합니다. 이후 값을 찾을 때는 "name", "age", "major"와 같은 키로 찾습니다.
student['name'] : student의 'name' 키에 해당하는 값 '김철수'를 찾습니다.
student['age'] : student의 'age' 키에 해당하는 값 20을 찾습니다.
student['major'] : student의 'major' 키에 해당하는 값 '컴퓨터공학'을 찾습니다.
마치 사전을 찾아 뜻을 보는 모습 같습니다. 리스트에서는 인덱스를 사용하여 student[0]과 같이 작성해야 리스트의 요소 값에 접근할 수 있었지만 딕셔너리에서는 사람이 인지하기 좋은 값을 사용하므로 좀 더 코드가 인간다워졌습니다.
딕셔너리의 값 수정하기
딕셔너리는 리스트와 마찬가지로 가변 자료형입니다. 그래서 값을 변경할 수 있습니다. 리스트에서는 인덱싱으로 값을 수정했다면 딕셔너리에서는 키를 이용하여 수정할 수 있습니다. 말 그대로 '나이를 수정하자'와 같은 생각으로 student["age"]를 이용하여 코드 수정을 해볼 수 있습니다.
student = {"name": "김철수", "age": 20}
# 기존 값 변경
student["age"] = 21
print(f"나이 변경 후: {student}")
[실행 결과]
나이 변경 후: {'name': '김철수', 'age': 21}
코드를 보면 student["age"]로 키가 "age"인 값을 20에서 21로 수정했습니다. 이해하기 어려운 코드는 아니므로 바로 다음으로 넘어가겠습니다.
딕셔너리에 값 추가하기
값을 추가하는 것도 마찬가지입니다. 만약 student에 학점을 추가하고 싶다면 다음과 같이 코드를 작성하면 됩니다.
student = {"name": "김철수", "age": 20}
# 새로운 항목 추가
student["grade"] = "A+"
print(f"성적 추가 후: {student}")
[실행 결과]
성적 추가 후: {'name': '김철수', 'age': 21, 'grade': 'A+'}
실행 결과를 보면 값의 수정과 추가는 '키가 이미 있는 건지 아닌지'에 따라 결정된다는 것을 알 수 있습니다. 이미 있는 키에 값을 할당하면 기존 값이 바뀝니다. 그리고 없는 키에 값을 할당하면 딕셔너리에 새 항목이 추가됩니다.
<1:1코칭> 딕셔너리는 더하기나 곱하기가 안 되나요?
네 안 됩니다. 리스트는 + 연산자로 두 리스트를 합치고 * 연산자로 리스트를 복사할 수 있지만, 딕셔너리에 더하기나 곱하기와 같은 연산자를 직접 사용하면 오류가 발생합니다. 딕셔너리는 키-값 쌍을 저장하는 자료구조이기 때문에 수학 연산이 정의되어 있지 않기 때문이죠. 만약 두 딕셔너리를 합치고 싶다면 다음과 같이 update( ) 함수를 사용해야 합니다.
menu1 = {"커피": 3000, "주스": 2500}
menu2 = {"케이크": 5000, "쿠키": 2000}
# update() 메서드로 합치기
combined = menu1.copy()
combined.update(menu2)
print(f"합친 메뉴: {combined}")
[실행 결과]
합친 메뉴: {'커피': 3000, '주스': 2500, '케이크': 5000, '쿠키': 2000}
</1:1코칭>
딕셔너리에서 키 검색하기
딕셔너리는 사전식으로 데이터를 관리한다고 했습니다. 그렇다면 앞에서 배운 in을 사용해볼 수 있습니다. in은 '그것이 거기에 있는가?'를 계산해줍니다. 따라서 다음과 같이 코드를 작성하면 딕셔너리에서 키를 검색하고 해당 키가 있는지 없는지를 알 수 있습니다.
student = {"name": "김철수", "age": 20, "major": "컴퓨터공학"}
print("name" in student)
print("grade" in student)
[실행 결과]
True
False
실행 결과를 보면 키가 딕셔너리에 있으면 True를 반환하고, 그렇지 않으면 False를 반환합니다. in의 장점은 데이터가 있는지 없는지 보고 알려준다는 것에 있습니다. 이 설명이 좀 이상하게 느껴질 수 있습니다. 왜냐하면 '딕셔너리에 해당 키가 있는지 없는지 검색을 할 때 student['name']으로 바로 접근해도 되는 것 아닐까?'라고 생각할 수도 있기 때문입니다. 하지만 그렇게 프로그래밍을 하면 프로그램 실행 도중 오류가 발생할 수도 있습니다. 프로그래밍 세계에서는 실행 도중 발생하는 오류를 대처하는 것이 아주 중요합니다. 예를 들어 딕셔너리에서 "score"키가 있는지 없는지 검사하기 위해 다음 코드를 작성했다고 생각해봅시다.
print(student["score"]) ➝ 오류 발생!
그러면 프로그램은 이 코드를 지나갈 때 오류를 발생시키고 이후 코드를 더 실행하지 않고 중단할 것입니다. 프로그램을 작성하는 사람 입장에서는 이건 곤란한 일입니다. 아예 프로그램이 뻗어버리는 셈이니까요. 여러분이 프로그램을 사용하다가 '응용 프로그램이 응답하지 않습니다'라는 메시지를 봤다면 그것이 바로 지금의 예와 비슷한 경우입니다.

그래서 이런 일을 방지하기 위한 문법 요소가 있습니다. 앞에서 사용한 in은 어쨌든 오류가 발생하지 않고 False를 반환하고 있으므로 이후 처리만 잘해준다면 프로그램의 실행은 계속될 수 있습니다. 혹시라도 'in을 쓰는 것이 대체 나에게 무슨 의미가 있는 걸까?'라는 생각이 들었다면 이 글을 통해 의문이 풀렸기 바랍니다.
딕셔너리에서 for문과 함께 반복하기
딕셔너리도 리스트에서 공부했던 것처럼 반복문과 함께 사용할 수 있습니다. 리스트에서는 특별히 이런 성질에 대해 언급하지는 않았지만 for문과 같은 반복문 문법으로 반복할 수 있는 성질을 가진 자료형을 iterable하다고 합니다. 리스트에서 반복문을 리스트와 어떻게 조합했는지 다시 코드를 작성하며 기억을 떠올려봅시다.
scores = [85, 92, 78, 96, 88]
# 반복문으로 합계 구하기
total = 0
for score in scores:
print(f"현재 점수 : {score}")
[실행 결과]
현재 점수 : 85
현재 점수 : 92
현재 점수 : 78
현재 점수 : 96
현재 점수 : 88
실행 결과를 보면 리스트의 요소를 처음부터 끝까지 딱 요소 개수만큼만 반복하면서 print( ) 함수를 실행하여 현재 점수를 출력하였습니다. 이렇게 iterable한 자료형에 반복문을 조합하면 요소 처음부터 끝까지 요소 개수만큼 반복합니다. 딕셔너리도 마찬가지입니다. 하지만 딕셔너리에는 key, value 개념이 있으므로 for문을 조합할 때 그냥 조합할 수도 있고, key, value 개념을 구분하여 조합할 수도 있습니다. 정리하자면 딕셔너리는 총 3가지 방법으로 반복문을 조합하여 사용할 수 있습니다.
딕셔너리와 for문 그냥 조합하기
다음은 student 딕셔너리와 for문을 그냥 조합한 것입니다. 딕셔너리와 for문을 그냥 조합하면 딕셔너리의 키만 순회합니다.
student = {
"name": "김철수",
"age": 20,
"major": "컴퓨터공학",
"grade": "A+"
}
# 기본 반복 - 키만 가져오기
for key in student:
print(f"키: {key}")
[실행 결과]
키: name
키: age
키: major
키: grade
이제는 for key in student: 문장을 보면 student 딕셔너리를 이용해서 키를 가지고 순회하라는 의미로 받아들여져야 합니다. 이런 그림을 떠올려야 합니다.

한마디로 student 딕셔너리가 for ... in 문을 만나면 순회를 준비하게 되는데, 순회 시에는 요소의 처음부터 끝까지 하나씩 사용하게 되는 것입니다. 따라서 딕셔너리의 요소가 총 4개이므로 for key in student: 문장은 4회의 반복을 하게 될 것입니다. 이때 반복문에서는 key를 사용하게 되므로 키값인 name, age, major, grade가 print(f"키: {key}")에 의하여 출력된 것입니다.
딕셔너리 값으로 순회하기
이제 값으로 순회하는 방법을 알아봅시다. student.values( )를 실행하면 student 딕셔너리에 있는 값을 순회할 수 있는 형태로 만들어줍니다. 아직 '순회할 수 있는 형태'는 완벽하게 이해하지 못해도 됩니다. 앞에서 우리가 배운 '어쨌든 뭔가 값을 하나씩 빼서 반복할 수 있다' 정도로 이해하면 됩니다. 다음 코드를 작성해봅시다.
student = {
"name": "김철수",
"age": 20,
"major": "컴퓨터공학",
"grade": "A+"
}
# values() - 값만 가져오기
for value in student.values():
print(f"값: {value}")
[실행 결과]
값: 김철수
값: 20
값: 컴퓨터공학
값: A+
실행 결과를 보면 값만 순회하며 출력합니다. 다음 그림을 떠올리면 됩니다. 그림과 함께 코드와 실행 결과를 번갈아보기 바랍니다. 아마 이해가 어렵진 않을 겁니다.

딕셔너리 키와 값을 동시에 순회하기
이제는 '키와 값을 한꺼번에 순회하는 방법은 없을까?'라는 생각이 들 겁니다. 키만 따로 순회하고 값만 따로 순회하기보다는 한꺼번에 순회하면서 필요한 구성 요소를 쓰면 좋으니까요. 그럴 때는 student.items( )를 in 다음에 두면 됩니다. 앞의 코드를 수정하여 다음 코드를 입력하여 실행해보기 바랍니다.
...생략...
for key, value in student.items():
print(f"{key}: {value}")
[실행 결과]
name: 김철수
age: 20
major: 컴퓨터공학
grade: A+
이제는 그림 없이 봐도 코드가 이해될 것입니다. 다만 student.items( )는 key, value 순서쌍으로 순회할 수 있는 형태의 무언가를 만들어주므로 key, value의 순서는 지켜야 합니다.
for 오른쪽에 있는 key, value의 순서를 바꾸거나 이름을 바꾸면 어떻게 되나요?
파이썬은 변수 이름이 무엇인지는 신경 쓰지 않고 키-값 순서쌍으로 할당합니다. 그래서 순서를 바꿔 코드를 작성하면 value라는 이름의 변수에 키가 들어가고, key라는 이름의 변수에 값이 들어가게 되죠.
for value, key in student.items():
print(f"value 변수: {value}, key 변수: {key}")
[실행 결과]
value 변수: name, key 변수: 김철수
value 변수: age, key 변수: 20
value 변수: major, key 변수: 컴퓨터공학
출력 결과를 보면 부자연스럽습니다. 왜냐하면 value의 자리는 student.items( )에서 보내준 키가 들어올 자리이기 때문이죠. 이를 통해 'for 다음에 쓰는 변수는 순서가 중요하지 이름이 중요한 게 아니구나'라는 생각을 해볼 수 있습니다. 그림으로 보면 이렇게 동작하는 셈입니다.

실제로 이렇게 작성해도 코드는 잘 동작합니다. one에는 키가, two에는 값이 들어갈 겁니다.
for one, two in student.items():
print(f"one 변수: {one}, two 변수: {two}")
[실행 결과]
one 변수: name, two 변수: 김철수
one 변수: age, two 변수: 20
one 변수: major, two 변수: 컴퓨터공학
결론은 student.items( )는 키-값 순서쌍을 튜플로 만들어 보내줄 뿐이고, for 다음에 나올 변수의 순서가 중요하지 이름은 전혀 중요하지 않다는 걸 알 수 있습니다. 딕셔너리 반복문을 공부하면서 의문이 있었다면 이 코너를 통해 의문이 말끔히 해결되었기 바랍니다.
딕셔너리 응용 연습하기
딕셔너리는 리스트와 마찬가지로 딕셔너리 안에 딕셔너리를 포함할 수도 있고, 리스트를 포함할 수도 있는 자유로운 자료형입니다.
중첩 딕셔너리 사용해보기
딕셔너리는 값으로 또 다른 딕셔너리를 가질 수 있습니다. 이를 중첩 딕셔너리라고 부르며, 복잡한 구조를 딕셔너리로 표현할 때 매우 유용합니다. 다음 코드를 입력해서 실행해봅시다.
students = {
"김철수": {"age": 20, "major": "컴퓨터공학", "grade": "A"},
"이영희": {"age": 21, "major": "경영학", "grade": "B+"},
"박민수": {"age": 19, "major": "수학", "grade": "A+"}
}
print(students["김철수"])
print(students["김철수"]["major"])
print(students["이영희"]["age"])
[실행 결과]
{'age': 20, 'major': '컴퓨터공학', 'grade': 'A'}
컴퓨터공학
21
첫 번째 출력은 "김철수" 키에 해당하는 전체 딕셔너리를 보여줍니다. 두 번째와 세 번째 출력은 대괄호를 두 번 사용해서 중첩된 딕셔너리의 특정 값에 접근하는 방법을 보여줍니다. students["김철수"]["major"]는 먼저 ["김철수"]를 키로 하고 있는 값, 즉, 딕셔너리 안의 딕셔너리 {"age": 20, "major": "컴퓨터공학", "grade": "A"}를 찾고, 다시 그 안에서 ["major"] 키의 값 "컴퓨터공학"을 가져오는 겁니다.
중첩 딕셔너리의 값을 수정하거나 추가할 수도 있습니다.
students = {
"김철수": {"age": 20, "major": "컴퓨터공학"},
"이영희": {"age": 21, "major": "경영학"}
}
# 값 수정
students["김철수"]["age"] = 21
# 새로운 키와 학생 추가
students["김철수"]["grade"] = "A"
students["최지원"] = {"age": 20, "major": "물리학", "grade": "B"}
print(students)
[실행 결과]
{'김철수': {'age': 21, 'major': '컴퓨터공학', 'grade': 'A'}, '이영희': {'age': 21, 'major': '경영학'}, '최지원': {'age': 20, 'major': '물리학', 'grade': 'B'}}
이처럼 중첩 딕셔너리를 사용하면 관련 정보를 묶어서 체계적으로 관리할 수 있습니다. 각 학생의 정보가 하나의 딕셔너리로 정리되어 있어서 데이터를 다루기가 훨씬 편리해지는 걸 느낄 수 있을 겁니다.
딕셔너리에 리스트 넣어보기
딕셔너리의 값으로 리스트를 사용할 수도 있습니다. 이 방법은 하나의 키에 여러 개의 값을 연결해야 할 때 특히 유용합니다. 예를 들어 한 학생이 수강하는 여러 과목을 저장하거나, 한 회사의 여러 직원 이름을 관리할 때 리스트를 값으로 사용하면 편리합니다. 다음 코드를 입력해서 실행해보면 딕셔너리와 리스트를 조합하는 방법을 알 수 있을 겁니다.
student_courses = {
"김철수": ["수학", "영어", "과학"],
"이영희": ["국어", "역사", "음악"],
"박민수": ["수학", "물리", "화학", "생물"]
}
print(student_courses["김철수"])
print(student_courses["박민수"][1])
print(len(student_courses["이영희"]))
[실행 결과]
['수학', '영어', '과학']
물리
3
첫 번째 출력은 김철수가 수강하는 모든 과목 리스트를 보여줍니다. 두 번째 출력은 박민수의 과목 리스트에서 인덱스 1의 값인 "물리"를 가져옵니다. 세 번째 출력은 이영희가 수강하는 과목의 개수를 len( ) 함수로 계산했습니다.
리스트에 딕셔너리 넣기
반대로 리스트에 딕셔너리를 넣을 수도 있습니다. 딕셔너리는 키로 값을 찾는 데에 특화가 되어 있으므로 '키로 값을 찾는 것이 좋겠다'라는 생각이 들 때는 딕셔너리가 좋습니다. 하지만 어차피 값의 형태가 균일하면 딕셔너리보다는 리스트가 훨씬 유리합니다. 예를 들어 학생의 정보가 이름, 나이, 학점으로 모두 동일하다면 굳이 딕셔너리에 딕셔너리를 넣을 필요는 없습니다. 오히려 그렇게 설계하면 바깥쪽 딕셔너리의 키를 무엇으로 할지 고민하거나 지정하는 수고가 더 큽니다.
students = [
{"name": "김철수", "age": 20, "grade": "A"},
{"name": "이영희", "age": 21, "grade": "B+"},
{"name": "박민수", "age": 19, "grade": "A+"}
]
print(students[0])
print(students[1]["name"])
print(f"{students[2]['name']}의 학점은 {students[2]['grade']}입니다.")
[실행 결과]
{'name': '김철수', 'age': 20, 'grade': 'A'}
이영희
박민수의 학점은 A+입니다.
첫 번째 출력은 리스트의 첫 번째 요소인 김철수의 전체 딕셔너리를 보여줍니다. 두 번째 출력은 인덱스로 딕셔너리를 선택한 후 그 안의 "name" 키 값을 가져옵니다. 세 번째 출력은 f-string을 사용해서 데이터를 문장으로 만드는 예입니다.
딕셔너리 실전 연습하기
그럼 딕셔너리는 대체 왜 쓰는 걸까요? 지금까지 실습한 내용은 솔직히 가슴에 와 닿지는 않을 겁니다. 실용성이 크게 느껴지지 않을 겁니다. 그래서 이번에는 학교에서 학생 데이터를 파일로 받았다고 가정하고, 이것을 리스트, 딕셔너리로 다루는 실습을 진행해보겠습니다. 여러분의 10명의 학생을 관리하는 선생님이라고 상상하며 실전 연습을 진행해봅시다. 엑셀 파일에는 다음과 같은 구성의 학생 데이터가 들어 있습니다.
[Note] 실습의 편의를 위해 커서의 힘을 빌리겠습니다.

엑셀로 정리한 학생 데이터를 딕셔너리로 불러오기
bit.ly/4nsOMCy에서 엑셀 파일을 다운로드해서 빈 폴더에 넣고 커서로 열어봅시다.

이제 커서를 이용해서 엑셀 파일의 내용을 딕셔너리로 불러오는 방법에 대해 질문해보겠습니다. 파일의 내용을 커서가 알 수 있도록 파일 이름을 언급하여 질문하겠습니다.
[나] : 학생_데이터.xlsx 파일을 파이썬의 딕셔너리로 불러오려면 어떻게 해야 할까?

[커서] :

커서는 다양한 파일을 처리하는 방법을 여러 개 알고 있으므로 여러 방법을 제안하고 추천할 것입니다. 그러면 가장 추천하는 방법으로 해달라고 하면 됩니다. 이때 구체적인 요구사항을 조금만 더 첨가합시다. 앞에서 배운대로면 엑셀 파일을 불러와 엑셀의 열 이름이 딕셔너리의 각각의 키가 되면 되고, 행의 값들이 값이 되면 됩니다.
[나] : 엑셀의 열 이름이 딕셔너리의 키, 행의 값이 값이 되면 돼. 그렇게 해주는 코드를 너가 가장 추천하는 방법으로 작성해줘.
[커서] : 네, 가장 추천하는 방법인 pandas를 사용해서 Excel 파일을 딕셔너리로 변환하는 코드를 작성해드리겠습니다.
...생략...
그러면 커서는 코드를 작성한 후 폴더에 파일까지 만들어 줄 것입니다. 어쩌면 실행까지 해줄 수 있습니다.

만약 실행이 되지 않았거나 결과가 자세히 보이지 않는다면 이렇게 이야기하면 됩니다.
[나] : 터미널에서 excel_to_dict.py의 실행 결과를 보고 싶어.
[실행 결과]
Excel 데이터를 딕셔너리로 변환 완료!
총 10개의 행이 있습니다.
첫 번째 행 데이터:
{'학번': 2024001, '이름': '김민준', '성별': '남', '나이': 20, '학년': 2, '전공': '컴퓨터공학', '평점': 3.8, '출석률': 95, '연락처': '010-1234-5678', '주소': '서울시 강남구'}
전체 데이터:
행 1: {'학번': 2024001, '이름': '김민준', '성별': '남', '나이': 20, '학년': 2, '전공': '컴퓨터공학', '평점': 3.8, '출석률': 95, '연락처': '010-1234-5678', '주소': '서울시 강남구'}
행 2: {'학번': 2024002, '이름': '이서연', '성별': '여', '나이': 19, '학년': 1, '전공': '경영학', '평점': 4.0, '출석률': 98, '연락처': '010-2345-6789', '주소': '서울시 서초구'}
...생략...
행 10: {'학번': 2024010, '이름': '송현우', '성별': '남', '나이': 19, '학년': 1, '전공': '물리학', '평점': 3.9, '출석률': 91, '연락처': '010-0123-4567', '주소': '경기도 용인시'}
그러면 오른쪽에 커서가 출력을 위한 코드 실행을 대신해 줄 것입니다. 실행 결과는 엑셀을 딕셔너리로 변환하여 잘 출력해주고 있습니다.
여기서 여러분이 '이상하다' 느낄 수도 있습니다. 왜냐하면 문법서에서 코드 작성을 직접하고 있지 않기 때문이죠. 하지만 중요한 건 여러분이 딕셔너리의 개념을 알고 있고, 이를 통해 엑셀이라는 전혀 다른 형식의 파일이 딕셔너리로 전환하기에 적합하다는 걸 알았다는 겁니다.

문법을 공부하는 책에서 코드를 직접 입력하지 않는 실습을 진행하니 좀 이상하게 느껴질 수도 있겠지만 요즘은 프로그래밍 언어의 문법이나 개념을 정확하게 알고 있다면 굳이 코드를 직접 작성할 필요가 없는 시대입니다. 개념을 알고 있다면 위 그림이 머릿속에 자연스럽게 받아들여질 것입니다. 실행 결과를 자세히 보려면 다음 그림을 참고하여 확인해보세요.

채팅을 보낸 이후 아래쪽 패널을 열면 커서가 알아서 실행해준 코드의 실행 결과가 보일 것입니다. 이렇게 엑셀 파일을 파이썬으로 읽어올 수 있다면 이후에는 파이썬으로 다양한 작업들을 해볼 수 있겠죠? 예를 들어 이 데이터를 이용해서 대시보드 웹 페이지를 만들거나 데이터 분석을 진행할 수도 있습니다. 아직 분석에 대해 공부한 내용은 없지만 커서에 이렇게 이야기해봅시다.
[나] : 읽어들인 딕셔너리 데이터를 통해 데이터 통계 분석을 간단히 진행해줘.
[커서] : Excel에서 읽어들인 학생 데이터를 이용해서 통계 분석을 진행해보겠습니다. 다양한 통계 정보를 제공하는 프로그램을 만들어보겠습니다.

결과를 보면 놀랍습니다. 엑셀 파일을 읽어 딕셔너리로 읽어들인 데이터의 통계 분석 결과를 알려주고 있네요. 이처럼 파이썬으로 데이터를 읽어들이면 다양한 작업을 해볼 수 있는 기회가 생깁니다. 물론 그렇게 하려면 공부해야 할 것들이 많습니다. 하지만 그럴 수 있는 가능성을 여러분에게 보여주고 싶었습니다. 이 실습을 통해 딕셔너리의 유용함이 조금이라도 느껴졌기 바랍니다.
