
복잡한 숫자와 딱딱한 차트로 가득한 부동산 데이터, 보고만 있어도 머리가 지끈거리신 경험이 있으신가요? 수많은 통계 자료 속에서 의미 있는 흐름을 읽어내는 것은 전문가에게도 쉽지 않은 일입니다.
만약 부동산 시장 동향을 매일 아침 확인하는 날씨 예보처럼 쉽고 직관적으로 파악할 수 있다면 어떨까요? 이제 기술을 통해, 누구나 방송국 수준의 부동산 브리핑을 매일 아침 자동으로 받아보는 시대를 열 수 있습니다. 이 글에서는 ‘한국부동산원_주간아파트동향 조회 서비스’의 공공데이터를 활용해 데이터 수집부터 영상 제작까지, 모든 과정을 엮어내는 ‘4단계 자동화 파이프라인’의 핵심 비법을 공개합니다.
1. 첫 번째 비법: 데이터를 '날씨 지도'처럼 시각화하기
자동화 파이프라인의 첫 단계는 딱딱한 숫자 데이터를 날씨 예보의 '기상도'처럼 한눈에 들어오는 시각 자료로 변환하는 것입니다. API를 통해 받은 원본 JSON 데이터는 먼저 Pandas와 같은 라이브러리로 분석하기 쉽게 정제하고, 이후 지도 위에 직관적으로 표현하는 것이 핵심입니다.
Geopandas는 지리 정보 데이터를 다루는 데 강력하고, Folium은 인터랙티브 웹 지도를 만드는 데 탁월합니다. 이러한 도구를 사용해 전국 지도를 그린 뒤, 각 지역의 아파트 가격 상승률에 따라 색상을 입힙니다. 예를 들어, 가격이 오른 지역은 붉은색 계열로, 내린 지역은 푸른색 계열로 표현하면 누구나 지도만 보고도 전국 부동산 시장의 흐름을 즉시 파악할 수 있습니다. 여기에 Matplotlib이나 Seaborn 같은 도구로 주간 추세 그래프를 함께 생성하면 데이터의 설득력을 더욱 높일 수 있습니다.
이렇게 완성된 '부동산 기상도'는 파이프라인의 다음 단계로 전달되어 생명을 얻게 됩니다.
2. 두 번째 비법: 생성형 AI를 '뉴스 앵커'로 만들기
시각 자료가 준비되었다면, 이제 이 자료를 설명할 전문 앵커가 필요합니다. 생성형 AI, 즉 LLM(대규모 언어 모델)이 바로 그 역할을 수행합니다. 수집된 데이터를 바탕으로 LLM은 마치 날씨 예보 앵커가 말하는 듯한 자연스러운 톤의 대본을 자동으로 생성합니다.
AI가 실제로 어떤 결과물을 만드는지 다음 예시를 통해 체감해 보세요.
"이번 주 수도권 부동산 기상도는 '맑음'입니다. 서울 매매가는 전주 대비 0.05% 상승하며..."
이렇게 생성된 대본은 음성 합성(TTS, Text-to-Speech) 기술을 통해 실제 아나운서의 목소리로 변환됩니다. Google Text-to-Speech, Naver CLOVA Voice는 물론, 최근 각광받는 ElevenLabs 같은 서비스를 활용하면 사람이 직접 녹음하지 않아도 전문적인 느낌의 음성 파일을 손쉽게 만들 수 있습니다.
이제 시각 자료와 목소리가 모두 준비되었습니다. 마지막 관문은 이 둘을 하나의 완벽한 영상으로 엮어내는 자동 편집 단계입니다.
3. 세 번째 비법: 코딩 몇 줄로 '영상 편집' 자동화하기
앞서 만든 시각 자료(이미지)와 음성 파일(오디오)을 합쳐 하나의 영상으로 만드는 과정 역시 코드를 통해 완벽하게 자동화할 수 있습니다. 이 자동화의 핵심은 바로 파이썬 라이브러리인 MoviePy입니다.
MoviePy는 일종의 '코드 기반 영상 편집 스튜디오' 역할을 합니다. 이 라이브러리를 사용하면 배경 영상 위에 '부동산 기상도'와 차트를 올리고, 생성된 AI 앵커의 음성을 입히는 복잡한 편집 과정을 단 몇 줄의 코드로 간단하게 처리할 수 있습니다. 강력한 FFmpeg 엔진을 기반으로 동작하는 MoviePy는 반복적인 편집 지옥에서 벗어나 콘텐츠 기획이라는 본질에 집중하게 만드는 혁신입니다.
4. 네 번째 비법: '가상 인간 아나운서'로 전문성 더하기
단순히 이미지와 음성을 합치는 것을 넘어, 한 차원 높은 수준의 영상 콘텐츠를 제작할 수도 있습니다. 최신 AI 기술을 활용하면 가상 인간 아나운서가 직접 데이터를 리포트하는 전문 뉴스 영상을 만들 수 있습니다.
DeepBrain AI나 Synthesia와 같은 서비스가 대표적입니다. 이 서비스들은 우리가 생성한 대본을 입력하면, 가상 아나운서가 자연스러운 표정과 제스처로 해당 내용을 브리핑하는 영상을 만들어줍니다. 이는 단순히 전문성을 더하는 것을 넘어, 콘텐츠에 일관된 ‘브랜드 페르소나’를 구축하여 시청자의 신뢰를 확보하는 강력한 전략적 선택이 될 수 있습니다.
결론 (Conclusion)
공공데이터, 데이터 시각화, 생성형 AI, 그리고 영상 합성 자동화 기술. 이 네 가지를 파이프라인으로 연결하는 것은 단순한 효율성 향상을 넘어, 데이터 기반 콘텐츠를 조직의 핵심 전략적 자산으로 전환하는 첫걸음입니다.
이 시스템을 통해 매주 목요일 한국부동산원의 데이터가 업데이트될 때마다 자동으로 새로운 분석이 담긴 유튜브 쇼츠나 리포트 영상을 배포할 수 있습니다. 이제 기술은 복잡한 정보를 소비하는 방식을 완전히 바꾸고 있습니다.
부동산 시장을 넘어, 당신의 관심 분야에서는 어떤 데이터를 이와 같은 '자동화 콘텐츠'로 만들어볼 수 있을까요?

