realestate-lab 설계 스펙
부동산 청약 공고 자동 수집 + 프로필 기반 자격 매칭 서비스
1. 개요
공공데이터포털(한국부동산원 청약홈 분양정보 API)에서 청약 공고를 자동 수집하고, 사용자 프로필 기반으로 지원 가능 여부를 자동 판별하는 독립 서비스.
핵심 목표:
- 수동 공고 등록 없이 자동 수집 → DB 저장
- 프로필 기반 자격 매칭 → 지원 가능한 청약만 필터링
- 프론트에서 "새 공고 N건" 확인 → 향후 텔레그램 알림 확장
2. 서비스 아키텍처
독립 서비스 구조
수집 흐름
3. 데이터 소스
공공데이터포털 — 한국부동산원_청약홈 분양정보 조회 서비스
- Base URL:
https://api.odcloud.kr/api
- 서비스 키:
DATA_GO_KR_API_KEY 환경변수
- 일 호출 제한: 40,000건
- 데이터 포맷: JSON
수집 대상 API 엔드포인트
| 엔드포인트 |
설명 |
/ApplyhomeInfoDetailSvc/v1/getAPTLttotPblancDetail |
APT 분양정보 상세 |
/ApplyhomeInfoDetailSvc/v1/getUrbtyOfctlLttotPblancDetail |
오피스텔/도시형/민간임대 상세 |
/ApplyhomeInfoDetailSvc/v1/getRemndrLttotPblancDetail |
잔여세대 상세 |
/ApplyhomeInfoDetailSvc/v1/getPblPvtRentLttotPblancDetail |
공공지원 민간임대 상세 |
/ApplyhomeInfoDetailSvc/v1/getOPTLttotPblancDetail |
임의공급 상세 |
주택형별 상세 API (모델별 세대수·분양가)
| 엔드포인트 |
설명 |
/ApplyhomeInfoDetailSvc/v1/getAPTLttotPblancMdl |
APT 주택형별 |
/ApplyhomeInfoDetailSvc/v1/getUrbtyOfctlLttotPblancMdl |
오피스텔 주택형별 |
/ApplyhomeInfoDetailSvc/v1/getRemndrLttotPblancMdl |
잔여세대 주택형별 |
/ApplyhomeInfoDetailSvc/v1/getPblPvtRentLttotPblancMdl |
공공지원 민간임대 주택형별 |
/ApplyhomeInfoDetailSvc/v1/getOPTLttotPblancMdl |
임의공급 주택형별 |
공통 쿼리 파라미터
page (기본: 1), perPage (기본: 100)
serviceKey — 인코딩된 API 키
cond[RCRIT_PBLANC_DE::GTE] / cond[RCRIT_PBLANC_DE::LTE] — 모집공고일 범위 필터
4. DB 스키마 (realestate.db)
announcements (청약 공고)
| 컬럼 |
타입 |
설명 |
| id |
INTEGER PK |
자동 증가 |
| house_manage_no |
TEXT NOT NULL |
주택관리번호 |
| pblanc_no |
TEXT NOT NULL |
공고번호 |
| house_nm |
TEXT |
주택명 |
| house_secd |
TEXT |
주택구분코드 (01:APT, 02:오피스텔, 04:무순위 등) |
| house_dtl_secd |
TEXT |
주택상세구분코드 (01:민영, 03:국민 등) |
| rent_secd |
TEXT |
분양구분 (0:분양, 1:임대) |
| region_code |
TEXT |
공급지역코드 |
| region_name |
TEXT |
공급지역명 |
| address |
TEXT |
공급위치 |
| total_units |
INTEGER |
공급규모 |
| rcrit_date |
TEXT |
모집공고일 |
| receipt_start |
TEXT |
청약접수시작일 |
| receipt_end |
TEXT |
청약접수종료일 |
| spsply_start |
TEXT |
특별공급 접수시작일 |
| spsply_end |
TEXT |
특별공급 접수종료일 |
| gnrl_rank1_start |
TEXT |
1순위 접수시작일 |
| gnrl_rank1_end |
TEXT |
1순위 접수종료일 |
| winner_date |
TEXT |
당첨자발표일 |
| contract_start |
TEXT |
계약시작일 |
| contract_end |
TEXT |
계약종료일 |
| homepage_url |
TEXT |
홈페이지 |
| pblanc_url |
TEXT |
공고 URL |
| constructor |
TEXT |
시공사 |
| developer |
TEXT |
시행사 |
| move_in_month |
TEXT |
입주예정월 |
| is_speculative_area |
TEXT |
투기과열지구 |
| is_price_cap |
TEXT |
분양가상한제 |
| contact |
TEXT |
문의처 |
| status |
TEXT |
청약예정/청약중/결과발표/완료 (자동 계산) |
| source |
TEXT |
auto/manual |
| created_at |
TEXT |
|
| updated_at |
TEXT |
|
- UNIQUE 제약:
(house_manage_no, pblanc_no)
- INDEX:
idx_realestate_status on status
- INDEX:
idx_realestate_region on region_name
announcement_models (주택형별 상세)
| 컬럼 |
타입 |
설명 |
| id |
INTEGER PK |
|
| house_manage_no |
TEXT |
FK → announcements |
| pblanc_no |
TEXT |
FK → announcements |
| model_no |
TEXT |
모델번호 |
| house_ty |
TEXT |
주택형 (84A 등) |
| supply_area |
REAL |
공급면적(㎡) |
| general_units |
INTEGER |
일반공급 세대수 |
| special_units |
INTEGER |
특별공급 세대수 |
| multi_child_units |
INTEGER |
다자녀 |
| newlywed_units |
INTEGER |
신혼부부 |
| first_life_units |
INTEGER |
생애최초 |
| old_parent_units |
INTEGER |
노부모부양 |
| institution_units |
INTEGER |
기관추천 |
| youth_units |
INTEGER |
청년 |
| newborn_units |
INTEGER |
신생아 |
| top_amount |
INTEGER |
분양최고금액(만원) |
- UNIQUE:
(house_manage_no, pblanc_no, model_no)
user_profile (사용자 청약 프로필)
| 컬럼 |
타입 |
설명 |
| id |
INTEGER PK |
항상 1 (단일 사용자) |
| name |
TEXT |
이름 |
| age |
INTEGER |
나이 |
| is_homeless |
BOOLEAN |
무주택 여부 |
| is_householder |
BOOLEAN |
세대주 여부 |
| subscription_months |
INTEGER |
청약통장 가입개월수 |
| subscription_amount |
INTEGER |
청약통장 납입총액(만원) |
| family_members |
INTEGER |
세대원 수 |
| has_dependents |
BOOLEAN |
부양가족 유무 |
| children_count |
INTEGER |
미성년 자녀수 |
| is_newlywed |
BOOLEAN |
신혼부부 여부 |
| marriage_months |
INTEGER |
혼인기간(개월) |
| has_newborn |
BOOLEAN |
2세 이하 자녀 유무 |
| is_first_home |
BOOLEAN |
생애최초 해당 여부 |
| income_level |
TEXT |
소득수준 (100%이하/100130%/130160%) |
| preferred_regions |
TEXT |
관심지역 JSON 배열 |
| preferred_types |
TEXT |
관심주택유형 JSON 배열 |
| min_area |
REAL |
최소 희망면적(㎡) |
| max_area |
REAL |
최대 희망면적(㎡) |
| max_price |
INTEGER |
최대 분양가(만원) |
| updated_at |
TEXT |
|
match_results (매칭 결과)
| 컬럼 |
타입 |
설명 |
| id |
INTEGER PK |
|
| announcement_id |
INTEGER |
FK → announcements |
| model_id |
INTEGER |
FK → announcement_models (nullable) |
| match_score |
INTEGER |
매칭 점수 (0~100) |
| match_reasons |
TEXT |
매칭 사유 JSON 배열 |
| eligible_types |
TEXT |
지원 가능 유형 JSON 배열 |
| is_new |
BOOLEAN |
신규 매칭 여부 (알림용) |
| created_at |
TEXT |
|
- UNIQUE:
(announcement_id, model_id)
5. API 엔드포인트
청약 공고
| 메서드 |
경로 |
설명 |
| GET |
/api/realestate/announcements |
공고 목록 (필터: region, status, house_type, matched_only, sort, page, size) |
| GET |
/api/realestate/announcements/{id} |
공고 상세 (주택형별 포함) |
| POST |
/api/realestate/announcements |
수동 공고 등록 |
| PUT |
/api/realestate/announcements/{id} |
공고 수정 |
| DELETE |
/api/realestate/announcements/{id} |
공고 삭제 |
수집 관리
| 메서드 |
경로 |
설명 |
| POST |
/api/realestate/collect |
수동 수집 트리거 |
| GET |
/api/realestate/collect/status |
마지막 수집 결과 (수집일시, 신규건수, 에러) |
프로필
| 메서드 |
경로 |
설명 |
| GET |
/api/realestate/profile |
내 프로필 조회 |
| PUT |
/api/realestate/profile |
프로필 수정 (upsert) |
매칭
| 메서드 |
경로 |
설명 |
| GET |
/api/realestate/matches |
매칭 결과 목록 (점수순, 신규 우선) |
| POST |
/api/realestate/matches/refresh |
매칭 재계산 |
| PATCH |
/api/realestate/matches/{id}/read |
신규 알림 읽음 처리 |
대시보드
| 메서드 |
경로 |
설명 |
| GET |
/api/realestate/dashboard |
요약 (진행중 공고수, 신규 매칭수, 다가오는 일정) |
6. 매칭 엔진
점수 산출 (0~100)
| 기준 |
가중치 |
로직 |
| 지역 매칭 |
30 |
preferred_regions에 포함 → 30점 |
| 주택유형 매칭 |
10 |
preferred_types에 포함 → 10점 |
| 면적 매칭 |
15 |
min_area~max_area 범위 내 주택형 존재 → 15점 |
| 가격 매칭 |
15 |
max_price 이하 주택형 존재 → 15점 |
| 자격 매칭 |
30 |
지원 가능 공급유형 수에 비례 |
자격 매칭 세부
| 공급유형 |
판별 조건 |
| 일반 1순위 |
무주택 + 세대주 + 청약통장 가입기간 충족 (투기과열 24개월, 그 외 12개월) |
| 일반 2순위 |
1순위 미충족 시 |
| 특별-신혼부부 |
is_newlywed + 무주택 + 소득기준 |
| 특별-생애최초 |
is_first_home + 무주택 + 소득기준 |
| 특별-다자녀 |
children_count >= 2 + 무주택 |
| 특별-노부모부양 |
has_dependents + 무주택 |
| 특별-청년 |
age 19~39 + 무주택 |
| 특별-신생아 |
has_newborn + 무주택 |
- 1개 유형 → 10점, 2개 → 20점, 3개 이상 → 30점
eligible_types: 지원 가능 유형 목록 저장
match_reasons: 각 판별 사유 저장
상태 자동 계산
매칭 실행 시점
- 신규 공고 수집 후 자동 실행
- 프로필 변경 시
POST /matches/refresh로 재계산
- 매일 00:00 상태 갱신 시 재매칭
7. 인프라 통합
Docker Compose
Nginx
APScheduler
| 시간 |
Job |
설명 |
| 매일 09:00 |
run_collection |
5개 API 수집 → 매칭 |
| 매일 00:00 |
update_statuses |
날짜 기반 상태 갱신 |
배포
scripts/deploy-nas.sh에 realestate-lab/ rsync 대상 추가
8. lotto-backend 제거 대상
| 파일 |
제거 항목 |
backend/app/db.py |
realestate_complexes 테이블 생성, CRUD 함수 5개 |
backend/app/main.py |
ComplexCreate/ComplexUpdate 모델, /api/realestate/complexes 라우트 4개 |
기존 realestate_complexes 테이블 데이터는 마이그레이션 불필요 (스키마 완전 상이).
9. 환경변수
| 변수 |
설명 |
필수 |
DATA_GO_KR_API_KEY |
공공데이터포털 API 키 |
선택 (미설정 시 수동 등록만 가능) |
10. 향후 확장
- 텔레그램 알림: 신규 매칭 공고 발생 시 텔레그램 봇으로 push (알림 모듈 분리 구조 대비)
- 경쟁률 조회: 청약 접수 기간 중 경쟁률 실시간 수집
- 실거래가 비교: 주변 시세와 분양가 비교 분석