파이썬 openpyxl 설치부터 새 시트 생성까지, 3개월 삽질 끝에 정리한 진짜 기초

파이썬으로 엑셀 파일을 다루고 싶은데 openpyxl 설치부터 막히셨나요? pip 한 줄이면 설치 끝이고, 코드 5줄이면 새 시트가 만들어집니다.

솔직히 말하면 저도 처음엔 엑셀 자동화라는 말 자체가 막연했거든요. 매일 아침 출근하면 전날 매출 데이터를 엑셀에 정리하는 게 루틴이었는데, 시트 20개를 하나하나 손으로 만들고 있으니까 어느 날 갑자기 현타가 온 거예요. 이걸 왜 수작업으로 하고 있지? 그래서 파이썬을 찾아봤고, openpyxl이라는 라이브러리를 알게 됐습니다.

근데 막상 시작하니까 가상환경이 뭔지, pip가 뭔지, Workbook이랑 Worksheet 차이가 뭔지 헷갈리는 게 한두 가지가 아니더라고요. 3개월 정도 이것저것 부딪히면서 배운 걸 정리해봤어요. 지금 이 글 하나면 설치부터 시트 생성, 데이터 입력까지 한 번에 끝낼 수 있을 거예요.

openpyxl이 뭐길래 이렇게 많이 쓰일까

openpyxl은 파이썬에서 엑셀 2010 이후 형식인 xlsx, xlsm, xltx, xltm 파일을 읽고 쓸 수 있게 해주는 라이브러리예요. 좀 더 쉽게 말하면, 엑셀을 열지 않고도 파이썬 코드만으로 엑셀 파일을 만들고, 수정하고, 저장할 수 있는 도구인 거죠.

제가 처음에 가장 놀랐던 건 읽기와 쓰기 둘 다 된다는 점이었어요. 비슷한 라이브러리인 xlsxwriter는 쓰기만 가능하거든요. 이미 있는 엑셀 파일을 열어서 특정 셀만 수정하고 싶다? 그러면 openpyxl을 쓸 수밖에 없습니다.

원래 이 라이브러리는 PHP 쪽의 PHPExcel이라는 프로젝트에서 영감을 받아 만들어졌대요. 지금은 파이썬 엑셀 자동화 하면 가장 먼저 이름이 올라오는 라이브러리가 됐고, PyPI 기준 최신 버전은 3.1.5입니다. 오픈소스라 무료이고, 순수 파이썬으로 작성돼서 별도 의존성이 거의 없다는 것도 장점이에요.

한 가지 오해를 짚고 넘어가자면, openpyxl은 xls 파일(엑셀 2003 이전 형식)은 지원하지 않아요. 저도 처음에 회사에서 쓰던 오래된 xls 파일을 열려다가 에러가 나서 한참 헤맸거든요. xls를 다뤄야 한다면 xlrd라는 별도 라이브러리가 필요합니다.

pip install openpyxl 설치, 이것만 따라하면 됩니다

설치는 정말 간단해요. 터미널(맥/리눅스)이나 명령 프롬프트(윈도우)를 열고 아래 한 줄만 입력하면 됩니다.

pip install openpyxl

끝이에요. 진짜로. 근데 여기서 막히는 사람이 은근 많거든요. 저도 그랬어요. “pip를 찾을 수 없습니다”라는 에러 메시지를 보고 30분 넘게 구글링했던 기억이 납니다. 이 에러가 뜨는 이유는 대부분 파이썬 설치 시 “Add Python to PATH” 옵션을 체크하지 않았기 때문이에요. 파이썬을 다시 설치하면서 그 체크박스 하나 눌러주면 해결됩니다.

아나콘다를 쓰는 분이라면 openpyxl이 기본으로 포함돼 있을 가능성이 높아요. 확인하려면 파이썬 인터프리터에서 import openpyxl을 입력해보세요. 에러 없이 넘어가면 이미 설치된 겁니다.

💡 꿀팁

가상환경(venv)을 만들어서 설치하는 걸 강력 추천합니다. python -m venv myenv 명령으로 가상환경을 만들고, 활성화한 뒤 pip install openpyxl을 실행하면 프로젝트마다 라이브러리 버전을 독립적으로 관리할 수 있어요. 나중에 프로젝트가 3~4개 쌓이면 이게 왜 중요한지 뼈저리게 느끼게 됩니다.

혹시 엑셀에 이미지도 넣고 싶다면 pillow 라이브러리도 함께 설치해야 해요. pip install pillow 한 줄 추가하면 됩니다. 저는 보고서에 차트 이미지를 삽입할 때 pillow 없이 하려다가 에러를 만났었거든요. 처음부터 같이 깔아두면 편합니다.

