
코딩 하나도 몰랐던 내가,
아파트 실거래가 자동화에 성공!!!
(ChatGPT 고마워^^)
👩💻 "코딩? 나랑 상관없는 줄 알았어요.
근데 ChatGPT랑 하니까 이게 되네요!"
오전에 지하철로 이동하다가
문득 아파트 실거래가를
쉽게 조회할 수 있게
해보고 싶었어요.

토요일 저녁 집에 돌아와서
chatGPT랑 작업했고
아파트 실거래 데이터를
구글시트로 구현하는데 성공했네요.
물론 국토교통부 홈페이지에서
확인하면 되는 일이지만
그래도 구글시트로
바로 가져오면
여러가지 쓸모가
많을 것 같네요.
이 글은 "나도 할 수 있을까?"
고민하고 계신 분들을 위해 써보는 후기
입니다.
코딩 완전 초보였던 제가
ChatGPT의 도움을 받아
구글시트를 통해
국토교통부 API로
아파트 거래동향을
간편하게 조회하는 과정을
공유합니다.

우선 화면 구성은 좀 촌스럽지만
첫 화면이니
차차 개선해 나가면 되겠죠
기본 구성은 간결하게
노란색 입력 부분과
빨간색 실행 버튼만 있습니다.
A1 : 11680 (5자리 행정동 코드) 또는 11 (서울 전체)
C1 : 검색 시작월
D1 : 검색 종료월
7월중 서울시 전체 실거래 데이터를 뽑아볼께요.

11번은 서울 전체를 의미해요.
7월 13일 현재
7월 서울 전체 거래는
231건이 구글시트로 쏙
들어왔습니다.
헉~~
7월 최고가는
압구정동 현대8차
83억!!!

만들게 된 배경은
실거래가 매번 검색하기 귀찮기 때문
부동산이든 주식이든, 데이터는 많지만
내가 원하는 정보만 뽑아보는 건 참 어렵죠.
저는 평소 아파트 실거래가에 관심이 많았는데,
매번 검색하고, 엑셀에 붙여넣고… 너무 비효율적이었어요.
그때 문득 생각난 게 "이거 자동으로 안 되나?"였고,
ChatGPT에게 물어봤습니다.
🤖 Step 1. ChatGPT에게 물어봤어요

