스타워즈 6편의 우주를 데이터로 탐사하는 은하수 도감 — SWAPI 완전 정복
🌌 SWAPI(swapi.dev)는 스타워즈 세계관 데이터(영화 6편·인물·행성·스타십·종·탈것)를 무료로 제공하는 팬메이드 API입니다. API 키 없이 열리며, 오늘 실측으로 search=skywalker 한 번에 루크·아나킨·쉬미 3대가 나란히 검색되는 것, 응답이 {count, next, previous, results} 표준 봉투(envelope) 구조로 오는 것, format=wookiee로 우키어(웨이스의 언어) 번역 응답까지 가능한 것을 확인했습니다.
이 API의 진짜 교육적 보물은 관계 데이터가 '숫자'가 아니라 '주소(URL) 목록'으로 온다는 하이퍼미디어 구조입니다 — 웹의 본질을 만지는 첫 경험. 학내망 '외부 호출 0' 원칙은 관심 카드(에피소드 IV + 주요 인물) 심기로 통과합니다.
📖 한 줄 정의
심기 모드(데이터 임베딩): API 데이터를 미리 받아 HTML 파일 안 상수로 박아두는 방식(앱 실행 중 외부 통신 0).
학내망 원칙: 학교 배포 웹앱은 개인정보 수집·저장·전송 없음(외부 CDN·API 호출 0, 단일 파일) — 학생은 학내망에서 교사 PC 서버에 접속.
1. 3대 핵심 분석 비교표
| 무엇이 바뀌었나요? / 영역 | 초보자를 위한 쉬운 설명 | 이렇게 한번 써보세요! |
|---|---|---|
| API 정체 | 스타워즈 공식이 아니라 팬메이드 무료 API. 자원 6개(people 인물·planets 행성·films 영화·species 종·vehicles 탈것·starships 스타십), 키 없이 열립니다. 영화는 6편(에피소드 I~VI) 실측. | https://swapi.dev/api/ → 자원 6개 목록 확인. |
| 응답 봉투(envelope) | 목록 응답은 {count, next, previous, results} 봉투에 담겨 옵니다 — count는 전체 건수, next·previous는 다음·이전 페이지 주소. API의 페이지네이션 표준 구조를 그대로 배울 수 있습니다. | people/?search=skywalker → count 3(실측) 확인. |
| 데이터 모양 | height '172', birth_year '19BBY' — 숫자도 문자열, 연대는 BBY(야빈 전투 기준 세계관 연도). opening_crawl에는 줄바꿈 문자(\r\n)가 그대로 들어옵니다. 인물이 인간이면 species는 빈 배열(실측 함정). | Number(height)로 변환 후 표기, species 빈 배열엔 'Human(인간)' 기본값. |
| 관계는 주소로 | characters[]가 이름이 아니라 URL 목록으로 옵니다(에피소드 IV는 등장인물 18개 주소 — 실측). 주소를 따라가며 데이터를 연결하는 하이퍼미디어 구조, 웹의 본질입니다. | 인물 카드 → homeworld 주소 따라가 행성 카드 열기. |
| 학내망 배포 대응 | 관심 카드(에피소드 IV + 주요 인물 8명 등)를 미리 받아 슬림화해 심으면 학생 단말은 통신 0. 수치가 흥미로운 행성 카드(타투인: 하루 23시간·1년 304일 — 실측)도 심기 소재로 좋습니다. | EMBED_DATA에 카드 목록 심기 → 학내망 배포본 완성. |
2. 핵심 아키텍처 해설 — 은하수 창고는 이렇게 생겼다
① URL 해부: 루트가 안내판이다
https://swapi.dev/api/ 를 열면 자원 6개의 주소가 안내됩니다(실측): people, planets, films, species, vehicles, starships. 조건은 ?search=(검색), ?page=(페이지), ?format=wookiee(우키어 번역 — 재미용, 실측 200 OK). CORS는 Access-Control-Allow-Origin: * 로 열려 있습니다(실측).
② 봉투(envelope) 데이터 모양: search=skywalker 실측 예시
{
"count": 3,
"next": null,
"previous": null,
"results": [{
"name": "Luke Skywalker",
"height": "172",
"birth_year": "19BBY",
"gender": "male",
"homeworld": "https://swapi.dev/api/planets/1/",
"films": ["https://swapi.dev/api/films/1/", "..."],
"species": []
}]
}
실측 응답(간추림)입니다. count 3 = 루크·아나킨·쉬미, 스카이워커 3대가 한 번에 나옵니다. homeworld는 주소 — 타투인 행성 카드로 연결됩니다. species가 비어 있는 이유는 '인간은 종 목록에 등재되지 않은 기본값'이기 때문(실측) — 빈 배열 처리는 좋은 코딩 연습입니다.
③ 영화 자원: opening_crawl과 관계 목록
films/1(에피소드 IV)의 실측 구조: title "A New Hope", episode_id 4, opening_crawl(오프닝 크롤 텍스트, 줄바꿈 문자 포함), director "George Lucas", producer "Gary Kurtz, Rick McCallum", release_date "1977-05-25", 그리고 characters(18개 주소)·planets(3)·starships(8)·vehicles(4)·species(5)의 URL 목록. API는 결과를 에피소드 IV부터 나열합니다 — '번호 1번 = 에피소드 IV'라는 정렬 함정도 실측.
④ 행성 자원: 세계관 수치로 하는 진짜 단위 수업
planets/1 타투인(실측): rotation_period "23"(하루 길이), orbital_period "304"(1년 길이), diameter "10465", terrain "desert", population "200000". 지구의 하루·1년과 비교하는 활동이 곧 단위·비율 수업이 됩니다 — 모든 수치가 문자열이라 Number() 변환 연습도 함께.
⑤ 검색 코드와 관계 따라가기
const API = "https://swapi.dev/api";
async function searchPeople(word) {
const res = await fetch(API + "/people/?search=" + encodeURIComponent(word));
const json = await res.json();
return json; // json.count, json.next, json.results
}
async function follow(url) {
const res = await fetch(url);
return await res.json(); // characters[]의 주소를 하나씩 방문
}
학내망 배포용은 에피소드 IV 카드와 주요 인물 목록을 미리 받아 슬림화한 뒤 EMBED_DATA로 심습니다. 심기 모드(데이터 임베딩)가 무엇인지는 앞의 '📖 한 줄 정의' 박스를 참고하세요 — 상태가 절대 바뀌지 않는 세계관 데이터는 심기와 궁합이 좋습니다.
3. 초보자를 위한 바이브 코딩 실전 사용 예시
- 프롬프트 복사 — 아래 '제미나이 전용 에러 제로 프롬프트' 전체를 복사해 Gemini에 붙여넣습니다.
- 역질문 답변 — Gemini가 던지는 질문 3가지(자원 중심, 데이터 모드, 화면 톤)에 답하면 설계가 확정됩니다.
- HTML 파일 실행 — 완성 코드를 '은하수도감.html'로 저장 후 더블클릭. 심기 모드 파일이면 곧 학내망 배포본입니다.
제미나이 전용 에러 제로 프롬프트
[🚨 에러 방지 기본 안전장치]
1. 결과물은 외부 라이브러리·프레임워크·웹폰트 없이 단일 HTML 파일로 완성한다. (SWAPI 데이터 fetch는 유일한 외부 통신 예외)
2. 사운드는 Web Audio API로 직접 합성한다: 검색 성공 시 부드러운 '똑' 소리, 결과 0건·통신 실패 시 '삑' 경고음. 오디오 파일·CDN 사운드 사용 금지.
3. 모바일 터치 대응: 뷰포트 메타 태그 필수, 버튼 최소 44×44px, 입력 필드 font-size 16px 이상, 360px 화면에서 가로 스크롤 금지.
4. 응답 봉투 {count, next, previous, results} 구조를 그대로 처리한다: count는 항상 화면에 표시하고, next가 null이 아닐 때 '더 보기' 버튼으로 다음 페이지를 이어서 불러온다.
5. height·mass·diameter 같은 수치 칸은 문자열로 오므로 Number()로 변환하고 천 단위 콤마로 표기한다. 'unknown' 같은 특수 값도 그대로 보여준다.
6. opening_crawl의 줄바꿈 문자(\r\n)는 화면용으로 정리해서 보여주고, 인물의 species가 빈 배열이면 'Human(인간)' 기본값을 보여준다.
7. 파일 상단 EMBED_DATA에 카드 목록이 심어져 있으면 fetch를 완전히 생략한다(학내망 배포용 외부 호출 0 모드). // TODO, /* 생략 */ 같은 미완성 코드는 절대 넣지 말고 끝까지 완성한다.
[❓ 역질문 유도]
코드를 바로 만들지 말고, 아래 3가지를 먼저 나에게 질문한 뒤 내 답변으로 설계를 확정한다.
Q1. 어떤 자원을 중심으로 만들까? (인물 / 행성 / 스타십)
Q2. 데이터 모드는 무엇으로 할까? (A: 실시간 fetch 모드 / B: 학내망용 관심 카드 심기 모드)
Q3. 화면 톤은? (검색 카드 목록 / 영화·인물 연결 탐사 지도)
🎯 에디터 한줄평
'172'와 172의 차이, '19BBY'라는 세계관 연대, 타투인의 304일 — 가짜 수치로 하는 진짜 데이터 다루기의 완벽한 안전한 실험실입니다. 관계가 URL 목록으로 온다는 하이퍼미디어 개념은 웹의 본질을 아이에게 처음 열어주는 문이고, '더 보기' 버튼은 페이지네이션의 첫 실습입니다. 스카이워커 3대가 검색 한 번에 나란히 나오는 순간, 도감이 아니라 우주 가계도 앱으로 확장할 수 있다는 것도 알게 되죠. 심기 모드로 학내망까지 통과한 설계 — 세계관 데이터 특유의 '절대 안 바뀜'이 이 설계를 쉽게 만들어줍니다.
📚 기술·교육 참고 링크
- SWAPI : 이번 글의 은하수 데이터 창고(팬메이드)
- SWAPI 공식 문서 : 자원·검색·페이지네이션·wookiee 포맷 설명
- 교육과정 연계: 수학(단위·비율 — 행성 하루/1년 비교), 과학(우주·행성), 국어(세계관 설정문 읽기)와 함께 활용