13화에서 데이터 무결성에 대한 원칙을 세운 이야기를 했습니다. 교차 검증, 전체 검증, 검증 없는 데이터는 저장하지 않기.
그 원칙을 적용하면서 영양성분 데이터를 다시 들여다봤는데, 또 다른 문제가 있었습니다.
한국에서 포장 식품을 팔려면, 영양정보를 의무적으로 표시해야 합니다.
열량, 탄수화물, 당류, 단백질, 지방, 포화지방, 트랜스지방, 콜레스테롤, 나트륨. 이 아홉 가지 항목이에요.
마트에서 아무 제품이나 뒤집어보면 영양정보표가 있고, 이 아홉 가지가 적혀 있습니다.
그러니까 이 데이터는 세상에 존재합니다. 모든 포장 식품의 겉면에 인쇄되어 있으니까요.
문제는 이 데이터가 디지털화되어 있느냐는 거였습니다.
공공데이터포털에서 제공하는 식품 영양성분 API를 확인했습니다. 약 27만 건의 데이터가 있었어요.
그런데 데이터를 자세히 들여다보니, 아홉 가지 의무 영양소가 전부 채워져 있는 비율이 극히 낮았습니다.
포화지방이 채워져 있는 비율: 0.2%. 트랜스지방: 0.1%. 콜레스테롤: 0.3%. 나트륨도 2.0%에 불과했습니다.
0.1%요. 27만 건 중에서 트랜스지방 정보가 들어 있는 건 270건 정도라는 뜻입니다.
열량, 탄수화물, 단백질, 지방 같은 기본 항목은 비교적 잘 채워져 있었지만, 나머지 의무 항목들은 거의 비어 있었어요.
이건 데이터베이스의 문제이지, 현실의 문제가 아닙니다.
실제 제품에는 이 정보가 다 인쇄되어 있어요. 법적으로 의무니까요. 그런데 그 정보가 디지털 데이터베이스에는 반영되지 않은 거예요.
포장지에 인쇄되어 있는 정보와, API를 통해 접근할 수 있는 정보가 다른 겁니다.
1화에서 했던 이야기가 또 떠오릅니다. “공개되어 있다”와 “쓸 수 있다”는 다르다고요. 이건 한 단계 더 나가서, “존재한다”와 “디지털로 접근 가능하다”가 다른 경우였습니다.
그래서 다른 소스를 찾아봤습니다.
같은 기관에서 CSV 파일로 제공하는 영양성분 데이터가 따로 있었는데, 이쪽은 의무 아홉 가지가 100% 채워져 있었습니다. 하지만 커버하는 제품 수가 적었어요.
재미있는 건, API에만 있는 데이터가 있고 CSV에만 있는 데이터도 있었다는 겁니다. 같은 기관에서 같은 종류의 정보를 제공하는데, 두 군데에 나뉘어 있고 서로 보완하는 관계였어요. 완전한 데이터를 확보하려면 양쪽 다 받아서 합쳐야 했습니다.
그런데 CSV 쪽은 API가 없었습니다. 포털에 가서 파일을 직접 내려받아야 했어요. 자동으로 갱신할 수 없다는 뜻이죠. 언제 데이터가 바뀌었는지도 알 수 없었고요.
두 데이터를 합치면 커버리지가 늘어나긴 하지만, 그래도 104만 제품 중 영양정보가 연결된 건 전체의 일부에 불과했습니다.
다행히, 한 가지 긍정적인 발견이 있었습니다.
영양성분 API의 응답을 자세히 살펴보다가, ‘품목제조보고번호’라는 필드가 포함되어 있다는 걸 발견했어요. 이 번호가 우리 제품 데이터의 번호와 같은 체계였습니다.
11화에서 이야기한 것처럼, 공공데이터의 번호 체계가 서로 달라서 연결이 안 되는 경우가 많았는데 이번에는 달랐어요. 이 번호 하나로 영양성분 데이터를 제품에 직접 연결할 수 있었습니다.
이름이나 제조사를 비교해서 “이것 같다”고 추측하는 게 아니라, 번호가 정확히 일치하는 것끼리만 연결하는 거예요. 13화에서 세운 원칙 그대로.
이 방법으로 13만 건 이상의 제품에 영양정보를 연결할 수 있었습니다.
그리고 또 하나의 가능성을 발견했습니다.
HACCP 인증 정보를 제공하는 API가 있었는데, 여기에 ‘포장지 표기 정보’라는 필드가 있었어요.
이 필드에 실제 포장지에 인쇄된 영양정보 텍스트가 그대로 들어가 있는 경우가 있었습니다.
예를 들면 이런 식이에요.
열량 150kcal, 탄수화물 20g, 당류 5g, 단백질 3g, 지방 6g, 포화지방 3g, 트랜스지방 0g, 콜레스테롤 0mg, 나트륨 200mg
이건 구조화된 데이터가 아니라, 포장지에 적힌 그대로의 텍스트입니다. 사람이 읽으면 바로 이해할 수 있지만, 프로그램이 쓰려면 다시 파싱을 해야 합니다.
또 파싱입니다.
8화, 9화에서 원재료 파싱을 했는데, 이번에는 영양성분 텍스트를 파싱하는 거예요.
“열량 150kcal”에서 “열량”이라는 항목명과 “150”이라는 수치와 “kcal”이라는 단위를 분리해내는 작업.
원재료 파싱보다는 규칙이 단순했지만, 제품마다 표기 방식이 달라서 역시 예외 처리가 필요했습니다.
어떤 제품은 “열량: 150kcal”이고, 어떤 제품은 “열량 150 kcal”이고, 어떤 제품은 “에너지 150킬로칼로리”라고 적혀 있었거든요.
이 작업을 통해 1,600건 정도의 영양정보를 추가로 확보할 수 있었습니다.
많은 숫자는 아닙니다. 104만 제품에 비하면 아주 적어요.
하지만 이 1,600건은 의무 아홉 가지 영양소가 전부 채워져 있는 질 높은 데이터였습니다.
이 경험에서 배운 것이 있습니다.
데이터의 ‘양’과 ‘질’은 다른 문제라는 것.
27만 건의 영양성분 데이터가 있다고 하면 많아 보이지만, 정작 필요한 항목이 0.1%만 채워져 있으면 그 데이터로 할 수 있는 일이 매우 제한됩니다.
반면에, HACCP 포장지 텍스트에서 파싱한 1,600건은 수는 적지만 실제로 사용자에게 보여줄 수 있는 완전한 데이터였어요.
숫자가 크다고 좋은 데이터가 아니고, 숫자가 작다고 나쁜 데이터가 아닙니다.
영양정보 문제는 아직 완전히 해결되지 않았습니다. 104만 제품 중 대다수는 아직 영양정보가 연결되어 있지 않아요.
이건 데이터가 공개되지 않아서가 아닙니다. 모든 포장 식품의 겉면에 인쇄되어 있으니까요. 디지털로 접근할 수 있는 경로가 충분하지 않을 뿐입니다.
이 부분은 20화에서 다시 이야기하겠습니다.
다음 화에서는 원재료 이야기로 돌아가겠습니다. “L-글루탐산나트륨”이 대체 뭔지, 첨가물의 이름을 어떻게 사람이 이해할 수 있는 말로 바꿨는지에 대해서요.