본문 바로가기

좋아하는것_부자되는매직TV

주택도시보증공사(HUG) Openapi 와 텔레그램 봇을 활용한 나만의 아파트 공사 정보 검색 기능 구현!

반응형

블로그 목적

주택도시보증공사(HUG) Openapi  와 텔레그램 봇을 활용한 아파트 공사 정보 기능 구현에 대해서 공부및 정리후 나만의 노하우와 지식을 공유한다.

블로그 요약

1. 주택도시보증공사(HUG) Openapi 에 대해서 알아본다.

2. 주택도시보증공사(HUG) Openapi 와 텔레그램 봇을 활용한 아파트 공사 정보 검색 기능을 간단하게 구현해 본다.

블로그 상세내용

요즘에 재테크로 아파트 공사 정보에 대해서 관심이 생겨서 아파트 공사 정보관련 Openapi 가 있나?
검색창을 두리번 거리다가요.

드디어 주택도시보증공사(HUG)   Openapi 를 발견했습니다. 

참고로 주택도시보증공사(HUG) 에 대해서 정리해보면 아래와 같은데요?

주택도시보증공사(HUG)는 대한민국의 주요 공공기관으로, 주거복지 증진과 도시재생 활성화를 지원하는 중요한 역할을 수행하고 있습니다. 이 기관에 대해 자세히 알아보겠습니다.

주택도시보증공사(HUG) 개요
주택도시보증공사는 2015년 7월 1일, 주택도시기금법에 근거하여 설립되었습니다.
이전에는 대한주택보증주식회사로 운영되다가 주택도시기금 전담 운용 기관으로 새롭게 출범하게 되었고요.

설립 목적은 아래와 같은데요?
HUG의 주요 목적은 주거복지 증진과 도시재생 활성화를 지원하여 국민의 삶의 질 향상에 기여하는 것이라고 하네요.

주요 업무
HUG는 다양한 보증 업무와 정책 사업을 수행하고 있습니다.

하나, 보증 업무
주택 분양보증, 임대보증금보증, 조합주택시공보증, 전세보증금반환보증, 모기지보증

둘, 정책 지원 업무
공유형모기지 수탁, 국가 및 지방자치단체 위탁 업무

셋, 주택도시기금 운용·관리
주택도시기금법에 따른 기금의 효율적 운용 및 관리

HUG의 역할과 중요성
하나, 주택 시장 안정화 
HUG는 주택 사업 전 단계에 걸친 기업보증 제도를 운영하여 주택금융시장의 안정을 도모합니다

둘, 서민 주거 안정 지원
개인보증 공급 및 전세피해자 지원 등을 통해 서민들의 주거 안정을 돕습니다

셋, 도시재생 촉진
노후 주택 및 재개발, 재건축 사업에 대한 보증 및 지원을 통해 도시 재생과 지역 개발을 촉진합니다

넷, 주택금융 상담 서비스
주택금융상담센터를 운영하여 일반 국민들에게 맞춤형 상담 및 정보를 제공합니다

재테크 관점에서 궁금해서 HUG의 비전에 대해서 알아봣는데요?
주택도시보증공사는 "국민의 주거안정을 선도하는 주택도시금융 동반자"로 거듭나기 위해 노력하고 있다고 하고요.
이를 위해 다음과 같은 4대 경영전략을 추진하고 있다고 하네요.
하나, 주거안정 금융서비스 강화
둘, 주택공급 기반 금융 확대
셋, ESG경영 선도
넷, 지속가능 혁신기반 구축

아무튼 주택도시보증공사는 지난 30년간 국민의 삶의 질 향상에 기여해 왔으며, 앞으로도 주택 시장의 안정과 서민 주거 안정을 위해 중요한 역할을 수행할 것으로 기대됩니다.  
혹시나 HUG 에 대해서 좀더 아시고 싶은 분은 홈페이지에 접속해 보시면 좋을 것 같네요.

그럼 HUG 가 제공하는 OPENAPI 중에 제가 찾는 API가 있나 봤더니? 있더라고요 감사하더라고요..

 