설치 확인은 간단해요. 터미널에서 pip show openpyxl을 입력하면 설치된 버전과 경로가 나옵니다. Version: 3.1.5 이런 식으로 뜨면 정상이에요.

Workbook 생성과 기본 시트 구조 이해하기

openpyxl에서 가장 먼저 만나는 개념이 Workbook이에요. 엑셀 파일 하나가 곧 Workbook 하나라고 생각하면 됩니다. 코드로 보면 이렇게 생겼어요.

from openpyxl import Workbook
wb = Workbook()

이 두 줄만 실행해도 메모리 안에 엑셀 파일 하나가 만들어진 거예요. 아직 실제 파일로 저장한 건 아니고, 파이썬이 “엑셀 파일을 만들 준비가 됐어”라고 말하는 상태입니다. 재밌는 건, Workbook을 생성하면 자동으로 “Sheet”라는 이름의 시트가 1개 딸려온다는 거예요.

이 기본 시트에 접근하려면 active 속성을 쓰면 됩니다.

ws = wb.active

이 ws가 바로 워크시트 객체예요. 여기서 제가 처음에 헷갈렸던 부분이 있는데, Workbook은 엑셀 파일 전체이고, Worksheet는 그 안에 들어있는 탭 하나하나를 말하는 거거든요. 엑셀 하단에 보이는 Sheet1, Sheet2 탭 있잖아요. 그게 각각 Worksheet입니다.

⚠️ 주의

wb.active는 기본적으로 인덱스 0번 시트를 반환해요. 근데 시트 순서를 바꾸거나 삭제한 뒤에 active를 호출하면 예상과 다른 시트가 잡힐 수 있습니다. 확실하게 하려면 wb[“시트이름”]으로 직접 지정하는 게 안전합니다. 저도 한 번 active로 잡은 시트에 데이터를 넣었다가, 엉뚱한 시트에 들어가서 데이터를 날린 적이 있어요.

새 시트 만들기, 이름 바꾸기, 삭제까지

자, 여기가 핵심이에요. 새 시트를 만드는 건 create_sheet() 메서드 하나면 됩니다.

ws_new = wb.create_sheet(“매출데이터”)

이렇게 하면 “매출데이터”라는 이름의 시트가 맨 뒤에 추가돼요. 위치를 지정하고 싶다면 두 번째 인자에 인덱스를 넣으면 됩니다. 0을 넣으면 맨 앞, -1을 넣으면 끝에서 두 번째에 들어가요.

ws_first = wb.create_sheet(“첫번째시트”, 0)
ws_second = wb.create_sheet(“끝에서두번째”, -1)

시트 이름을 나중에 바꾸고 싶다면 title 속성을 쓰면 돼요.

ws_new.title = “2024년_매출”

삭제는 remove() 메서드를 사용합니다. 근데 여기서 살짝 직관적이지 않은 게, remove에 시트 이름(문자열)이 아니라 시트 객체를 넣어야 한다는 거예요.

wb.remove(wb[“2024년_매출”])

현재 워크북에 어떤 시트들이 있는지 확인하려면 sheetnames 속성을 쓰면 돼요. print(wb.sheetnames)를 실행하면 [‘Sheet’, ‘첫번째시트’, ‘끝에서두번째’] 이런 식으로 리스트가 출력됩니다.

제가 실무에서 이걸 제일 많이 쓴 건 월별 시트 자동 생성이었어요. for문 돌리면서 create_sheet(“1월”), create_sheet(“2월”) 이렇게 12개를 한 번에 만들 수 있거든요. 손으로 하면 1분, 코드로 하면 0.1초. 이 차이가 쌓이면 엄청납니다.

셀에 데이터 넣고 저장하는 실전 코드

시트를 만들었으면 이제 데이터를 넣어야죠. 셀에 값을 넣는 방법은 크게 두 가지예요.

첫 번째는 키 방식. ws[“A1”] = “이름” 이렇게 엑셀에서 보는 것처럼 셀 주소를 직접 지정하는 거예요. 직관적이라 간단한 작업에 좋습니다.

두 번째는 cell() 메서드 방식. ws.cell(row=1, column=1, value=”이름”) 이렇게 행과 열을 숫자로 지정해요. for문과 조합할 때 이 방식이 훨씬 편합니다. 반복문으로 수백 개 셀에 값을 넣으려면 “A1”, “A2”, “A3” 이런 식으로 문자열을 만드는 것보다 row=i로 숫자를 증가시키는 게 깔끔하잖아요.

행 전체를 한 번에 추가하고 싶다면 append()가 있어요.

ws.append([“홍길동”, 28, “서울”])
ws.append([“김영희”, 34, “부산”])