부동산 시장의 데이터를 수집하여 시각화하고, AI 대본 생성 및 영상 편집까지 한 번에 수행하는 '부동산 날씨 예보 자동 생성 시스템'의 전체 구현 가이드를 정리해 드립니다.
🏗️ 시스템 아키텍처
이 시스템은 네 가지 핵심 모듈로 구성됩니다.
- 데이터 수집: 공공데이터 포털 API를 통해 주간 아파트 실거래가 및 동향 파악.
- 데이터 시각화: 수집된 데이터를 바탕으로 히트맵(지도) 및 통계 차트 생성.
- AI 콘텐츠 생성: OpenAI GPT-4로 대본을 쓰고, TTS로 음성 파일 생성.
- 영상 자동 편집: 생성된 이미지와 음성을 결합하여 최종 MP4 영상 제작.
⚙️ 0. 환경 설정 및 라이브러리
먼저 프로젝트에 필요한 도구들을 설치합니다.
# 필수 라이브러리 설치
pip install pandas requests matplotlib seaborn folium openai moviepy python-dotenv
.env 파일을 생성하여 API 키를 관리합니다.
PUBLIC_DATA_API_KEY=your_api_key
OPENAI_API_KEY=your_openai_key
📊 1. 데이터 수집 및 전처리
공공데이터 API로부터 데이터를 가져와 분석 가능한 형태로 가공합니다.
import requests
import pandas as pd
import os
from dotenv import load_dotenv
load_dotenv()
class RealEstateCollector:
def __init__(self):
self.api_key = os.getenv('PUBLIC_DATA_API_KEY')
self.url = "http://openapi.molit.go.kr/OpenAPI_ToolInstallPackage/service/rest/RTMSOBJSvc/getRTMSDataSvcAptTradeDev"
def fetch_data(self, lawd_cd="11110", deal_ymd="202401"):
params = {
'serviceKey': self.api_key,
'LAWD_CD': lawd_cd,
'DEAL_YMD': deal_ymd,
}
# 실제 환경에서는 xml을 dict로 변환하는 과정이 필요합니다 (xmltodict 활용 권장)
# 여기서는 예시를 위해 간략화된 구조를 사용합니다.
response = requests.get(self.url, params=params)
return response.text # XML 응답
🎨 2. 데이터 시각화 (날씨 지도 생성)
수집된 데이터를 시각적으로 표현합니다. 지도는 Folium을, 통계는 Matplotlib을 사용합니다.
import matplotlib.pyplot as plt
import seaborn as sns
def create_trend_chart(df, save_path='trend.png'):
plt.figure(figsize=(10, 6))
sns.barplot(data=df, x='region', y='price_change')
plt.title('Weekly Real Estate Trend')
plt.savefig(save_path)
plt.close()
🎙️ 3. AI 대본 생성 및 음성 합성 (TTS)
OpenAI GPT-4가 데이터를 분석하여 뉴스 대본을 작성하고, 이를 음성으로 바꿉니다.
from openai import OpenAI
client = OpenAI()
def generate_script(stats_summary):
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "너는 전문 부동산 뉴스 캐스터야. 친근한 날씨 예보 스타일로 대본을 써줘."},
{"role": "user", "content": f"이번 주 통계: {stats_summary}"}
]
)
return response.choices[0].message.content
def text_to_speech(text, output_file="voice.mp3"):
response = client.audio.speech.create(
model="tts-1",
voice="alloy", # 전문적인 목소리
input=text
)
response.stream_to_file(output_file)
🎬 4. 영상 자동 편집
MoviePy를 사용하여 배경 이미지(지도/차트) 위에 음성을 입히고 자막을 추가합니다.
from moviepy.editor import ImageClip, AudioFileClip
def create_video(image_path, audio_path, output_path="final_report.mp4"):
audio = AudioFileClip(audio_path)
# 이미지 길이를 오디오 길이에 맞춤
clip = ImageClip(image_path).set_duration(audio.duration)
clip = clip.set_audio(audio)
clip.write_videofile(output_path, fps=24)
🚀 5. 통합 실행 모듈 (Main)
def main():
# 1. 데이터 수집
data = {"total_avg": "5.4억", "top_region": "서울 강남", "trend": "상승"}
# 2. 시각화
create_trend_chart(pd.DataFrame(...), "chart.png")
# 3. 대본 및 음성 생성
script = generate_script(data)
text_to_speech(script, "voice.mp3")
# 4. 최종 영상 제작
create_video("chart.png", "voice.mp3", "real_estate_weather.mp4")
print("✨ 부동산 예보 영상 제작 완료!")
if __name__ == "__main__":
main()
💡 팁: 더 발전시키려면?
- 자동 업로드: google-api-python-client를 활용해 생성된 영상을 유튜브 쇼츠에 자동 업로드할 수 있습니다.
- 스케줄링: GitHub Actions나 Airflow를 사용하여 매주 월요일 아침에 자동으로 실행되게 만드세요.
이 가이드의 특정 부분(예: 지도 시각화 상세 코드나 API 연동 실패 대응)에 대해 더 자세히 알고 싶으신가요?
앞서 구축한 시스템의 마지막 단계인 유튜브 쇼츠 자동 업로드 기능을 구현해 보겠습니다. 이를 위해서는 google-api-python-client, google-auth-oauthlib, google-auth-httplib2 라이브러리가 필요합니다.
🔑 사전 준비 사항
- Google Cloud Console에서 프로젝트를 생성합니다.
- YouTube Data API v3를 활성화합니다.
- OAuth 2.0 클라이언트 ID를 생성하고 client_secrets.json 파일을 다운로드하여 프로젝트 폴더에 저장합니다.
- 필요 라이브러리 설치:
pip install google-api-python-client google-auth-oauthlib google-auth-httplib2
🎥 유튜브 쇼츠 자동 업로드 모듈
유튜브 쇼츠는 별도의 API가 있는 것이 아니라, **세로형 영상(9:16)**이면서 제목이나 설명에 #Shorts가 포함되면 자동으로 쇼츠로 분류됩니다.
import os
import datetime
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload
from google.auth.transport.requests import Request
import pickle
class YouTubeUploader:
def __init__(self, client_secrets_file="client_secrets.json"):
self.scopes = ["https://www.googleapis.com/auth/youtube.upload"]
self.client_secrets_file = client_secrets_file
self.youtube = self._get_authenticated_service()
def _get_authenticated_service(self):
"""OAuth2 인증 및 서비스 빌드"""
creds = None
# 기존 인증 토큰 로드
if os.path.exists("token.pickle"):
with open("token.pickle", "rb") as token:
creds = pickle.load(token)
# 유효한 인증 정보가 없으면 새로 인증
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
self.client_secrets_file, self.scopes)
creds = flow.run_local_server(port=0)
# 다음 실행을 위해 인증 정보 저장
with open("token.pickle", "wb") as token:
pickle.dump(creds, token)
return build("youtube", "v3", credentials=creds)
def upload_shorts(self, video_path, title, description):
"""영상을 유튜브 쇼츠로 업로드"""
# 쇼츠 분류를 위해 제목/설명에 #Shorts 포함
full_title = f"{title} #Shorts"
full_description = f"{description}\n\n#Shorts #부동산날씨 #부동산동향"
body = {
"snippet": {
"title": full_title,
"description": full_description,
"tags": ["부동산", "아파트시세", "Shorts"],
"categoryId": "22" # 'People & Blogs' 카테고리
},
"status": {
"privacyStatus": "public", # 공개 설정 (public, private, unlisted)
"selfDeclaredMadeForKids": False
}
}
# 파일 업로드 설정
media = MediaFileUpload(
video_path,
mimetype="video/mp4",
resumable=True
)
print(f"🚀 유튜브 업로드 시작: {full_title}")
request = self.youtube.videos().insert(
part="snippet,status",
body=body,
media_body=media
)
response = None
while response is None:
status, response = request.next_chunk()
if status:
print(f"📤 업로드 중... {int(status.progress() * 100)}%")
print(f"✅ 업로드 완료! 영상 ID: {response['id']}")
return response['id']
# ==========================================
# 통합 실행 예시 (Main Pipeline에 추가)
# ==========================================
if __name__ == "__main__":
# 이전 단계에서 생성된 파일 경로
video_to_upload = "output/real_estate_weather.mp4"
if os.path.exists(video_to_upload):
uploader = YouTubeUploader()
today = datetime.date.today().strftime("%Y-%m-%d")
uploader.upload_shorts(
video_path=video_to_upload,
title=f"[{today}] 이번 주 부동산 날씨 예보",
description="전국 주요 지역 아파트 매매 동향 및 시세 분석 결과입니다."
)
💡 주의 및 팁
- 쇼츠 규격: 영상은 반드시 1080x1920 (9:16) 또는 1:1 비율이어야 하며, 길이는 60초 이내여야 합니다. (이전 Visualizer 클래스에서 차트 생성 시 figsize 조절 필요)
- API 할당량: YouTube API의 업로드 할당량은 하루에 약 1,600유닛(영상 1개당 약 1,600소모)입니다. 즉, 무료 계정으로는 하루에 영상 1~2개 정도만 자동 업로드가 가능합니다.
- 인증 정보 유지: token.pickle 파일이 생성되면 이후에는 브라우저 로그인 창 없이 자동으로 인증이 진행됩니다.
- 세로 영상 팁: Matplotlib으로 차트를 그릴 때 가로가 아닌 세로로 길게 배치하거나, MoviePy에서 배경을 세로형(9:16)으로 설정하고 그 위에 차트를 얹는 방식으로 편집해야 완벽한 쇼츠가 됩니다.
부동산 날씨 예보 시스템에서 가장 중요한 지도 시각화(Heatmap) 기능을 상세하게 구현해 보겠습니다. 이 코드는 단순히 점을 찍는 것을 넘어, 가격 변동에 따라 색상이 변하고 클릭 시 정보가 표시되는 인터랙티브 지도를 생성합니다.
🗺️ 지도 시각화 상세 모듈 (Folium 활용)
이 모듈은 위경도 데이터를 기반으로 전국 지도를 그리고, 이를 영상에 쓰기 위해 이미지 파일(.png)로 변환하는 기능까지 포함합니다.
import folium
from folium import plugins
import pandas as pd
import os
import time
from selenium import webdriver # HTML을 이미지로 저장하기 위해 필요
class RealEstateMap:
def __init__(self):
# 주요 지역 좌표 데이터 (실제 서비스 시 상세 위경도 DB 활용)
self.region_coords = {
'서울': [37.5665, 126.9780], '경기': [37.4138, 127.5183],
'인천': [37.4563, 126.7052], '부산': [35.1796, 129.0756],
'대구': [35.8714, 128.6014], '대전': [36.3504, 127.3845],
'광주': [35.1595, 126.8526], '울산': [35.5384, 129.3114]
}
def create_interactive_map(self, df, save_name="map.html"):
"""Folium을 이용한 인터랙티브 지도 생성"""
# 1. 한국 중심 좌표로 지도 시작
m = folium.Map(location=[36.5, 127.5], zoom_start=7, tiles='cartodbpositron')
# 2. 데이터 시각화 (CircleMarker 활용)
for _, row in df.iterrows():
region = row['region']
if region in self.region_coords:
# 상승/하락에 따른 색상 결정
color = '#FF4B4B' if row['change_rate'] > 0 else '#4B89FF'
radius = abs(row['change_rate']) * 100 + 10 # 변동폭에 따른 크기
folium.CircleMarker(
location=self.region_coords[region],
radius=radius,
popup=f"<b>{region}</b><br>평균가: {row['avg_price']}억<br>변동률: {row['change_rate']}%",
color=color,
fill=True,
fill_color=color,
fill_opacity=0.6
).add_to(m)
# 지역명 라벨 추가
folium.map.Marker(
self.region_coords[region],
icon=folium.DivIcon(html=f'<div style="font-size: 10pt; font-weight:bold;">{region}</div>')
).add_to(m)
m.save(save_name)
return save_name
def save_map_as_png(self, html_path, output_path="map.png"):
"""Selenium을 사용하여 HTML 지도를 이미지로 변환"""
options = webdriver.ChromeOptions()
options.add_argument('--headless') # 창 없이 실행
driver = webdriver.Chrome(options=options)
# 로컬 파일 경로 설정
abs_path = "file://" + os.path.abspath(html_path)
driver.get(abs_path)
time.sleep(2) # 지도 로딩 대기
driver.set_window_size(1080, 1920) # 쇼츠 규격(세로형)으로 캡처
driver.save_screenshot(output_path)
driver.quit()
return output_path
🎨 시각화 퀄리티를 높이는 포인트
- 컬러 스케일(Color Scale): 단순히 빨강/파랑이 아니라 branca.colormap을 사용하면 변동률에 따른 부드러운 그라데이션 표현이 가능합니다.
- 레이어 컨트롤: 매매가 레이어와 전세가 레이어를 분리하여 사용자가 선택해서 볼 수 있게 만들 수 있습니다.
- 세로형 레이아웃: 유튜브 쇼츠 영상을 위해 driver.set_window_size(1080, 1920) 설정을 적용했습니다. 이렇게 하면 지도가 세로로 길게 캡처되어 쇼츠 화면에 꽉 차게 들어갑니다.
🛠️ 추가 설치 필요 (이미지 변환용)
HTML 지도를 영상 소스인 이미지로 바꾸려면 Chrome 브라우저와 ChromeDriver가 필요합니다.
pip install selenium
이제 이 지도 모듈을 이전에 만든 Visualizer 클래스 대신 넣거나 보완하면, 훨씬 전문적인 "지도 기반 부동산 뉴스" 영상을 자동으로 생산할 수 있습니다.
서울시 구 단위의 상세 경계선을 지도에 넣기 위해서는 GeoJSON 데이터가 필요합니다. GeoJSON은 지리적 형상을 JSON 형식으로 저장한 데이터로, 이를 이용하면 지도 위에 각 구의 경계선을 그리고 색상을 채울 수 있습니다.
파이썬의 folium.Choropleth 기능을 사용하여 서울 구 단위 경계선을 시각화하는 상세 코드를 정리해 드립니다.
1. 서울 구 단위 GeoJSON 데이터 준비
인터넷에서 공개된 서울 구 단위 GeoJSON 파일을 사용합니다. (가장 유명한 데이터셋은 southkorea/seoul-maps입니다.)
2. 상세 구현 코드
import folium
import json
import requests
import pandas as pd
def create_seoul_boundary_map(df, output_path="seoul_map.html"):
"""
df: '구이름'과 '변동률' 혹은 '가격' 데이터가 담긴 DataFrame
"""
# 1. 서울 구 단위 GeoJSON 데이터 로드 (오픈 데이터 활용)
# 직접 파일을 다운로드받아 경로를 지정해도 됩니다.
geo_url = 'https://raw.githubusercontent.com/southkorea/seoul-maps/master/kostat/2013/json/seoul_municipalities_geo_simple.json'
geo_json = requests.get(geo_url).json()
# 2. 지도 기본 설정 (서울 중심)
m = folium.Map(location=[37.5665, 126.9780], zoom_start=11, tiles='cartodbpositron')
# 3. Choropleth (단계 구분도) 추가
# 이 기능이 구 경계선을 그리고 데이터에 따라 색상을 채워줍니다.
folium.Choropleth(
geo_data=geo_json, # 경계선 데이터
name='choropleth',
data=df, # 시각화할 데이터프레임
columns=['region', 'price'], # 데이터프레임의 [구이름, 데이터값] 컬럼
key_on='feature.properties.name', # GeoJSON에서 구 이름이 들어있는 키 (중요!)
fill_color='YlOrRd', # 색상 팔레트 (Yellow-Orange-Red)
fill_opacity=0.7,
line_opacity=0.2,
legend_name='평균 매매가 (억원)'
).add_to(m)
# 4. 각 구 중앙에 이름 라벨 표시 (선택 사항)
for feature in geo_json['features']:
name = feature['properties']['name']
# 구별 중심점 좌표 (실제 데이터에 따라 조정 필요)
# 여기선 예시로 구 이름을 툴팁처럼 보여주는 방식 사용
folium.GeoJson(
feature,
style_function=lambda x: {'fillColor': '#ffffff00', 'color': '#00000000'},
tooltip=name
).add_to(m)
m.save(output_path)
return output_path
# --- 실행 예시 ---
data = {
'region': ['강남구', '서초구', '송파구', '강동구', '종로구', '마포구'],
'price': [25.5, 23.8, 19.2, 12.5, 11.0, 15.6]
}
sample_df = pd.DataFrame(data)
create_seoul_boundary_map(sample_df)
3. 핵심 포인트 설명
- key_on 설정: GeoJSON 파일 내부의 구조를 확인해야 합니다. 보통 서울 데이터는 feature.properties.name에 '강남구', '서초구' 같은 이름이 들어있습니다. 이 값과 내 데이터프레임(df)의 구 이름이 정확히 일치해야 색상이 칠해집니다.
- 색상 스케일 (fill_color):
- YlOrRd (노랑-주황-빨강): 가격 상승이나 높은 가격대 표시 시 적합
- RdYlBu (빨강-노랑-파랑): 상승(+)과 하락(-) 변동률을 동시에 표시할 때 적합
- 데이터 정제: 공공데이터 API에서 가져온 지역명은 '서울특별시 강남구' 형태일 수 있습니다. GeoJSON의 이름과 맞추기 위해 '강남구'와 같이 문자열을 전처리하는 과정이 필수입니다.
4. 쇼츠 영상 적용 팁
유튜브 쇼츠용으로 만들 때는 지도를 너무 넓게 잡지 말고, 특정 핫플레이스(예: 강남 3구)를 줌인(Zoom-in) 하도록 location과 zoom_start 값을 조정하면 시청자들의 시선을 더 잘 끌 수 있습니다.










'IT 개발,관리,연동,자동화' 카테고리의 다른 글
| 광고 기반 리워드형 SaaS 호스팅 비즈니스 모델: "Ad-Powered Cloud" (0) | 2026.01.22 |
|---|---|
| 똑똑한 AI 비서, 쓰기도 전에 'API 키'의 미로에서 길을 잃다 (0) | 2026.01.21 |
| 주말엔 뭐 볼까!? : '이주의 박스 오피스 기상도' 기획 (0) | 2026.01.18 |
| 문법의 시대에서 의도의 시대로: AI가 소프트웨어를 '살아있는 유기체'로 만드는 법 (0) | 2026.01.15 |
| 챗봇을 넘어 '진짜 내 PC 동료'로, 클로드 코워크(Claude Cowork)의 충격적인 활용법 5가지 (1) | 2026.01.14 |