바로 아파트 공사정보입니다.  OPEN API 기능 정보를 보니 요청 변수는 아래와 같고요.

응답 변수는 아래와 같았습니다.

실제적으로 아파트 공사 정보를 요청해보니 아래와 같았습니다. 

응답 구조는 json 이 아니라 xml 이였고요. 
items 에 묶여서 item 을 파싱하면 되는 구조더라고요.

이제 어느정도 OPENAP 에 대해서 분석을 마쳤으니 golang 을 통해서 구현 시도를 해봅니다. 

아래와 같이 go 프로젝트를 우선 세팅합니다. (텔레그램 bot api 도 세팅)

$ go mod init hug_aptinfo_telegram
$ go get -u github.com/go-telegram-bot-api/telegram-bot-api/v5

구현은 아래와 같이 진행합니다. 

첫번째, 응답 구조체 선언,  위의 xml 보고 아래와  같이 구조체도 선언합니다. 

// OpenAPI 응답 구조체 정의
type Response struct {
	Header struct {
		ResultCode string `xml:"resultCode"`
		ResultMsg  string `xml:"resultMsg"`
	} `xml:"header"`
	Body struct {
		Items struct {
			Item []ConstructionInfo `xml:"item"`
		} `xml:"items"`
	} `xml:"body"`
}

type ConstructionInfo struct {
	BUNO               string  `xml:"BUNO"`
	BSU_NM             string  `xml:"BSU_NM"`
	BIZ_DCD            string  `xml:"BIZ_DCD"`
	BIZ_NM             string  `xml:"BIZ_NM"`
	AREA_DCD           string  `xml:"AREA_DCD"`
	AREA_NM            string  `xml:"AREA_NM"`
	AREA_DTL_NM        string  `xml:"AREA_DTL_NM"`
	TPOW_RT            float64 `xml:"TPOW_RT"`
	MIN_TPOW_YYM       string  `xml:"MIN_TPOW_YYM"`
	MAX_TPOW_YYM       string  `xml:"MAX_TPOW_YYM"`
	MAX_HSHD_FOR_SILT_WN int    `xml:"MAX_HSHD_FOR_SILT_WN"`
	MIN_HSHD_FOR_SILT_WN int    `xml:"MIN_HSHD_FOR_SILT_WN"`
	HOUS_TOT_HOCO      int     `xml:"HOUS_TOT_HOCO"`
	HIGH_FLOR_QT       int     `xml:"HIGH_FLOR_QT"`
	TOTL_DONG_QT       int     `xml:"TOTL_DONG_QT"`
}

두번째, 위에서 정의한 구조체 정보를 기반으로 필요정보들을 기준으로 xml를 파싱하는 함수를 구현하고요.

// OpenAPI 데이터 호출 함수
func fetchConstructionInfo(apiURL, apiKey string) ([]ConstructionInfo, error) {

	area_dcd := "01" //서울

	// URL 구성
	reqURL := fmt.Sprintf("%s?API_KEY=%s&AREA_DCD=%s", apiURL, apiKey, area_dcd)

	// API 호출
	resp, err := http.Get(reqURL)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch data: %v", err)
	}
	defer resp.Body.Close()

	// 응답 데이터 읽기
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("failed to read response body: %v", err)
	}

	// XML 파싱
	var apiResponse Response
	err = xml.Unmarshal(body, &apiResponse)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal XML: %v", err)
	}

	if apiResponse.Header.ResultCode != "00" {
		return nil, fmt.Errorf("API error: %s", apiResponse.Header.ResultMsg)
	}

	return apiResponse.Body.Items.Item, nil
}

마지막으로 메시지로 만들고 텔레그램으로 전송하는 함수를 작성하면 될것 같습니다. 

