공공데이터 크롤링 자동화

데이터 · 크롤링5분 읽기

공공데이터 크롤링 자동화 소개 영상

문제

이 고객사는 시민에게 정책·복지·행사·교육 정보를 카드 형태로 보여주는 앱을 운영합니다. 문제는 그 정보가 한곳에 있지 않다는 점이었습니다. 중앙부처는 공공데이터포털 API로, 서울시는 열린데이터광장으로, 25개 자치구는 각자의 홈페이지 게시판으로, 일부 기관은 네이버 블로그로 공고를 냅니다. 담당자가 매일 이 사이트들을 직접 돌며 새 공고를 확인하고 옮겨 적는 방식은 소스가 늘어날수록 버틸 수 없는 구조였습니다.

수집만 문제가 아니었습니다. 기관마다 데이터 형식이 전부 다르고 같은 정책이 여러 기관에 동시에 게재됩니다. 복지 정책 하나가 부처 API에도, 구청 게시판에도, 기관 블로그에도 올라오면 앱에는 같은 카드가 세 번 나타납니다. 형식 통일과 중복 정리를 사람이 하던 것이 두 번째 병목이었습니다.

마지막 조건은 운영이었습니다. 이 파이프라인은 담당 개발자가 상주하지 않는 환경에서 돌아가야 했습니다. 하루라도 수집이 멈추면 앱의 정보가 낡기 시작하므로, 사람이 지켜보지 않아도 매일 돌고 실패하면 스스로 복구하거나 최소한 무엇이 실패했는지 남기는 구조가 필요했습니다.

접근

기능

109개 소스를 하나의 파이프라인으로

공공데이터포털 API 10종, 전국·서울 크롤러, 25개 자치구 게시판 65개, 네이버 블로그 27개까지 총 109개 소스를 수집·정규화·적재의 단일 흐름에 올렸습니다. 소스마다 수집기를 따로 두되, 실패는 소스 단위로 격리해 한 곳의 장애가 전체 수집을 멈추지 않게 했습니다.

수집 대상 중 가장 까다로운 것은 자치구 게시판이었습니다. 구청마다 홈페이지 시스템이 달라서 25개 구를 각각 크롤링 코드로 짜면 유지보수가 곧 지옥이 됩니다. 그래서 게시판 구조를 유형별로 분석해 11종의 템플릿으로 추상화하고 각 구는 설정 파일만 추가하면 붙는 구조를 만들었습니다. 새 자치구나 새 게시판을 추가할 때 크롤링 코드를 새로 짜지 않습니다.

기능

11개 템플릿으로 25개 자치구를 커버하는 설정형 크롤러

자치구 홈페이지의 게시판 시스템을 11종 템플릿으로 추상화하고 구별 차이는 설정 파일로만 표현했습니다. 게시판 주소와 선택자 몇 줄이면 새 소스가 추가되고 사이트 개편도 해당 구의 설정만 고치면 됩니다.

수집된 원본은 정규화를 거쳐 공통 스키마로 모입니다. 기관마다 다른 날짜 표기("상시", "예산 소진 시까지", 온갖 구분자의 연월일)를 파서가 흡수하고 EUC-KR 인코딩과 상대 경로 링크도 이 단계에서 정리됩니다. 그 위에 AI 분류가 올라갑니다. 정책의 기관·분류·관심주제·생애주기·문의처·핵심 혜택 여섯 필드를 Claude가 추출하되, 소스에 표준 코드가 있으면 그대로 쓰고 없을 때만 AI가 판단하는 하이브리드 방식입니다. 대량 처리는 배치 API로 돌려 호출 비용을 절반 수준으로 낮췄습니다.

기능

AI 분류와 의미 기반 중복 제거

수집 공고마다 기관·분류·관심주제·생애주기·문의처·핵심 혜택을 AI가 추출합니다. 여러 출처에 올라온 같은 정책은 제목이 조금씩 달라 단순 문자열 비교로는 못 잡기 때문에, 후보를 좁힌 뒤 LLM이 같은 정책인지 판정하고 가장 정보가 풍부한 출처를 대표로 선정해 하나로 통합합니다.

공공 사이트 수집에는 교과서에 없는 함정이 많습니다. 공공 API는 에러를 HTTP 200에 담아 돌려주는 경우가 있어 응답 검증기를 파싱 앞에 두었고 요청은 분당 30회로 제한해 상대 서버에 부담을 주지 않게 했습니다. 일시 장애는 지수 백오프로 최대 6회 재시도하고 봇 차단이 감지되면 클라우드 크롤러로 전환해 수집을 이어갑니다.

