2026년 9월 6일 일요일

[교과 연계] 우리 고장 역사 탐방 성향 진단 - 한국관광공사 TourAPI 연동 추천 웹앱



우리 고장을 성향 진단처럼 탐방하는 웹앱 — 역사 탐방 성향 진단 & TourAPI 연동 완전 정복

🏛 학생들이 역사 탐방 성향 진단 4대 축(유적지-자연경관, 도보-교통, 체험-관람, 맛집-기념관) 16문항을 직접 설계하면, 가중치(weight) 연산으로 4글자 성향 코드가 나오고 보딩패스(boarding pass) 형태의 결과 카드가 발급됩니다. 여기에 한국관광공사 공공데이터(TourAPI)를 연동하면 성향에 맞는 우리 고장 여행지까지 추천됩니다.

사회(우리 고장의 문화유산)·수학(가중치 연산과 비율)·실과(SW)가 한 화면에서 만나는 융합 수업입니다. 학내망 배포용은 '우리 고장 여행지 심기'로 통신 0 — TourAPI 연동은 교사 PC 시연용 확장(무료 키 발급)으로 설계합니다.

📖 한 줄 정의

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

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

1. 3대 핵심 분석 비교표

무엇이 바뀌었나요? / 영역 초보자를 위한 쉬운 설명 이렇게 한번 써보세요!
수업 시나리오 사회 '우리 고장의 문화유산' + 실과 SW 단원. 학생이 진단 설계자가 되는 역전 구조 — 문항 16개도 학생 회의에서 만듭니다. 4축 문항표를 모둠별로 설계한 뒤 반 전체 문항 응답.
가중치(weight) 연산 답 하나가 축 양쪽에 +1. 4문항 합산 후 더 높은 쪽이 그 축의 글자 — 4축이 모이면 4글자 성향 코드. 합산 함수로 코드 산출 + 각 축 비율(%)까지 표시.
보딩패스(boarding pass) 카드 항공 티켓처럼 생긴 결과 카드 — 출발지 '우리 반', 도착지 '성향 코드', 좌석 칸에 축별 비율. 점선 분리선 + 큰 글자 코드로 카드 CSS 완성.
TourAPI 연동 한국관광공사 공공데이터 — 무료이지만 serviceKey(개인 인증키) 발급 필수. 구버전 KorService1은 폐기(실측), 현재는 KorService2. 공공데이터포털 가입 → 활용신청 → 키 발급 → areaBasedList2 호출.
학내망 배포 대응 진단·카드·여행지 추천은 전부 심기 모드(데이터 임베딩)로 완결 — 학생 단말은 통신 0. TourAPI fetch는 교사 PC 시연용 확장. 우리 고장 여행지 16곳을 성향 코드별로 EMBED_DATA에 심기.

2. 핵심 아키텍처 해설 — 진단 엔진은 이렇게 생겼다

① 4축 × 4문항 = 16문항 설계

축(axis) 하나가 두 극을 잡고(예: 유적지 vs 자연경관), 축마다 문항 4개를 만듭니다. 문항마다 답은 둘 중 하나 — 어느 쪽에 +1이 들어갈지만 정하면 됩니다. 예시:

  • 축1(유적지 vs 자연경관): "오래된 벽돌 담과 잔디 정원, 어느 쪽 사진이 끌리나?"
  • 축2(도보 vs 교통): "고장 골목은 걸어서 돌아보고 싶나, 자전거로 빠르게 돌고 싶나?"

② 가중치(weight) 연산 코드

const AXIS_META = [
  { a: "유", b: "자", name: "유적지 vs 자연경관" },
  { a: "보", b: "통", name: "도보 vs 교통" },
  { a: "체", b: "관", name: "체험 vs 관람" },
  { a: "맛", b: "기", name: "맛집 vs 기념관" }
];
// QUESTIONS 16개 — 각 문항은 축 번호(axis)와 두 극을 가진다

const tally = [0, 0, 0, 0, 0, 0, 0, 0];   // 4축 x 2극 = 8칸 점수판

QUESTIONS.forEach(function (q, i) {
  tally[q.axis * 2 + ANSWERS[i]] += 1;    // 답한 극에 +1
});

function letterFor(axis) {
  const a = tally[axis * 2];
  const b = tally[axis * 2 + 1];
  return { letter: a >= b ? AXIS_META[axis].a : AXIS_META[axis].b,
           pct: Math.round(a / (a + b) * 100) };
}

const parts = [0, 1, 2, 3].map(letterFor);
const code = parts.map(function (p) { return p.letter; }).join("");
// 예: '유보체맛' — parts[0].pct는 유적지 쪽 비율(예: 75)

③ 보딩패스(boarding pass) 결과 카드

<div class="pass">
  <p class="route">우리 반 ➜ <strong>유보체맛</strong></p>
  <p class="seat">유적지 75% · 도보 50% · 체험 62% · 맛집 100%</p>
</div>

티켓 감성은 CSS로 충분합니다 — 점선 분리선(border-style: dashed), 큰 성향 코드 글자, 하단에 축별 비율 좌석표. 이미지 파일이 하나도 필요 없습니다.

④ TourAPI 연동(교사 PC 시연용 확장 모드)

한국관광공사 공공데이터는 무료이지만 serviceKey 발급이 필수입니다. 절차: 공공데이터포털(data.go.kr) 가입 → '국문 관광정보 서비스' 활용신청 → 인증키 발급(보통 하루 이내).