리스트를 넣으면 자동으로 A, B, C열에 순서대로 배치됩니다. 저는 DB에서 뽑은 데이터를 리스트로 변환한 다음 append로 쭉 넣는 방식을 제일 자주 써요. 한 달 치 데이터 3,000행을 넣는 데 2초도 안 걸리더라고요.

마지막으로 저장. wb.save(“결과물.xlsx”) 한 줄이면 끝이에요. 근데 여기서 중요한 게 하나 있는데, 같은 이름의 파일이 이미 있으면 경고 없이 덮어쓴다는 거예요. 저도 한 번 기존 파일을 날려먹고 나서부터는 항상 파일명에 날짜를 붙이는 습관이 생겼어요.

💬 직접 써본 경험

처음에는 매번 ws[“A1”], ws[“A2”] 이런 식으로 일일이 입력했었어요. 100행쯤 되니까 코드가 눈이 아프더라고요. 그러다 append()를 발견하고 세상이 달라졌습니다. CSV 파일을 읽어서 리스트로 만든 다음, for문 안에서 append만 호출하면 수천 행이 순식간에 들어가거든요. 코드가 10줄에서 3줄로 줄었을 때의 쾌감은 아직도 잊을 수 없어요.

openpyxl vs xlsxwriter vs pandas, 뭘 써야 할까

파이썬 엑셀 라이브러리를 검색하면 openpyxl 말고도 xlsxwriter, pandas가 자주 나와요. 셋 다 엑셀을 다루는 도구지만 성격이 꽤 달라서, 뭘 쓸지 고민되는 분이 많을 거예요.

구분 openpyxl xlsxwriter
읽기 가능 불가
쓰기 가능 가능
기존 파일 수정 가능 불가
차트/서식 기본 지원 강력한 서식 지원

핵심 차이를 한마디로 정리하면 이래요. openpyxl은 읽기+쓰기 둘 다 되는 만능형, xlsxwriter는 쓰기 전용이지만 서식 표현력이 뛰어난 특화형이에요. pandas의 to_excel()은 사실 내부적으로 openpyxl이나 xlsxwriter를 엔진으로 쓰거든요. 데이터프레임을 엑셀로 내보내는 게 목적이라면 pandas가 편하고, 셀 단위로 세밀하게 제어하고 싶다면 openpyxl을 직접 쓰는 게 맞습니다.

제가 내린 결론은 이거예요. 이미 있는 엑셀 파일을 열어서 수정해야 하는 상황이 하나라도 있다면, openpyxl이 답이에요. xlsxwriter는 기존 파일을 아예 열 수 없으니까요. 저처럼 매주 같은 양식의 엑셀 파일을 업데이트하는 업무라면 선택지가 사실상 openpyxl 하나밖에 없었습니다.

📊 실제 데이터

PyPI 기준 openpyxl 최신 버전은 3.1.5(2024년 6월 28일 릴리즈)이며, 파이썬 2와 3 모두 지원합니다. 패키지 용량은 약 250KB 수준으로 가볍고, 필수 외부 의존성 없이 순수 파이썬으로 작성되어 있어서 어떤 환경에서든 설치가 쉬운 편이에요.

한 가지 아쉬운 점도 있어요. openpyxl로 파일을 열고 저장하면 기존 파일에 있던 도형(Shape)이나 매크로가 날아갈 수 있거든요. 공식 문서에서도 “shapes will be lost”라고 명시하고 있어요. 그래서 복잡한 서식이 잔뜩 들어간 엑셀 파일은 원본 백업을 꼭 해두는 습관이 필요합니다.

그리고 보안 관련으로 하나 알아두셔야 할 게, openpyxl은 기본적으로 XML 관련 공격(billion laughs 같은)에 대한 방어가 없어요. 신뢰할 수 없는 출처의 엑셀 파일을 열어야 한다면 defusedxml 라이브러리를 추가로 설치하는 걸 권장하고 있습니다. 회사 내부 파일만 다루는 거라면 크게 걱정할 부분은 아니지만, 외부에서 받은 파일을 처리하는 자동화 시스템이라면 꼭 챙기세요.

실전에서 자주 만나는 실수와 해결법

3개월간 openpyxl을 쓰면서 몇 번이고 같은 실수를 반복했는데, 미리 알았으면 시간을 아꼈을 것들을 정리해볼게요.

첫 번째, 셀에 접근만 해도 셀이 생성된다는 거예요. for문으로 ws.cell(row=i, column=j)를 호출하면, 값을 넣지 않아도 메모리에 셀 객체가 만들어져요. 100×100 범위를 그냥 순회하면 만 개의 빈 셀이 생기는 거죠. 대용량 파일을 다룰 때 메모리가 터지는 원인 중 하나가 바로 이겁니다.