기능

사람 없이 도는 일일 무인 운영

매일 새벽 자동 실행되는 오케스트레이터가 수집, 이미지 추출, AI 분류, 중복 통합을 단계별로 진행합니다. 단계마다 프로세스를 격리하고 실행 이력을 감사 테이블에 남기며 AI 비용에는 상한을 걸어 폭주를 차단합니다. 운영자는 대시보드에서 수집 현황과 실패 로그를 확인합니다.

전체 구조는 다음과 같습니다.

109개 소스에서 수집한 공고가 정규화, AI 분류, 의미 중복 제거를 거쳐 통합 DB와 앱·대시보드로 흐르는 구조소스 109개부처 API 10크롤러 72블로그 27수집·정규화원본 DBAI 분류 · 6필드 추출LLM 의미 중복 제거통합 DB시민 앱 · 운영대시보드매일 새벽 무인 오케스트레이터재시도 · 차단 폴백 · 감사 로그AI 비용 상한

글로도 요약하면 이렇습니다. 109개 소스에서 수집한 공고는 공통 스키마로 정규화되어 원본 DB에 쌓이고 AI가 여섯 필드를 추출해 붙인 뒤, LLM 판정으로 같은 정책을 하나로 통합해 통합 DB를 만듭니다. 시민 앱과 운영자 대시보드는 이 통합 DB만 바라봅니다. 전 과정은 매일 새벽 오케스트레이터가 무인으로 실행합니다.

결과

담당자가 기관 사이트를 돌며 공고를 확인하고 옮겨 적던 일이 사라졌습니다. 전국과 서울의 정책 공고가 매일 새벽 자동으로 모이고 분류와 중복 정리까지 끝난 데이터가 앱에 바로 쓸 수 있는 형태로 유지됩니다. 같은 정책이 앱에 여러 번 나타나던 문제는 통합 DB가 흡수합니다.

운영 관점의 변화도 큽니다. 수집이 실패해도 어느 소스가 왜 실패했는지 감사 로그와 대시보드에 남고 새 소스 추가는 설정 파일 작성 수준의 일이 됐습니다. 실제로 납품 이후에도 이 구조 위에서 소스와 기능이 계속 늘고 있습니다.

이 프로젝트에서 다룬 기술적 결정들은 아래 글에서 더 자세히 풀었습니다.

자주 묻는 질문

공공데이터는 API만으로 전부 수집할 수 있나요?

아니요. 공공데이터포털 API가 커버하는 범위는 일부이고 자치구 게시판이나 기관 블로그처럼 API가 없는 소스가 훨씬 많습니다. 이 프로젝트도 API 10종에 크롤러 72개, 블로그 수집 27개를 병행해 109개 소스를 채웠습니다.

사이트 구조가 바뀌면 크롤러가 멈추지 않나요?

영향은 해당 소스 하나로 격리됩니다. 소스별로 실행이 분리되어 있어 한 곳의 개편이 전체 수집을 멈추지 않고 실패는 감사 로그와 대시보드에 바로 드러납니다. 자치구 게시판은 템플릿과 설정으로 분리되어 있어 대부분 설정 수정만으로 복구됩니다.

여러 사이트에 올라온 같은 공고는 어떻게 처리하나요?

단순 문자열 비교가 아니라 LLM이 의미를 보고 판정합니다. 제목과 기관, 내용 요약으로 후보를 좁힌 뒤 같은 정책인지 판단하고 정보가 가장 풍부한 출처를 대표로 선정해 통합 DB에 하나만 남깁니다.

수집이 상대 기관 서버에 부담을 주지는 않나요?

요청 속도를 분당 30회로 제한하고 실패 시에도 간격을 지수적으로 늘려 재시도합니다. 공개된 공고 정보를 사람이 열람하는 것보다 완만한 속도로 수집하도록 설계했습니다.

도입 결과

담당자가 기관 사이트를 돌며 공고를 확인하던 일이 사라지고, 전국과 서울의 정책 공고가 매일 새벽 자동으로 수집·분류·통합되어 앱과 대시보드에서 항상 최신 상태로 조회되는 구조가 갖춰졌습니다.
#공공데이터#크롤링#데이터파이프라인#AI분류

비슷한 업무 자동화가 필요하신가요?

무료 상담 신청