// 상위 10개 데이터에 대해 메시지 생성 및 전송
	for i, item := range constructionInfo {
		if i >= 10 {
			break
		}

		// 메시지 생성
		message := fmt.Sprintf(
			"🏗 **아파트 공사 정보** 🏗\n"+
				"1️⃣ 사업 번호: %s\n"+
				"2️⃣ 단지명: %s\n"+
				"3️⃣ 사업 구분: %s (%s)\n"+
				"4️⃣ 지역: %s, %s\n"+
				"5️⃣ 전용면적: %.1f㎡\n"+
				"6️⃣ 공사 기간: %s ~ %s\n"+
				"7️⃣ 세대 수: %d세대\n"+
				"8️⃣ 최고층: %d층\n"+
				"9️⃣ 동 수: %d동\n"+
				"🔟 분양가: %d ~ %d원\n",
			item.BUNO,
			item.BSU_NM,
			item.BIZ_DCD, item.BIZ_NM,
			item.AREA_NM, item.AREA_DTL_NM,
			item.TPOW_RT,
			item.MIN_TPOW_YYM, item.MAX_TPOW_YYM,
			item.HOUS_TOT_HOCO,
			item.HIGH_FLOR_QT,
			item.TOTL_DONG_QT,
			item.MIN_HSHD_FOR_SILT_WN, item.MAX_HSHD_FOR_SILT_WN,
		)

		// 텔레그램 메시지 전송
		err = sendTelegramMessage(botToken, chatID, message)
		if err != nil {
			log.Printf("Failed to send message for item %d: %v", i+1, err)
		}

전체 소스는 아래와 같습니다. 

package main

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
)

// OpenAPI 응답 구조체 정의
type Response struct {
	Header struct {
		ResultCode string `xml:"resultCode"`
		ResultMsg  string `xml:"resultMsg"`
	} `xml:"header"`
	Body struct {
		Items struct {
			Item []ConstructionInfo `xml:"item"`
		} `xml:"items"`
	} `xml:"body"`
}

type ConstructionInfo struct {
	BUNO               string  `xml:"BUNO"`
	BSU_NM             string  `xml:"BSU_NM"`
	BIZ_DCD            string  `xml:"BIZ_DCD"`
	BIZ_NM             string  `xml:"BIZ_NM"`
	AREA_DCD           string  `xml:"AREA_DCD"`
	AREA_NM            string  `xml:"AREA_NM"`
	AREA_DTL_NM        string  `xml:"AREA_DTL_NM"`
	TPOW_RT            float64 `xml:"TPOW_RT"`
	MIN_TPOW_YYM       string  `xml:"MIN_TPOW_YYM"`
	MAX_TPOW_YYM       string  `xml:"MAX_TPOW_YYM"`
	MAX_HSHD_FOR_SILT_WN int    `xml:"MAX_HSHD_FOR_SILT_WN"`
	MIN_HSHD_FOR_SILT_WN int    `xml:"MIN_HSHD_FOR_SILT_WN"`
	HOUS_TOT_HOCO      int     `xml:"HOUS_TOT_HOCO"`
	HIGH_FLOR_QT       int     `xml:"HIGH_FLOR_QT"`
	TOTL_DONG_QT       int     `xml:"TOTL_DONG_QT"`
}

// 텔레그램 메시지 전송 함수
func sendTelegramMessage(botToken, chatID, message string) error {
	bot, err := tgbotapi.NewBotAPI(botToken)
	if err != nil {
		return fmt.Errorf("failed to create bot: %v", err)
	}

	msg := tgbotapi.NewMessageToChannel(chatID, message)
	_, err = bot.Send(msg)
	if err != nil {
		return fmt.Errorf("failed to send message: %v", err)
	}

	return nil
}

// OpenAPI 데이터 호출 함수
func fetchConstructionInfo(apiURL, apiKey string) ([]ConstructionInfo, error) {

	area_dcd := "01" //서울

	// URL 구성
	reqURL := fmt.Sprintf("%s?API_KEY=%s&AREA_DCD=%s", apiURL, apiKey, area_dcd)

	// API 호출
	resp, err := http.Get(reqURL)
	if err != nil {
		return nil, fmt.Errorf("failed to fetch data: %v", err)
	}
	defer resp.Body.Close()

	// 응답 데이터 읽기
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("failed to read response body: %v", err)
	}

	// XML 파싱
	var apiResponse Response
	err = xml.Unmarshal(body, &apiResponse)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal XML: %v", err)
	}

	if apiResponse.Header.ResultCode != "00" {
		return nil, fmt.Errorf("API error: %s", apiResponse.Header.ResultMsg)
	}

	return apiResponse.Body.Items.Item, nil
}