두 번째, save() 할 때 파일이 열려 있으면 에러가 나요. 엑셀에서 해당 파일을 열어놓은 상태로 파이썬에서 저장하려고 하면 PermissionError가 발생합니다. 별것 아닌 것 같은데, 회사에서 자동화 스크립트를 만들 때 이 문제로 스크립트가 멈추는 경우가 꽤 있어요. try-except로 감싸거나, 파일명에 타임스탬프를 붙여서 항상 새 파일로 저장하는 방식으로 우회할 수 있습니다.

세 번째, 수식이 들어간 셀을 읽으면 수식 자체가 나온다는 거예요. =SUM(A1:A10) 같은 수식이 들어간 셀을 읽으면 계산 결과가 아니라 수식 문자열이 반환돼요. 계산된 값을 얻고 싶다면 load_workbook() 호출 시 data_only=True 옵션을 줘야 합니다. 다만 이 값은 엑셀이 마지막으로 계산한 캐시값이라, 파일을 엑셀에서 한 번도 안 열었다면 None이 나올 수도 있어요.

네 번째로, 시트 이름에 특수문자 제한이 있어요. 슬래시(/), 백슬래시(\), 별표(*), 물음표(?), 대괄호([ ]) 같은 문자는 시트 이름에 쓸 수 없습니다. 엑셀 자체의 제한인데, openpyxl에서 이런 이름으로 create_sheet을 호출하면 에러가 터져요. 날짜를 시트 이름에 넣을 때 “2024/01” 대신 “2024-01″로 쓰는 게 안전합니다.

자주 묻는 질문

Q. openpyxl은 파이썬 몇 버전부터 쓸 수 있나요?

openpyxl 3.1.x 버전은 파이썬 3.6 이상에서 동작해요. 다만 최신 기능을 안정적으로 쓰려면 3.8 이상을 권장합니다. 파이썬 2 환경이라면 openpyxl 2.6.x 이하를 써야 해요.

Q. xlsx 말고 csv 파일도 다룰 수 있나요?

아니요, openpyxl은 xlsx/xlsm/xltx/xltm 형식만 지원합니다. csv는 파이썬 내장 모듈인 csv나 pandas로 처리하는 게 맞아요. csv를 xlsx로 변환하고 싶다면, csv로 읽은 데이터를 openpyxl로 다시 써서 저장하면 됩니다.

Q. 하나의 엑셀 파일에 시트를 최대 몇 개까지 만들 수 있나요?

openpyxl 자체에는 시트 수 제한이 없어요. 다만 엑셀 프로그램의 한계는 시스템 메모리에 의존하기 때문에, 현실적으로 수백 개까지는 문제없이 생성 가능합니다. 다만 시트가 너무 많아지면 파일 열기 속도가 느려질 수 있어요.

Q. 기존 엑셀 파일에 새 시트를 추가하려면 어떻게 하나요?

load_workbook()으로 기존 파일을 열고, create_sheet()으로 시트를 추가한 다음, save()로 저장하면 돼요. 이때 save()에 같은 파일명을 넣으면 원본에 덮어씌워지니까, 다른 이름으로 저장하거나 원본을 백업해두는 게 안전합니다.

Q. openpyxl로 만든 파일이 엑셀에서 안 열려요. 왜 그런가요?

파일 확장자를 확인해보세요. save() 할 때 확장자를 .xlsx가 아닌 다른 걸로 지정하면 엑셀이 인식하지 못할 수 있어요. 또 xlsm 형식으로 저장해야 하는데 xlsx로 저장한 경우에도 문제가 생깁니다. 확장자를 .xlsx로 맞추고, 그래도 안 되면 openpyxl 버전을 최신으로 업데이트해보세요.

본 포스팅은 개인 경험과 공개 자료를 바탕으로 작성되었으며, 전문적인 의료·법률·재무 조언을 대체하지 않습니다. 정확한 정보는 해당 분야 전문가 또는 공식 기관에 확인하시기 바랍니다.

openpyxl은 설치 한 줄, 시트 생성 한 줄이면 시작할 수 있는 가벼운 라이브러리예요. 기존 엑셀 파일을 읽고 수정할 수 있다는 점이 다른 라이브러리와 차별되는 가장 큰 강점입니다. 엑셀 반복 작업에 시간을 뺏기고 있다면, 오늘 당장 pip install openpyxl부터 실행해보세요. 처음 한 시간만 투자하면 매주 수 시간을 아낄 수 있거든요.


이 글이 도움이 됐다면 댓글로 어떤 엑셀 작업을 자동화하고 싶은지 알려주세요. 경험을 나누면 서로한테 도움이 되니까요. 공유도 환영합니다.

댓글 남기기