2026년 9월 6일 일요일

[바이브 코딩] GBIF - 전 세계 생물 기록으로 만드는 우리 반 종 도감 (한국어 이름 검색까지)



전 세계 생물 기록으로 만드는 우리 반 종 도감 — GBIF API 완전 정복

🐻 API 키 없이 무료로, 전 세계 박물관·연구기관·시민과학자가 모은 생물 관찰·표본 기록의 세계 최대 공유 창고 GBIF(세계생물다양성정보기구)를 씁니다. 학명 검색에서 한국어 이름, 우리나라 관찰 기록, 멸종위기 등급까지 한 번에 꺼낼 수 있습니다.

실측(2026-09-05): '반달가슴곰' 한국어 검색 → 학명 Ursus thibetanus + 한국어 이름 2개(반달가슴곰·아시아흑곰) + IUCN 취약(VULNERABLE) 표기 + 국내 관찰 기록 4건. 생태계·생물 다양성 단원의 디지털 도감이자, 학내망 '외부 호출 0' 원칙을 관심 종 심기로 지키는 앱이 됩니다.

📖 한 줄 정의

심기 모드(데이터 임베딩): API 데이터를 미리 받아 HTML 파일 안 상수로 박아두는 방식(앱 실행 중 외부 통신 0).

학내망 원칙: 학교 배포 웹앱은 개인정보 수집·저장·전송 없음(외부 CDN·API 호출 0, 단일 파일) — 학생은 학내망에서 교사 PC 서버에 접속.

1. 3대 핵심 분석 비교표

무엇이 바뀌었나요? / 영역 초보자를 위한 쉬운 설명 이렇게 한번 써보세요!
GBIF란 세계 각국이 표본·관찰 기록을 한곳에 모은 국제 공유 기구입니다. 가입도, API 키도 없이 무료로 JSON을 돌려줍니다(오늘 실측). 브라우저에 species/match?name=Panthera%20tigris 를 입력 → 호랑이 학명 매칭 즉시 확인.
두 단계 검색 ① 학명 매칭(species/match — 실측 신뢰도 97~99) ② 자유 검색(species/search?q=) — 한국어로도 됩니다! 실측: q=반달가슴곰 → 학명·한국어 이름·등급이 한 번에. species/search?q=호랑이 → Panthera tigris 발견, 위기(ENDANGERED) 등급 확인.
데이터 모양 종 한 장에 분류 사다리(동물계 > 척삭동물문 > 포유강 > 식육목 > 곰과) + 전 세계 언어별 이름 목록(vernacularNames — kor 포함) + 위기 등급(threatStatuses)이 들어 있습니다. vernacularNames에서 language가 "kor"인 것만 골라 크게 표시하기.
국내 관찰 기록 occurrence(관찰 기록) 검색에 country=KR을 붙이면 우리나라 기록만 셀 수 있습니다. 실측: 반달가슴곰 국내 기록 4건. 우리 반 관심 종의 국내 기록 수를 세어 순위표 만들기.
학내망 배포 대응 종 데이터는 거의 바뀌지 않으므로 심기 모드와 찰떡입니다. 관심 종 20종 카드를 슬림화해 심으면 학생 단말은 통신 0으로 돌아갑니다. fetch 실시간 모드 → 교사 PC 시연용. 심기 모드 → 학내망 배포용. EMBED_DATA 상수 하나로 전환.

2. 핵심 아키텍처 해설 — 종 도감은 이렇게 생겼다

① URL 해부: match와 search의 역할

https://api.gbif.org/v1/species/search?q=반달가슴곰&limit=5

  • api.gbif.org/v1 — GBIF 데이터 창고 버전 1. 뒤에 자원 이름이 붙습니다.
  • species/match?name=학명 — '이 학명 찾아줘' 매칭. 실측: Ursus thibetanus → 곰과(Ursidae)까지 분류 사다리와 신뢰도 97이 돌아왔습니다.
  • species/search?q=검색어 — 자유 검색. 한국어도 됩니다. 주소에는 한국어를 그대로 쓸 수 없으니 encodeURIComponent로 변환해야 합니다.
  • occurrence/search — 관찰 기록. taxonKey(종 번호)와 country=KR을 붙여 국내 기록만 셉니다.

CORS 실측: GBIF는 요청에 Origin이 있을 때(브라우저는 항상 실어 보냅니다) Access-Control-Allow-Origin: * 를 돌려줍니다 — 브라우저에서 바로 fetch OK.

② 데이터 모양: 종 한 장에는 이것이 들어 있다

{
  "count": 3,
  "results": [{
    "canonicalName": "Ursus thibetanus",
    "kingdom": "Animalia",
    "phylum": "Chordata",
    "class": "Mammalia",
    "order": "Carnivora",
    "family": "Ursidae",
    "nubKey": 9335699,
    "threatStatuses": ["VULNERABLE"],
    "vernacularNames": [
      { "vernacularName": "아시아흑곰", "language": "kor" },
      { "vernacularName": "반달가슴곰", "language": "kor" }
    ]
  }]
}

분류 사다리(계 > 문 > 강 > 목 > 과)는 학교 실험실 벽 걸이 도표 그대로입니다. VULNERABLE은 IUCN 위기 등급 '취약' — 호랑이 검색에서는 ENDANGERED(위기)가 실측되었습니다.

③ 한국어 이름 꺼내기

