HTML·이미지·PDF 저장
완성된 차트를 fig.show()로 보는 것은 개발 단계에서만 쓸 수 있습니다. 발표 자료에 넣거나, 보고서에 첨부하거나, 팀원에게 공유하려면 파일로 저장해야 합니다. Plotly는 여러 형식의 저장을 지원합니다.
HTML 저장
가장 강력한 옵션입니다. 인터랙티브한 기능(줌, 툴팁, 범례 토글, 애니메이션)이 그대로 보존됩니다. 파일 하나로 공유하면 웹 브라우저에서 바로 열 수 있습니다.
# 새 파일: save_html.pyimport plotly.express as pxdf = px.data.gapminder()fig = px.scatter( df, x="gdpPercap", y="lifeExp", animation_frame="year", animation_group="country", size="pop", color="continent", hover_name="country", log_x=True, range_x=[200, 120000], range_y=[25, 90], title="GDP vs 기대수명 애니메이션")# HTML 저장fig.write_html("gapminder_animation.html")print("저장 완료: gapminder_animation.html")
저장된 HTML 파일을 더블클릭하면 웹 브라우저에서 열립니다. 애니메이션도 그대로 작동합니다.
HTML 크기를 줄이려면 include_plotlyjs="cdn"을 사용합니다. Plotly 라이브러리를 파일에 포함하지 않고 CDN에서 가져오도록 합니다. 파일 크기가 수십 MB에서 수십 KB로 줄어듭니다. 단, 인터넷 연결이 없는 환경에서는 열리지 않습니다.
# 파일 크기 최소화 (인터넷 연결 필요)fig.write_html("gapminder_small.html", include_plotlyjs="cdn")# 오프라인에서도 열 수 있도록 (파일 크기 큼)fig.write_html("gapminder_offline.html", include_plotlyjs=True)
이미지 저장 (PNG, SVG, JPEG)
정적 이미지 저장은 fig.write_image()를 사용합니다. 이 기능을 쓰려면 kaleido 패키지가 필요합니다.
pip install kaleido
# 새 파일: save_image.pyimport plotly.express as pxdf = px.data.iris()fig = px.scatter( df, x="sepal_width", y="sepal_length", color="species", title="붓꽃 데이터 산점도")# PNG 저장 (기본)fig.write_image("iris_scatter.png")# 고해상도 PNG (발표용)fig.write_image( "iris_scatter_hd.png", width=1920, height=1080, scale=2 # 2배 해상도 (Retina 디스플레이용))# SVG 저장 (무손실, 벡터)fig.write_image("iris_scatter.svg")# JPEG 저장 (파일 크기 작음)fig.write_image("iris_scatter.jpg")
scale 파라미터는 해상도를 배수로 높입니다. scale=2이면 실제 픽셀 수가 2배가 되어 선명한 이미지를 얻을 수 있습니다. 발표 화면이나 대형 포스터에 사용할 때 유용합니다.
PDF 저장
fig.write_image("chart.pdf")로 PDF를 만들 수 있습니다. 논문이나 보고서에 고품질 벡터 그래픽으로 첨부할 때 사용합니다.
# 새 파일: save_pdf.pyimport plotly.express as pxfrom plotly.subplots import make_subplotsimport plotly.graph_objects as go# 발표 자료용 대시보드 (고해상도)fig = make_subplots( rows=1, cols=2, subplot_titles=("분기별 매출", "대륙별 기대수명"))fig.add_trace( go.Bar( x=["1Q", "2Q", "3Q", "4Q"], y=[120, 145, 132, 178], marker_color="#1B3A5C" ), row=1, col=1)df = px.data.gapminder().query("year == 2007")continent_avg = df.groupby("continent")["lifeExp"].mean().reset_index()fig.add_trace( go.Bar( x=continent_avg["continent"], y=continent_avg["lifeExp"], marker_color="#4A90D9" ), row=1, col=2)fig.update_layout( title_text="캡스톤 프로젝트 발표 자료", showlegend=False, height=500)# PDF 저장 (A4 가로 비율)fig.write_image( "capstone_dashboard.pdf", width=1123, # A4 가로 (96 DPI 기준) height=794 # A4 세로)print("PDF 저장 완료: capstone_dashboard.pdf")
JSON 직렬화
차트를 JSON 형식으로 변환하면 나중에 다시 불러와서 수정하거나, 웹 서버에서 전송할 수 있습니다.
# 새 파일: save_json.pyimport plotly.express as pximport jsondf = px.data.iris()fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species")# JSON 문자열로 변환fig_json = fig.to_json()print(type(fig_json)) # str# 딕셔너리로 변환fig_dict = fig.to_dict()print(type(fig_dict)) # dict# JSON 파일로 저장with open("iris_scatter.json", "w", encoding="utf-8") as f: f.write(fig_json)# JSON 파일에서 불러오기import plotly.io as piowith open("iris_scatter.json", "r", encoding="utf-8") as f: fig_loaded = pio.from_json(f.read())fig_loaded.show()
저장 형식 비교
| 형식 | 인터랙티브 | 파일 크기 | 용도 |
|---|---|---|---|
.html |
O | 크다 (수 MB) | 웹 공유, 포트폴리오 |
.html (CDN) |
O | 작다 (수 KB) | 인터넷 연결 환경 |
.png |
X | 중간 | 보고서, 발표 슬라이드 삽입 |
.svg |
X | 작다 (벡터) | 논문, 인쇄 |
.pdf |
X | 작다 (벡터) | 논문 첨부, 고품질 인쇄 |
.jpg |
X | 가장 작다 | SNS, 빠른 공유 |
.json |
- | 크다 | 차트 재사용, API 전송 |
실전: 발표 자료용 고해상도 이미지 저장
중간발표 당일. 지윤은 교수님의 모니터가 4K라는 사실을 떠올렸습니다. 저해상도 이미지를 슬라이드에 넣으면 발표 화면에서 흐릿하게 보일 수 있습니다.
# 새 파일: export_presentation.pyimport plotly.express as pximport plotly.io as pioimport plotly.graph_objects as gofrom plotly.subplots import make_subplots# 학교 템플릿 등록 (custom_template.py에서 정의한 것)# pio.templates.default = "school"quarters = ["1Q", "2Q", "3Q", "4Q"]sales = [120, 145, 132, 178]growth = [None, 20.8, -8.9, 34.8]# 최종 발표용 차트fig = make_subplots( specs=[[{"secondary_y": True}]], subplot_titles=["분기별 매출 및 성장률"])fig.add_trace( go.Bar( x=quarters, y=sales, name="매출 (억원)", marker_color="#1B3A5C" ), secondary_y=False)fig.add_trace( go.Scatter( x=quarters, y=growth, name="성장률 (%)", mode="lines+markers", line=dict(color="#E74C3C", width=3), marker=dict(size=10) ), secondary_y=True)fig.update_yaxes(title_text="매출 (억원)", secondary_y=False)fig.update_yaxes(title_text="성장률 (%)", secondary_y=True)fig.update_layout( title_text="2024년 캡스톤 프로젝트 성과 분석", height=500)# 인터랙티브 HTML (발표 중 직접 조작)fig.write_html( "presentation_main.html", include_plotlyjs=True)# 고해상도 PNG (슬라이드 삽입용)fig.write_image( "presentation_main.png", width=1920, height=1080, scale=2)# PDF (교수님 제출용)fig.write_image( "presentation_main.pdf", width=1123, height=794)print("발표 자료 저장 완료.")print(" - presentation_main.html (인터랙티브)")print(" - presentation_main.png (슬라이드 삽입용)")print(" - presentation_main.pdf (제출용)")
지윤은 세 개의 파일을 모두 저장했습니다. HTML은 발표 중 실시간으로 보여주기 위해, PNG는 슬라이드에 삽입하기 위해, PDF는 교수님 제출용으로.
발표 당일, 지윤의 슬라이드는 화면에서 가장 선명했습니다. 그리고 "이 차트를 직접 만든 건가요?"라는 교수님의 질문에 지윤은 자신 있게 고개를 끄덕였습니다.
PART 03를 마칩니다. 여러 차트를 격자로 배치하고, 브랜드 색상으로 통일하고, 애니메이션으로 데이터에 생동감을 불어넣고, 파일로 저장하는 방법까지 익혔습니다. 이제 발표 자료 수준의 시각화를 만들 수 있습니다.
PART 04에서는 Pandas DataFrame과 Plotly를 연동하는 실전 패턴을 배웁니다.