const SERVICE_KEY = "발급받은_인증키";   // 교사 PC 전용 빌드에만 넣는다

async function loadPlaces() {
  const url = "https://apis.data.go.kr/B551011/KorService2/areaBasedList2"
    + "?numOfRows=5&pageNo=1&MobileOS=ETC&MobileApp=GajaTrip"
    + "&serviceKey=" + encodeURIComponent(SERVICE_KEY);
  const res = await fetch(url);
  const xml = await res.text();            // 응답은 XML
  const doc = new DOMParser().parseFromString(xml, "text/xml");
  const items = doc.getElementsByTagName("item");
  return Array.from(items).map(function (it) {
    return { title: it.getElementsByTagName("title")[0].textContent,
             addr: it.getElementsByTagName("addr1")[0].textContent };
  });
}

오늘 실측으로 잡아낸 함정 두 개: ① 구버전 주소 KorService1은 이미 폐기 — 호출하면 오류 코드 12 '해당 오픈API 서비스가 없거나 폐기됨'이 옵니다. ② 키 없이 KorService2를 호출하면 401·코드 20(SERVICE_KEY_IS_NULL). 오류 코드가 오히려 길잡이라는 좋은 수업 소재입니다. CORS도 실측 완료 — 요청에 Origin 헤더가 있으면(브라우저는 항상 실어 보냄) Access-Control-Allow-Origin을 돌려줍니다.

⑤ 학내망 전략: 우리 고장 여행지 16곳 심기

const EMBED_PLACES = {
  "유보체맛": "우리 고장 옛 성터 산책로",
  "자통관기": "고장 시립 박물관과 옛 우체국",
  // ... 16개 성향 코드별 1곳
};

학생 배포본은 이 상수만으로 추천이 완료되는 외부 통신 0 모드. 16곳 수집은 주말 현장 답사·TourAPI 웹사이트 검색을 활용한 교사의 미니 임무 — 한 번 심으면 갱신이 거의 필요 없습니다.

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

  1. 프롬프트 복사 — 아래 '제미나이 전용 에러 제로 프롬프트' 전체를 복사해 Gemini에 붙여넣습니다.
  2. 역질문 답변 — 4대 축 확정, 여행지 모드, 카드 톤 세 질문에 답하면 설계가 고정됩니다.
  3. HTML 파일 실행 — 완성 코드를 '고장탐방진단.html'로 저장 후 더블클릭. 학내망 배포본은 심기 모드 그대로입니다.

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

[🚨 에러 방지 기본 안전장치]
1. 결과물은 외부 라이브러리·프레임워크·웹폰트 없이 단일 HTML 파일로 완성한다. (TourAPI fetch는 교사 PC 시연용 확장 모드에서만 허용)
2. 진단 로직(4축 16문항), 가중치 연산, 보딩패스 카드, 우리 고장 여행지 16곳(EMBED_PLACES)을 한 파일에 완성한다(학내망 배포용 외부 통신 0).
3. 사운드는 Web Audio API로 직접 합성한다: 문항 넘김 '똑', 성향 코드 발급 '팡파르'. 오디오 파일·CDN 사운드 금지.
4. 모바일·크롬북 터치 대응: 뷰포트 메타 태그 필수, 답 선택 버튼 최소 44×44px, 16문항 진행바 표시.
5. 도구명은 '성향 진단'으로 쓴다 — MBTI는 상표이므로 도구 이름·로고에 사용 금지(4축·16코드 스타일 참고만).
6. SERVICE_KEY 상수는 교사 PC 전용 빌드에만 넣고, 학생 배포 파일에는 fetch 모드 자체를 제거한다.
7. // TODO, /* 생략 */ 같은 미완성 코드는 절대 넣지 말고 끝까지 완성한다.

[❓ 역질문 유도]
코드를 바로 만들지 말고, 아래 3가지를 먼저 나에게 질문한 뒤 내 답변으로 설계를 확정한다.
Q1. 4대 축은 무엇으로 확정할까? (기본: 유적지-자연경관 / 도보-교통 / 체험-관람 / 맛집-기념관)
Q2. 여행지 데이터는 어느 모드로 할까? (A: 우리 고장 16곳 심기 모드 / B: TourAPI 키 발급 후 실시간 모드)
Q3. 보딩패스 카드 톤은? (항공권 스타일 / 골든 티켓 스타일)

🎯 에디터 한줄평

'우리 고장 문화유산 암기 과제'가 '나에게 맞는 우리 고장 찾기'로 바뀌는 순간, 고장 사랑이 사랑 받아야 할 숙제에서 발견해야 할 재미로 바뀝니다. 가중치 연산은 비율 수업을 몸으로 하는 버전이고, 문항 16개를 학생이 설계한다는 점이 이 수업의 진짜 깊이입니다. 공공데이터는 '나라가 문을 열어준 창고' — 키 한 장 발급이 시민 데이터 소양의 첫걸음입니다. 구버전 폐기를 오류 코드로 잡아낸 실측 절차까지 학생과 함께 공유하세요. 그것이 이 방법의 핵심입니다.

📚 기술·교육 참고 링크

  • 한국관광공사 TourAPI 포털 : 공식 개발자 포털(오늘 실측 정상)
  • 공공데이터포털 : 가입·활용신청·serviceKey 발급 창구
  • 교육과정 연계: 사회(우리 고장의 문화유산), 수학(비율·가중치), 실과·정보(SW 활용)와 함께 활용