const koNames = sp.vernacularNames
  .filter(function (v) { return v.language === "kor"; })
  .map(function (v) { return v.vernacularName; });
// 결과 예: ["아시아흑곰", "반달가슴곰"]

④ 검색 코드: 한국어를 주소에 실으려면

const API = "https://api.gbif.org/v1";

async function findSpecies(word) {
  const res = await fetch(API + "/species/search?q=" + encodeURIComponent(word) + "&limit=5");
  const json = await res.json();
  return json.results;   // 각 결과: scientificName, vernacularNames, threatStatuses...
}

⑤ 국내 기록 세기와 심기 전략

async function countKoreaRecords(nubKey) {
  const res = await fetch(API + "/occurrence/search?country=KR&taxonKey=" + nubKey + "&limit=20");
  const json = await res.json();
  return json.count;   // 우리나라 관찰 기록 수
}

같은 종이 데이터셋마다 여러 개의 key를 가질 수 있으므로, 통합 열쇠인 nubKey를 쓰는 습관이 중요합니다. 심기 모드(데이터 임베딩)로 만들 때는 관심 종 20종의 카드 데이터(학명·한국어 이름·등급·국내 기록 수)를 슬림화해 EMBED_DATA에 심습니다 — 종 정보는 1년에 거의 바뀌지 않으니 학기 초에 한 번 갱신이면 충분합니다.

3. 초보자를 위한 바이브 코딩 실전 사용 예시

  1. 프롬프트 복사 — 아래 '제미나이 전용 에러 제로 프롬프트' 전체를 복사해 Gemini에 붙여넣습니다.
  2. 역질문 답변 — Gemini가 던지는 질문 3가지(어떤 생물, 데이터 모드, 화면 톤)에 답하면 설계가 확정됩니다.
  3. HTML 파일 실행 — 완성 코드를 '종도감.html'로 저장 후 더블클릭. 심기 모드 파일이면 곧 학내망 배포본입니다.

제미나이 전용 에러 제로 프롬프트

[🚨 에러 방지 기본 안전장치]
1. 결과물은 외부 라이브러리·프레임워크·웹폰트 없이 단일 HTML 파일로 완성한다. (GBIF 데이터 fetch는 유일한 외부 통신 예외)
2. 사운드는 Web Audio API로 직접 합성한다: 검색 성공 시 부드러운 '똑' 소리, 결과 0건·통신 실패 시 '삑' 경고음과 함께 '비슷한 이름으로 다시 검색해 보자' 안내 화면을 보여준다.
3. 모바일 터치 대응: 뷰포트 메타 태그 필수, 버튼 최소 44×44px, 입력 필드 font-size 16px 이상, 360px 화면에서 가로 스크롤 금지.
4. 한국어 검색어는 반드시 encodeURIComponent로 인코딩해 주소에 붙인다(species/search?q=...).
5. vernacularNames에서 language가 "kor"인 이름만 골라 크게 표시하고, 학명(canonicalName)을 옆에 함께 보여준다.
6. threatStatuses는 사람이 읽는 한국어 라벨로 바꿔 보여준다(예: VULNERABLE=취약, ENDANGERED=위기).
7. 파일 상단 EMBED_DATA 상수에 관심 종 카드 데이터가 심어져 있으면 fetch를 완전히 생략한다(학내망 배포용 외부 호출 0 모드). 카드에는 국내 관찰 기록 수(occurrence country=KR)도 함께 표시한다.
8. // TODO, /* 생략 */ 같은 미완성 코드는 절대 넣지 말고 끝까지 완성한다.

[❓ 역질문 유도]
코드를 바로 만들지 말고, 아래 3가지를 먼저 나에게 질문한 뒤 내 답변으로 설계를 확정한다.
Q1. 어떤 생물을 위주로 할까? (교내·지역 서식 종 / 세계 유명 종 / 멸종위기 종)
Q2. 데이터 모드는 무엇으로 할까? (A: 실시간 fetch 모드 / B: 학내망용 관심 종 심기 모드)
Q3. 화면 톤은? (종 카드 도감 / 분류 사다리 그리기 / 국내 관찰 기록 수 순위)

🎯 에디터 한줄평

학명과 '반달가슴곰'이 나란히 화면에 뜨는 순간, 아이들은 '생물의 이름에는 세계 공통 규약이 있다'는 걸 스스로 발견합니다 — 이것이 이 앱의 진짜 교육적 수확입니다. 여기에 위기 등급(VULNERABLE) 라벨과 국내 관찰 기록 4건이라는 숫자가 더해지면, '생물다양성'과 '과학은 기록 위에 쌓인다(시민과학)'는 이야기가 던짓 없이 시작됩니다. 관찰 기록의 좌표까지 다루는 단계는 개인정보 관점에서 조심해야 하니, 교실 배포본은 종 카드 중심으로 심기 모드(데이터 임베딩)를 쓰는 이번 설계가 정답에 가깝습니다.

📚 기술·교육 참고 링크

  • GBIF 공식 사이트 : 기구 소개·웹 종 검색·이용 약관(데이터 라이선스)
  • GBIF 개발자 문서 : species·occurrence 엔드포인트 전체 정리
  • 관찰 기록 웹 검색 : API 없이 웹에서 국내 기록 탐색 연습
  • 교육과정 연계: 과학(생태계 구성·생물 다양성), 사회(시민과학·국제 협력), 국어(이름과 분류 어휘)와 함께 활용