제가 처음 던진 질문은 이랬어요.
👉 "국토교통부 아파트 실거래가 OPEN API를 구글시트에서 활용하는 코드 만들어"
그러자 정말… 놀랍게도 필요한 절차부터 코드, 설명까지 다 알려주네요.
"이대로 따라만 하세요" 스타일로요!
인증키 발급 등
사전 준비는 필요하네요구글 계정 (구글시트용)
공공데이터포털 회원가입
실거래가 API 신청
인증키 발급
📜 Step 2. ChatGPT가 알려준 코드 복사 붙여넣기
구글시트 → 확장 프로그램 → 앱스 스크립트
ChatGPT와 코드 만들고 수정하기를
여러번 해서 일단 결과값이 나왔습니다.
다만, 코드에서 인증키만 일부 가렸습니다.
왠지 코드가 초보자 티가 나는것 같아요.
이건 차근차근 업그레이드 해야겠어요.
특히, 행정구역 넣는 부분을
쭉 나열한 부분은 개선해야겠어요
아래 코드에 본인의 인증키만 넣어서
구글시트-확장 프로그램-앱스 스크립트에
넣으면 됩니다.
처음에는 구글 계정에서
스크립트 사용하는 허가 과정이 있기는 합니다.
function fetchRealEstateFullFields() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getActiveSheet();
const regionInput = sheet.getRange('A1').getValue().toString().trim();
const startYmd = sheet.getRange('C1').getValue().toString().trim();
const endYmd = sheet.getRange('D1').getValue().toString().trim();
if (!regionInput || !startYmd || !endYmd) {
SpreadsheetApp.getUi().alert('A1(지역코드), C1(시작월), D1(종료월)을 입력해주세요.');
return;
}
const API_KEY = 'EiSwcNcFmNxdrxxxxxxxxxxxxxxxxxxxxxxxxxLyeThY9HnCpqzxxvXNQ%3D%3D';
const BASE_URL = 'https://apis.data.go.kr/1613000/RTMSDataSvcAptTrade/getRTMSDataSvcAptTrade';
const monthList = generateMonthList(startYmd, endYmd);
const allLawdCodes = getLawdCodesFromSheet();
const validLawdCodes = new Set();
if (regionInput.length === 2) {
allLawdCodes.forEach(code => {
if (code.startsWith(regionInput)) validLawdCodes.add(code);
});
} else if (regionInput.length === 5) {
validLawdCodes.add(regionInput);
} else {
SpreadsheetApp.getUi().alert('올바른 시·도(2자리) 또는 시군구(5자리) 코드를 A1에 입력해주세요.');
return;
}
sheet.getRange('A3:R10000').clearContent();
sheet.getRange('A2:R2').setValues([[
'아파트명', '동번호', '지번', '법정동', '건축년도', '전용면적(㎡)', '층', '거래금액(만원)', '거래일',
'매수자구분', '매도자구분', '거래유형', '공인중개소', '토지임차구분', '등기접수일', '시군구코드', '계약해제유형', '계약해제일'
]]);
let row = 3;
for (let lawdCd of validLawdCodes) {
for (let yyyymm of monthList) {
const url = `${BASE_URL}?serviceKey=${API_KEY}&LAWD_CD=${lawdCd}&DEAL_YMD=${yyyymm}`;
try {
const response = UrlFetchApp.fetch(url, {
method: 'get',
contentType: 'application/xml',
muteHttpExceptions: true
});
if (response.getResponseCode() !== 200) continue;
const xml = XmlService.parse(response.getContentText());
const items = xml.getRootElement().getChild('body').getChild('items').getChildren('item');
for (let item of items) {
const getText = tag => (item.getChildText(tag) || '').trim();
const aptNm = getText('aptNm');
const aptDong = getText('aptDong');
const jibun = getText('jibun');
const umdNm = getText('umdNm');
const buildYear = getText('buildYear');
const area = getText('excluUseAr');
const floor = getText('floor');
const price = getText('dealAmount');
const dealYear = getText('dealYear');
const dealMonth = getText('dealMonth').padStart(2, '0');
const dealDay = getText('dealDay').padStart(2, '0');
const dealDate = `${dealYear}-${dealMonth}-${dealDay}`;
const buyerGbn = getText('buyerGbn');
const slerGbn = getText('slerGbn');
const dealingGbn = getText('dealingGbn');
const agent = getText('estateAgentSggNm');
const leaseGbn = getText('landLeaseholdGbn');
const rgstDate = getText('rgstDate');
const sggCd = getText('sggCd');
const cdealType = getText('cdealType');
const cdealDay = getText('cdealDay');
sheet.getRange(row, 1, 1, 18).setValues([[
aptNm, aptDong, jibun, umdNm, buildYear, area, floor, price, dealDate,
buyerGbn, slerGbn, dealingGbn, agent, leaseGbn, rgstDate, sggCd, cdealType, cdealDay
]]);
row++;
}
} catch (err) {
Logger.log(`오류: LAWD_CD=${lawdCd}, DEAL_YMD=${yyyymm}, 메시지=${err.message}`);
}
}
}
SpreadsheetApp.getUi().alert(`데이터 수집 완료! 총 ${row - 3}건의 거래를 불러왔습니다.`);
}
function generateMonthList(startYmd, endYmd) {
const startYear = parseInt(startYmd.substring(0, 4), 10);
const startMonth = parseInt(startYmd.substring(4), 10);
const endYear = parseInt(endYmd.substring(0, 4), 10);
const endMonth = parseInt(endYmd.substring(4), 10);
const result = [];
for (let y = startYear; y <= endYear; y++) {
const mStart = (y === startYear) ? startMonth : 1;
const mEnd = (y === endYear) ? endMonth : 12;
for (let m = mStart; m <= mEnd; m++) {
result.push(`${y}${String(m).padStart(2, '0')}`);
}
}
return result;
}
function getLawdCodesFromSheet() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getActiveSheet();
const range = sheet.getRange('Z3:AA274').getValues();
const codes = [];
for (let row of range) {
for (let val of row) {
const str = val.toString().trim();
if (str.length === 5) {
codes.push(str);
}
}
}
return codes;
}
📷 이미지1: 구글시트에서 앱스스크립트 실행하는 화면 캡처
💬 왕초보에게 꼭 해주고 싶은 말
저 진짜 코딩 모르는데 ChatGPT가
이해할 수 있을 때까지 쉽게 설명해주
오류 나면 왜 그런지 알려주고
수정할 코드까지 제안해 주면서
만들었습니다.
저 같은 초보도 가능하니까, 여러분도 꼭 도전해보세요!
🙌 데이터는 이제 누구나 다룰 수 있어요
예전엔 전문가들만 다루던 데이터 분석도
지금은 ChatGPT와 함께라면
누구나 도전할 수 있는 시대입니다.
구독해주시고 궁금한 점 있으시면
댓글 남겨주세요.
'인공지능 (AI) 따라잡기' 카테고리의 다른 글
| [재건축 유망주] 목동신시가지아파트 1단지~14단지, 누적 매매대금 1조2330억 (6) | 2025.07.15 |
|---|---|
| [서울_아파트매매_실거래분석] 7월1일~7월 12일, 강남구 매매대금 합계 압도적 1위 (6) | 2025.07.14 |
| [인포그래픽] 서울 주요 자치구 아파트 매매가격 상승률...chatGPT + 파이썬 (22) | 2025.07.10 |
| chatGPT 데이터 분석 연습하기 (8) | 2025.07.02 |
| 이미지 두장으로 KRX 금 현물 과 금현물 ETF 시황 정리하기 (3) | 2025.07.01 |