4화에서 이야기했습니다. 한국 정부가 식품 관련 데이터를 공개하고 있다고요. 제품 정보, 원재료, 영양성분. API라는 창구를 통해 누구나 받아볼 수 있다고요.
그러면 이제 실제로 받아봐야겠죠.
처음에 저는 이렇게 생각했습니다. ‘API 신청하고, 데이터 받아오고, 저장하면 되는 거 아닌가?’
맞습니다. 원리는 그래요. 그런데 그 사이에 들어있는 세부사항이 문제였습니다.
AI에게 물어봤어요. “식약처 API에서 제품 데이터를 가져오려면 어떻게 해야 하나요?”
돌아온 대답은 친절했지만, 길었습니다. 그리고 그 안에는 제가 처음 듣는 말들이 가득했어요.
ETL이라는 단어가 있었습니다. Extract, Transform, Load. 데이터를 ‘가져오고’(Extract), ‘가공하고’(Transform), ‘저장한다’(Load).
쉽게 말하면 이런 거예요. 마트에서 장을 본다고 생각해보세요. 재료를 사 오고(Extract), 씻고 손질하고(Transform), 냉장고에 넣는다(Load).
요리를 하려면 그 전에 이 과정이 필요하듯이, 데이터를 서비스에 쓰려면 ETL이 먼저 필요합니다.
그래서 제가 연결해야 하는 API가 몇 개인지 세어봤습니다.
식약처 쪽에 있는 것들. 제품의 기본 정보(품목제조보고). 제품에 들어간 원재료 목록(품목제조보고 원재료). 원재료의 표준 코드 사전. 원재료의 일반 정보. 품목 유형 코드.
공공데이터포털이라는 곳에도 식품 관련 API가 있었습니다. 식품 영양성분 데이터베이스. 식품 원재료 정보.
거기에 CSV 파일로만 제공되는 데이터도 있었습니다. 전국통합식품영양성분정보라는 것인데, API로는 제공되지 않아서 파일을 직접 내려받아야 했어요.
처음에 파악한 것만 해도 여러 종류였습니다. 각각 형식이 다르고, 제공하는 곳이 다르고, 응답 구조도 달랐습니다. (나중에 더 늘어나게 되는데, 그건 7화에서 이야기하겠습니다.)
가장 먼저 시도한 건 제품 기본 정보였습니다. 한국에서 제조 신고된 식품 제품의 목록이요.
API에 요청을 보내면, 제품 정보가 돌아옵니다. 제품 이름, 제조사, 유통기한, 품목 유형 같은 것들.
그런데 한 번에 받아올 수 있는 건 1,000건까지였습니다. 전체 제품 수는 약 104만 건.
그러니까, 1,000건씩 1,040번 이상 요청을 보내야 전체 제품 목록을 받아올 수 있다는 뜻이었어요.
중간에 응답이 느려지기도 했습니다. 30초 안에 답이 안 와서 연결이 끊기는 경우도 있었고요. 특히 뒤쪽 페이지로 갈수록 이런 일이 잦아졌습니다. 그러면 어디까지 받았는지 기억해뒀다가, 그 다음부터 다시 이어서 받아야 했습니다.
그리고 또 헷갈리는 일이 있었어요. 요청을 보냈는데 “해당하는 데이터가 없습니다”라는 답이 올 때가 있었거든요. 이게 정말 데이터가 없는 건지, 아니면 뭔가 잘못된 건지 구분이 안 됐습니다. 정상적인 빈 결과와 오류 상황이 같은 모양으로 돌아왔어요.
처음 전체 제품 데이터를 다 받아오는 데 걸린 시간은, 솔직히 기억이 정확하지는 않지만, 꽤 오래 걸렸습니다.
제품 목록을 받아왔으니, 다음은 원재료 데이터였습니다.
이건 더 까다로웠어요.
제품마다 어떤 원재료가 들어갔는지를 알려주는 API인데, 이 데이터가 약 98만 건이었습니다. 역시 조금씩 나눠서 받아와야 했고, 중간에 끊기면 이어서 받아야 했습니다.
그리고 여기서 한 가지 중요한 사실을 알게 됐어요.
이 API가 돌려주는 원재료 이름은, 표준화된 코드가 아니라 제조사가 직접 입력한 자유 텍스트였습니다.
무슨 뜻이냐면요. 1화에서 이야기한 그 문제가 여기서 다시 나타난 거예요. 같은 원재료인데 제조사마다 다르게 적는 것. ‘설탕’, ‘정백당’, ‘백설탕’, ‘정제당’. 이런 것들이 전부 다른 이름으로 들어와 있었습니다.
데이터가 공개되어 있다고 해서 깔끔하게 정리된 상태로 오는 건 아니었던 거죠.
영양성분 데이터는 또 다른 이야기였습니다.
공공데이터포털에서 제공하는 식품 영양성분 API가 있었는데, 이건 약 27만 건의 데이터를 가지고 있었습니다. 열량, 탄수화물, 단백질, 지방, 나트륨 같은 영양 정보들.
그런데 같은 종류의 데이터가 CSV 파일로도 따로 제공되고 있었어요. API에만 있는 데이터가 있고, CSV에만 있는 데이터도 있었습니다. 같은 기관에서 제공하는 같은 종류의 정보인데, 두 군데에 나뉘어 있었던 거예요.
완전한 데이터를 확보하려면 양쪽 다 받아서 합쳐야 했습니다.
여기까지 하고 나서 깨달은 것이 있습니다.
데이터를 ‘가져오는 것’은 시작일 뿐이라는 것.
받아온 데이터는 제각각이었습니다. 이름 짓는 방식이 다르고, 같은 제품을 가리키는 번호도 API마다 달랐습니다.
응답이 돌아오는 형식도 API마다 달랐습니다. 같은 정부 포털에서 제공하는 API인데, 어떤 건 데이터가 목록으로 오고, 어떤 건 목록 안에 또 다른 상자에 담겨서 오고, 어떤 건 데이터가 없을 때 빈 목록 대신 아무것도 안 오는 거예요.
같은 질문을 했는데 대답하는 형식이 제각각인 셈이에요. 그래서 API를 새로 연결할 때마다 “이번에는 어떤 형식으로 오려나” 하고 먼저 살펴봐야 했습니다.
식약처에서는 ‘PRDLST_REPORT_NO’라고 부르는 것을 공공데이터포털에서는 ‘prdlstReportNo’라고 불렀어요. 같은 것인데 이름이 달라서, “이 데이터와 저 데이터가 같은 제품을 가리키고 있다”는 것을 프로그램이 자동으로 알아채지 못합니다.
하나하나 연결해줘야 했어요. 이 API의 이 필드가 저 API의 저 필드와 같은 것이라고.
열한 개의 API에서 데이터를 받아와서 하나의 데이터베이스에 정리하는 일. 이걸 전문 용어로는 ‘ETL 파이프라인을 구축한다’고 합니다.
저는 이 말의 뜻을 나중에야 제대로 이해했지만, 만드는 과정에서 몸으로 먼저 배웠습니다.
API마다 받아오는 코드를 따로 만들어야 했고, 중간에 끊겨도 이어서 받을 수 있게 해야 했고, 받아온 데이터에서 필요한 부분만 골라서 저장해야 했고, 이미 저장한 데이터와 새로 받아온 데이터가 겹치면 어떻게 할지도 정해야 했습니다.
그리고 한 가지 당황스러운 점이 있었습니다. “어제 이후로 바뀐 데이터만 주세요”라고 요청할 수가 없었어요. API 응답에는 수정일 정보가 포함되어 있는데, 정작 그 날짜로 필터링하는 기능은 없었습니다.
그러니까 새로 바뀐 제품이 열 건이든, 한 건이든, 매번 104만 건을 처음부터 다시 받아와야 했어요.
이 과정은 눈에 보이지 않는 작업이에요. 사용자가 앱을 열었을 때 보이는 건 예쁜 화면이지만, 그 화면에 제품 정보가 표시되려면 뒤에서 이런 작업이 전부 끝나 있어야 합니다.
결국, 열한 개의 API를 전부 연결하는 데 꽤 오랜 시간이 걸렸습니다.
제품 104만 건. 원재료 98만 건. 영양성분 28만 건. 원재료 표준 사전 4만 3천 건. 거기에 품목 유형 코드까지.
이 숫자들을 보면 대단해 보일 수 있지만, 사실 이건 그냥 ‘재료를 사 온 것’에 가깝습니다. 마트에서 장을 봐온 거예요.
이제부터 해야 하는 건, 이 재료들을 가지고 요리를 하는 것. 데이터를 담을 그릇을 만들고, 정리하고 연결하는 작업이었습니다.
다음 화에서 그 이야기를 하겠습니다. 100만 개의 제품 데이터를 담을 그릇, 즉 데이터베이스를 설계한 이야기요.