공공 데이터를 API로 가져와 데이터베이스에 저장하는 방법입니다.
여기서는 Supabase를 사용했습니다.
node-fetch와 Supabase 클라이언트가 필요합니다.
npm install node-fetch @supabase/supabase-js
Supabase는 클라우드 기반 데이터베이스입니다.
import { createClient } from '@supabase/supabase-js';
const SUPABASE_URL = 'https://xxxxxxxxxxxxxx.supabase.co';
const SUPABASE_ANON_KEY = 'your-servicekey';
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
데이터를 가져올 API는 공공 데이터 포털에서 제공하고, 가공식품 및 음식 정보를 반환합니다.
API 호출을 통해 100개씩 데이터를 가져와서 페이지 단위로 전체 데이터를 수집합니다.
const fetchData = async (pageNo) => {
const url = `${API_URL}?serviceKey=${SERVICE_KEY}&pageNo=${pageNo}&numOfRows=100&type=json`;
console.log(url);
try {
const response = await fetch(url);
const data = await response.json();
if (data.response?.header?.resultCode !== '00') {
console.error('API 요청 오류:', data.response?.header?.resultMsg || '알 수 없는 오류');
return null;
}
return {
items: data.response.body.items,
totalCount: Number(data.response.body.totalCount),
pageNo: Number(data.response.body.pageNo),
};
} catch (error) {
console.error('데이터를 가져오는 중 오류가 발생했습니다:', error);
return null;
}
};
공공 데이터를 페이지 단위로 호출하여 JSON 형식으로 데이터를 반환합니다.
Supabase에 데이터를 삽입하는 함수입니다.
const insertDataToSupabase = async (items) => {
for (const item of items) {
const processedItem = {
foodcd: item.foodCd || 'N/A',
foodnm: item.foodNm || 'N/A',
datacd: item.dataCd || 'N/A',
typenm: item.typeNm || 'N/A',
foodorigincd: item.foodOriginCd || 'N/A',
...
중략
...
distnm: item.distNm || 'N/A',
imptyn: item.imptYn || 'N',
coocd: item.cooCd || 'N/A',
coonm: item.cooNm || 'N/A',
dataprodcd: item.dataProdCd || 'N/A',
dataprodnm: item.dataProdNm || 'N/A',
crtymd: item.crtYmd || null,
crtrymd: item.crtrYmd || null,
insttcode: item.insttCode || 'N/A',
};
try {
const { data, error } = await supabase.from('processedfood').insert([processedItem]);
if (error) {
console.error('데이터 저장 중 오류가 발생했습니다:', error.message);
console.error('오류 세부 정보:', JSON.stringify(error, null, 2));
} else {
console.log('데이터가 성공적으로 저장되었습니다:', JSON.stringify(data, null, 2));
}
} catch (err) {
console.error('삽입 중 try-catch 오류 발생:', err);
}
}
};
이 함수는 items 배열의 각 항목을 하나씩 데이터베이스에 삽입하고
각 필드가 일치하도록 매핑하며 오류가 발생할 경우 구체적인 오류 메시지를 출력합니다.

전체 데이터는 한 번의 호출로 가져올 수 없기 때문에 반복 호출을 통해 페이지별 데이터를 조회합니다.
const main = async () => {
let pageNo = 1;
let fetchedData;
do {
console.log(`${pageNo}번째 페이지 데이터를 가져오는 중...`);
fetchedData = await fetchData(pageNo);
if (fetchedData && fetchedData.items && fetchedData.items.length > 0) {
await insertDataToSupabase(fetchedData.items);
pageNo++;
} else {
console.log('더 이상 가져올 데이터가 없습니다.');
break;
}
} while (fetchedData !== null);
};
main().catch((error) => console.error('스크립트 실행 중 오류가 발생했습니다:', error));
이 함수는 각 페이지의 데이터를 가져오고 Supabase에 데이터를 저장한 후
데이터가 더 이상 없을 때 까지 반복합니다.


전체 소스 코드
import fetch from 'node-fetch';
import { createClient } from '@supabase/supabase-js';
// Supabase 설정
const SUPABASE_URL = 'https://supabase.co';
const SUPABASE_ANON_KEY = ''; // Supabase의 익명 키
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
// API 설정
// const API_URL = 'http://api.data.go.kr/openapi/tn_pubr_public_nutri_process_info_api'; //가공식품;
const API_URL = 'http://api.data.go.kr/openapi/tn_pubr_public_nutri_food_info_api'; //음식
const SERVICE_KEY = '';
// 데이터 가져오기 함수
async function fetchData(pageNo) {
const url = `${API_URL}?serviceKey=${SERVICE_KEY}&pageNo=${pageNo}&numOfRows=500&type=json`;
try {
const response = await fetch(url);
const data = await response.json();
// API 응답이 정상인지 확인
if (data.response?.header?.resultCode !== '00') {
console.error('API 요청 오류:', data.response?.header?.resultMsg || '알 수 없는 오류');
return null;
}
// 데이터가 없는 경우
if (!data.response.body.items || data.response.body.items.length === 0) {
console.log('가져온 데이터가 없습니다.');
return { items: [], totalCount: 0 }; // 빈 배열과 0을 반환
}
return {
items: data.response.body.items,
totalCount: Number(data.response.body.totalCount),
pageNo: Number(data.response.body.pageNo),
};
} catch (error) {
console.error('데이터를 가져오는 중 오류가 발생했습니다:', error);
return null;
}
}
// Supabase에 데이터 저장 함수
async function insertDataToSupabase(items) {
for (const item of items) {
const foodItem = {
foodcd: item.foodCd || 'N/A',
foodnm: item.foodNm || 'N/A',
};
try {
const { data, error } = await supabase.from('food').insert([foodItem]);
if (error) {
console.error('데이터 저장 중 오류가 발생했습니다:', error.message);
console.error('오류 세부 정보:', JSON.stringify(error, null, 2));
} else {
console.log('데이터가 성공적으로 저장되었습니다 : ', JSON.stringify(data, null, 2));
}
} catch (err) {
console.error('삽입 중 try-catch 오류 발생:', err);
}
}
}
// 반복 호출을 통한 데이터 수집 및 저장
async function main() {
let pageNo = 1;
let fetchedData;
do {
console.log(`${pageNo}번째 페이지 데이터를 가져오는 중...`);
fetchedData = await fetchData(pageNo);
if (fetchedData && fetchedData.items && fetchedData.items.length > 0) {
// Supabase에 데이터 저장
await insertDataToSupabase(fetchedData.items);
pageNo++;
} else {
console.log('더 이상 가져올 데이터가 없습니다.');
break;
}
} while (fetchedData !== null);
}
// 메인 함수 실행
main().catch((error) => console.error('스크립트 실행 중 오류가 발생했습니다:', error));