공고 알림봇 만들기 (4편) — API마다 응답 구조가 달랐습니다

3편에서 주소를 겨우 찾았다고 했죠. 그래서 다섯 곳에 다 요청을 보냈어요. 그랬더니 돌아온 것들이 서로 하나도 안 닮았습니다.

지난 편 → 3편 — 목록에 없는 API를 직접 찾아냈습니다

다섯 곳이 다섯 가지 모양이었어요

같은 "공고 목록"을 달라고 했는데 이렇게 왔어요.

소스형식목록이 어디 있나
K-StartupXMLitem 태그들
기업마당JSONjsonArray
LHJSON배열의 두 번째 칸
마이홈JSONresponse → body → item
든든전세JSON그냥 최상위 배열

XML 하나에 JSON 넷인데, 그 JSON 넷도 목록 위치가 전부 달라요. 표준이 있는 줄 알았는데 아무도 같은 걸 안 쓰고 있었어요.

XML인데 필드명이 태그가 아니었어요

제일 당황스러웠던 건 K-Startup이었어요. XML이면 보통 이런 모양을 기대하잖아요.

<item>
  <공고명>청년창업 지원사업</공고명>
</item>

그런데 실제로는 이랬어요.

<item>
  <col name="biz_pbanc_nm">청년창업 지원사업</col>
</item>

전부 col이라는 똑같은 태그예요. 필드 이름은 태그가 아니라 속성 안에 들어 있고요.

이러면 "공고명 태그를 찾아줘"가 안 통해요. col을 전부 훑으면서 name 속성을 읽어 이름표를 붙여줘야 합니다. 한 줄이면 되는 일이 두 단계가 된 거죠.

dsList라는 복병

LH는 더 예상 밖이었어요. JSON을 열었더니 최상위가 객체가 아니라 배열이었고, 그 안에 두 덩어리가 들어 있었어요.

[ { "dsSch": [ ... ] },
  { "dsList": [ ... ] } ]

dsSch는 제가 보낸 검색 조건이 되돌아온 거고, 실제 공고 목록은 dsList 쪽에 있었어요. 요청과 응답이 한 봉투에 같이 담겨 온 셈이죠.

ds가 뭘 줄인 건지는 어디에도 안 적혀 있어요. 내부 시스템에서 쓰던 이름이 그대로 밖으로 나온 것처럼 보이는데, 확인할 방법은 없었습니다.

그래서 "배열의 두 번째 걸 꺼내라"고 짜지 않고, 배열을 돌면서 dsList 키를 가진 덩어리를 찾도록 했어요. 순서가 언제 바뀔지 모르니까요.

한 건일 때만 모양이 바뀌어요

마이홈에서는 다른 종류의 함정을 만났어요. 평소엔 목록이 배열로 오는데, 결과가 딱 한 건일 때는 배열이 아니라 그냥 객체 하나로 옵니다.

  • 여러 건: [ {...}, {...} ]
  • 한 건: {...}

이게 고약한 이유는 평소엔 멀쩡하다가 어느 날 갑자기 터지기 때문이에요. 공고가 여러 개일 땐 잘 돌다가, 하필 한 건만 남은 날 목록으로 처리하려다 깨집니다. 그것도 새벽에요.

그래서 받은 게 객체면 원소 하나짜리 배열로 감싸고 넘어가게 했어요. 몇 줄 안 되는데, 이런 게 없으면 어느 날 조용히 멈춰 있습니다.

같은 걸 부르는 이름이 네 가지였어요

구조를 통과해도 필드 이름이 또 제각각이었어요. 똑같이 "공고 제목"과 "상세 링크"인데 이렇습니다.

소스공고명상세 링크
K-Startupbiz_pbanc_nmdetl_pg_url
기업마당pblancNmpblancUrl
LHPAN_NMDTL_URL
마이홈pblancNmpcUrl
든든전세없음없음

소문자에 밑줄, 낙타등, 전부 대문자가 다 섞여 있어요. 기업마당과 마이홈만 pblancNm으로 우연히 겹치고, 그마저 링크 이름은 다릅니다.

든든전세는 아예 제목 필드가 없어서 지역·유형·면적을 조합해 제목을 만들어 붙였어요. 3편에서 상세 링크가 없다고 했는데, 제목도 없었던 거죠.

정리 — 그래서 소스마다 파일을 나눴어요

처음엔 파싱 코드를 하나로 합치려고 했어요. "어차피 다 공고 목록인데" 싶었거든요.

금방 포기했습니다. 공통점이 거의 없었어요. 형식도, 목록 위치도, 필드 이름도, 심지어 "없을 때 어떻게 주는지"까지 달랐으니까요.

그래서 방향을 바꿨어요. 소스 하나에 파일 하나. 각자 자기 API의 이상한 점을 자기 파일 안에서 처리하고, 밖으로는 똑같은 모양으로 내보내게 했죠. 제목, 링크, 기관, 기간, 지역. 이 다섯 가지로 통일해서요.

이렇게 하니 새 소스를 붙일 때 다른 파일을 안 건드려도 됩니다. 나중에 알림 채널을 늘리거나 필터를 얹을 때도 이 구조가 계속 도움이 됐어요.

다음 편

구조를 다 맞췄더니 이번엔 같은 공고가 매시간 오기 시작했어요. 봇이 처음 본 것과 이미 본 것을 구분하지 못하면 벌어지는 일. → 5편 — 같은 공고가 계속 왔습니다


(이전 편: 3편 — 목록에 없는 API를 직접 찾아냈습니다)

댓글