func main() {
	// 환경 변수 또는 설정
	apiURL := "https://www.khug.or.kr/myAptConstructionInfo.do" // OpenAPI URL
	apiKey := "오픈API KEY" 
	botToken := "텔레그램 봇 토큰" // 텔레그램 봇 토큰
	chatID := "텔레그램 채팅 ID"   // 텔레그램 채팅 ID


	// OpenAPI 데이터 가져오기
	constructionInfo, err := fetchConstructionInfo(apiURL, apiKey)
	if err != nil {
		log.Fatalf("Failed to fetch construction info: %v", err)
	}

	// 상위 10개 데이터에 대해 메시지 생성 및 전송
	for i, item := range constructionInfo {
		if i >= 10 {
			break
		}

		// 메시지 생성
		message := fmt.Sprintf(
			"🏗 **아파트 공사 정보** 🏗\n"+
				"1️⃣ 사업 번호: %s\n"+
				"2️⃣ 단지명: %s\n"+
				"3️⃣ 사업 구분: %s (%s)\n"+
				"4️⃣ 지역: %s, %s\n"+
				"5️⃣ 전용면적: %.1f㎡\n"+
				"6️⃣ 공사 기간: %s ~ %s\n"+
				"7️⃣ 세대 수: %d세대\n"+
				"8️⃣ 최고층: %d층\n"+
				"9️⃣ 동 수: %d동\n"+
				"🔟 분양가: %d ~ %d원\n",
			item.BUNO,
			item.BSU_NM,
			item.BIZ_DCD, item.BIZ_NM,
			item.AREA_NM, item.AREA_DTL_NM,
			item.TPOW_RT,
			item.MIN_TPOW_YYM, item.MAX_TPOW_YYM,
			item.HOUS_TOT_HOCO,
			item.HIGH_FLOR_QT,
			item.TOTL_DONG_QT,
			item.MIN_HSHD_FOR_SILT_WN, item.MAX_HSHD_FOR_SILT_WN,
		)

		// 텔레그램 메시지 전송
		err = sendTelegramMessage(botToken, chatID, message)
		if err != nil {
			log.Printf("Failed to send message for item %d: %v", i+1, err)
		}
	}

	fmt.Println("All messages sent successfully!")
}

그럼 컴파일을 하고 실행을 해봅니다. 

$ go build .\hug_aptinfo_telegram.go
$ .\hug_aptinfo_telegram.exe

 

아래와 같이 텔레그램봇이 있는 방으로 아파트 공사 정보 메시지가 수신됩니다. 

여기까지가 제가 한번 주택도시보증공사(HUG) Openapi  를 활용해서 golang  으로 구현한 아파트 공사 정보 기능입니다. 

항상 믿고 봐주셔서 감사합니다. 

맺음말

간단하게 오늘의 블로그에 대해서 저만의 생각을 정리해보자면요.

이 golang 프로그램을 잘이용하면 아파트 재테크 측면에서

자신이 원하는 아파트 공사 정보만을 잘 정리해서 텔레그램 메시지로 전송하고 공유 할 수 있을것 같고요.

요즘 물가도 치솟고 장볼때마다 식겁할때가 많은데요...ㅎㅎ

조금이나마 아파트 재테크할때 도움을 받을 수 있을것 같네요. 

요즘 로제 & 브루노마스  아파트 라는 노래가 중독성도 있고 대세 인데요...아파트 정보를 한번 가져와보고 싶어서 바로 구현해 보고 이렇게 블로그로 남기네요.

오늘의 블로그는 여기까지고요

항상 믿고 봐주셔서 감사합니다.

그럼 오늘하루도 건강하시고 행복한 하루되세요~

300x250