Google AI 스튜디오의 Build 기능 열기
Build는 대화만 하는 기능이 아니라, 프롬프트 하나로 실제로 동작하는 웹앱을 만들어 주는 기능입니다. 오늘 만들 앱의 작업실을 먼저 엽니다.
이 단계를 마치면 — 빈 Build 프로젝트가 열리고, 프롬프트를 붙여넣을 입력창과 오른쪽 미리보기 창이 보입니다.
따라 하기
Build로 만든 앱은 브라우저에서 도는 화면과 서버 두 부분으로 이루어집니다. 학교알리미 키는 서버에서만 읽고 브라우저로 내려보내지 않기 때문에, 학생이나 학부모가 앱을 써도 키가 노출되지 않습니다. 프롬프트에 이 구조가 이미 지정되어 있습니다.
발급받은 키 값은 채팅창·메신저·공유 문서에 붙여넣지 않습니다. 진행자에게는 "발급 완료"만 알리고, 화면을 공유하는 중이라면 키를 복사하기 전에 공유를 잠시 멈추세요.
준비된 프롬프트를 그대로 붙여넣기
아래 프롬프트에는 만들 화면뿐 아니라, 지난 실습에서 반복해서 생겼던 오류를 막는 조건이 함께 들어 있습니다. 문장을 고치면 그 오류가 다시 나타날 수 있으니 그대로 사용합니다.
이 단계를 마치면 — 앱 코드가 만들어지고, 오른쪽 미리보기에 앱 화면이 나타납니다. 키를 아직 넣지 않았으므로 지도 자리에는 안내 문구가 보입니다.
따라 하기
붙여넣을 프롬프트 원문
# 서울 고교 지도
# Google AI Studio 신규 프로젝트용 최종 프롬프트
서울특별시의 고등학교를 지도에서 탐색하고,
학교알리미의 공식 공시정보를 확인할 수 있는
완성도 높은 웹앱을 만들어줘.
앱 이름은
"서울 고교 지도"
부제는
"지도에서 찾고, 공시정보로 비교하는 서울 고등학교 안내"
로 한다.
이 앱은 중학생, 학부모, 담임교사,
진로진학상담교사가 사용하는 것을 목적으로 한다.
특히 진로교사가 학생과 상담하면서
- 우리 지역에는 어떤 고등학교가 있는가?
- 일반고, 자사고, 특목고, 영재고, 특성화고는 어디에 있는가?
- 남학교, 여학교, 남녀공학은 어떻게 분포하는가?
- 공립과 사립은 어떻게 다른가?
- 이 학교의 학생 규모는 어느 정도인가?
- 어떤 교육과정을 운영하는가?
- 학교의 특색사업이나 동아리는 무엇인가?
- 졸업생의 진로 현황은 어떠한가?
등을 확인할 수 있게 한다.
========================================================
0. 가장 중요한 원칙
========================================================
이 앱은 실제 공공데이터를 사용하는 앱이다.
학교에 관한 사실정보는 반드시
학교알리미(학교정보공시) Open API
의 실제 데이터를 사용한다.
AI가 서울의 학교 목록을 임의로 만들지 않는다.
다음과 같은 데이터를 실제 데이터로 사용하지 않는다.
sampleSchools
mockSchools
fallbackSchools
demoSchools
hardcodedSchools
API 연결에 실패했다고
임시 학교 데이터를 대신 보여주지 않는다.
학교 수 역시
319
323
76
등 특정 숫자로 하드코딩하지 않는다.
실제 학교알리미 API에서 조회한 결과를 사용한다.
========================================================
1. 환경변수는 정확히 2개만 사용
========================================================
이 프로젝트에서 사용자가 직접 입력해야 하는
환경변수/Secret은 정확히 다음 2개뿐이다.
1.
SCHOOLINFO_API_KEY
용도:
학교알리미 Open API 인증
2.
GOOGLE_MAPS_API_KEY
용도:
Google Maps JavaScript API
절대로 다음 환경변수를 만들지 않는다.
VITE_GOOGLE_MAPS_API_KEY
NEXT_PUBLIC_GOOGLE_MAPS_API_KEY
PUBLIC_GOOGLE_MAPS_API_KEY
GOOGLE_MAPS_SERVER_KEY
MAPS_API_KEY
Google Maps API Key를 두 개 요구하지 않는다.
Google Maps 관련 환경변수는 오직
GOOGLE_MAPS_API_KEY
하나만 사용한다.
따라서 AI Studio가 사용자에게
환경변수를 입력하라고 요청한다면
SCHOOLINFO_API_KEY
GOOGLE_MAPS_API_KEY
두 개의 입력란만 나타나야 한다.
========================================================
2. AI Studio Secret 구조
========================================================
Google AI Studio의 Secret은
서버 측 Node.js runtime에서 사용한다.
따라서 서버에서는
process.env.SCHOOLINFO_API_KEY
process.env.GOOGLE_MAPS_API_KEY
로 읽는다.
React 클라이언트에서
process.env...
또는
import.meta.env.VITE_...
를 이용하여
Secret을 직접 읽으려 하지 않는다.
========================================================
3. Google Maps 키를 클라이언트에 전달하는 방식
========================================================
Google Maps JavaScript API는
브라우저에서 실행되므로 지도 API Key가 필요하다.
하지만 VITE 환경변수를 추가로 만들지 않는다.
대신 서버에 다음 내부 endpoint를 만든다.
GET /api/maps-config
서버 응답 예:
{
"apiKey": process.env.GOOGLE_MAPS_API_KEY
}
이 endpoint는 Google Maps용 Key만 반환한다.
SCHOOLINFO_API_KEY는 절대로 반환하지 않는다.
React 앱 시작 시 다음 순서로 처리한다.
React
↓
GET /api/maps-config
↓
Google Maps API Key 획득
↓
@googlemaps/js-api-loader
↓
Google Maps JavaScript API 로딩
↓
지도 생성
따라서 사용자는
Google Maps API Key를 한 번만 입력한다.
========================================================
4. Google Maps 로딩
========================================================
Google Maps는 공식적인 방식으로 로드한다.
npm 패키지
@googlemaps/js-api-loader
를 사용한다.
Google Maps API Key를
index.html에 하드코딩하지 않는다.
YOUR_API_KEY
같은 가짜 Key도 사용하지 않는다.
지도 API는 앱 실행 중
중복 로딩되지 않도록 한다.
Google Maps API가 이미 로드되어 있다면
다시 script를 삽입하지 않는다.
Google Maps Key가 정상적으로 전달된 후에만
지도를 생성한다.
========================================================
5. 지도 오류 처리
========================================================
다음 상태를 구분한다.
① 지도 설정 로딩 중
"지도를 준비하고 있습니다…"
② GOOGLE_MAPS_API_KEY 없음
"Google Maps API Key가 설정되지 않았습니다."
③ Google Maps API 로딩 실패
"Google 지도를 불러오지 못했습니다."
④ 정상
서울 지도 표시
API Key가 없는데
깨진 Google Maps를 표시하지 않는다.
다음과 같은 화면이 나타난 상태를
정상으로 판단하지 않는다.
API KEY REQUIRED
For development purposes only
========================================================
6. Google Maps 구현에서 불필요한 API 요구 금지
========================================================
초기 버전에서 다음 Google API는 사용하지 않는다.
Places API
Geocoding API
Directions API
Street View API
Maps JavaScript API만 사용한다.
따라서 GOOGLE_MAPS_API_KEY는
Maps JavaScript API 사용만으로
기본 기능이 작동해야 한다.
학교 위치는 학교알리미에서 제공되는
위도/경도를 우선 사용한다.
========================================================
7. Google Maps Marker
========================================================
초기 구현에서는
Map ID가 별도로 필요한 기능을 사용하지 않는다.
별도의
GOOGLE_MAP_ID
환경변수를 요구하지 않는다.
학교 마커가 안정적으로 나타나는 것이
최우선이다.
Google Maps 기본 Marker 또는
Map ID가 추가로 필요하지 않은 안정적인
marker 구현을 사용한다.
마커 clustering은
@googlemaps/markerclusterer
등 검증된 라이브러리를 사용한다.
========================================================
8. 학교알리미 API는 서버에서만 호출
========================================================
학교알리미 Open API를
React 브라우저에서 직접 호출하지 않는다.
구조는 반드시 다음과 같다.
React Client
↓
AI Studio Node.js Server
↓
학교알리미 Open API
학교알리미 API Key는
process.env.SCHOOLINFO_API_KEY
를 사용한다.
SCHOOLINFO_API_KEY는
React 브라우저로 전달하지 않는다.
========================================================
9. 학교 목록용 내부 API
========================================================
서버에 다음 endpoint를 만든다.
GET /api/schools
이 endpoint가
서울 25개 자치구의 고등학교를
학교알리미에서 조회하고
하나의 JSON 배열로 정리해
React에 반환한다.
========================================================
10. 학교알리미 기본 요청
========================================================
학교알리미 학교기본정보 API를 사용한다.
기본 조건은
apiType = 0
sidoCode = 11
schulKndCode = 04
이다.
학교알리미 공식 Open API의
실제 요청 방식과 응답 구조를 기준으로 구현한다.
임의의 API endpoint나
존재하지 않는 파라미터를 만들어내지 않는다.
========================================================
11. 2026년 신규 API Key 대응
========================================================
2026년 신규 학교알리미 인증키에서는
sggCode가 필요한 방식이므로
서울 전체를 한 번에 요청하지 않는다.
서울 25개 자치구를 각각 조회한다.
다음 코드를 그대로 사용한다.
const SEOUL_DISTRICTS = [
{ name: "종로구", code: "11110" },
{ name: "중구", code: "11140" },
{ name: "용산구", code: "11170" },
{ name: "성동구", code: "11200" },
{ name: "광진구", code: "11215" },
{ name: "동대문구", code: "11230" },
{ name: "중랑구", code: "11260" },
{ name: "성북구", code: "11290" },
{ name: "강북구", code: "11305" },
{ name: "도봉구", code: "11320" },
{ name: "노원구", code: "11350" },
{ name: "은평구", code: "11380" },
{ name: "서대문구", code: "11410" },
{ name: "마포구", code: "11440" },
{ name: "양천구", code: "11470" },
{ name: "강서구", code: "11500" },
{ name: "구로구", code: "11530" },
{ name: "금천구", code: "11545" },
{ name: "영등포구", code: "11560" },
{ name: "동작구", code: "11590" },
{ name: "관악구", code: "11620" },
{ name: "서초구", code: "11650" },
{ name: "강남구", code: "11680" },
{ name: "송파구", code: "11710" },
{ name: "강동구", code: "11740" }
];
각 지역을
apiType=0
sidoCode=11
sggCode=해당 code
schulKndCode=04
조건으로 조회한다.
========================================================
12. 25개 구 API 호출 방식
========================================================
25개 중 일부 API 호출이 실패해도
전체 결과를 버리지 않는다.
Promise.allSettled()
또는 이에 준하는 안정적인 방식을 사용한다.
필요하면 API 요청을
3~5개씩 나누어 처리한다.
학교알리미가 반환하는 실제 응답에서
resultCode
resultMsg
list
를 확인한다.
학교 데이터는 반드시
list
배열에서 가져온다.
다음과 같은 임의의 구조를 만들지 않는다.
response.schools
response.items
response.rows
response.data.schools
========================================================
13. 학교 데이터 병합
========================================================
25개 자치구의 list 결과를
모두 합친다.
학교알리미의 학교 고유코드를 기준으로
중복만 제거한다.
학교 이름이 비슷하다는 이유로
학교를 제거하지 않는다.
학생 수가 없거나
학교 유형을 분류하지 못하거나
위치좌표가 없다는 이유로
학교 자체를 삭제하지 않는다.
========================================================
14. 데이터 로딩 상태
========================================================
앱을 실행하면 상단에
"서울 고등학교 조회 중"
이라고 표시할 수 있다.
하지만 loading 상태에서
무한정 멈추면 안 된다.
성공:
"서울 고등학교 XXX개교"
일부 지역 실패:
"서울 고등학교 XXX개교 · 일부 지역 조회 실패"
전체 실패:
"학교알리미 연결 실패"
finally 처리를 사용하여
항상 loading 상태를 종료한다.
========================================================
15. 개발 중 API 확인
========================================================
API Key는 console에 출력하지 않는다.
개발 중 서버 console에는
종로구: XX개
중구: XX개
...
동대문구: XX개
...
강동구: XX개
성공 지역: XX/25
실패 지역: XX/25
전체 학교: XXX개
정도의 로그를 출력할 수 있다.
이 로그는 사용자 화면에는 표시하지 않는다.
========================================================
16. 학교 데이터 구조
========================================================
학교알리미의 실제 데이터를
앱 내부 School 객체로 normalize한다.
예:
School {
schoolCode
schoolName
district
address
latitude
longitude
phone
homepage
genderType
foundationType
schoolType
studentCount
classCount
teacherCount
disclosureYear
}
실제 학교알리미 응답 필드명을 확인해서
올바르게 mapping한다.
존재하지 않는 필드명을
AI가 만들어내지 않는다.
========================================================
17. 서울 지도 화면
========================================================
첫 화면에서는
서울 전체가 한 화면에 들어와야 한다.
Google Maps fitBounds 등을 사용한다.
전국이 먼저 보이지 않게 한다.
서울 외부는
시각적으로 덜 강조한다.
가능하면 서울 경계 바깥을
반투명 회색으로 표현한다.
서울 학교가 주인공이 되어야 한다.
========================================================
18. 서울 구 경계
========================================================
서울 25개 자치구 경계를 지도에 표시한다.
신뢰할 수 있는 GeoJSON 데이터를
프로젝트 정적 데이터로 포함한다.
외부 지도 API를 추가로 호출해서
구 경계를 가져오지 않는다.
구 경계는 얇고 명확한 선으로 표현한다.
각 구 이름도 표시한다.
========================================================
19. 서울 교육지원청 경계
========================================================
11개 교육지원청 영역도 표시한다.
동부교육지원청
동대문구 + 중랑구
서부교육지원청
은평구 + 서대문구 + 마포구
남부교육지원청
영등포구 + 구로구 + 금천구
북부교육지원청
노원구 + 도봉구
중부교육지원청
종로구 + 중구 + 용산구
강동송파교육지원청
강동구 + 송파구
강서양천교육지원청
강서구 + 양천구
강남서초교육지원청
강남구 + 서초구
동작관악교육지원청
동작구 + 관악구
성동광진교육지원청
성동구 + 광진구
성북강북교육지원청
성북구 + 강북구
구 경계보다
교육지원청 경계를 조금 더 굵게 표현한다.
[구 경계]
[교육지원청 경계]
ON/OFF 토글도 제공한다.
단,
경계 GeoJSON 구현에 문제가 생기더라도
학교 지도와 학교 목록의 렌더링을 막지 않는다.
지도와 학교 데이터 표시가
항상 우선이다.
========================================================
20. 전체 UI
========================================================
PC 화면은 다음처럼 구성한다.
상단:
[로고]
서울 고교 지도
서울 고등학교 XXX개교
학교명 검색창
그 아래:
지역(구)
학교 유형
남녀
설립
필터
그 아래:
조건에 맞는 학교 XX개
적용된 조건
초기화
본체:
왼쪽 약 35%
→ 학교 목록
오른쪽 약 65%
→ Google 지도
흰색 중심의 깔끔한 화면에
파란색을 주요 포인트 색상으로 사용한다.
교육용 서비스처럼
신뢰감 있게 디자인한다.
========================================================
21. 지역 필터
========================================================
서울 전체 (25개 자치구)
및
25개 구를 선택할 수 있게 한다.
각 구 옆에
실제 현재 데이터에서 계산한 학교 수를 표시한다.
예:
동대문구 (11개교)
숫자를 하드코딩하지 않는다.
========================================================
22. 학교 유형 필터
========================================================
다음 유형을 구분한다.
전체
일반고
자사고
특목고
영재고
특성화고
학력인정고
기타
공식 데이터만으로 학교 유형을
확실하게 분류할 수 없는 경우
"확인 필요"
또는
"기타"
로 표시한다.
학교 이름만 보고
학교 유형을 추측하지 않는다.
========================================================
23. 남녀 및 설립 필터
========================================================
남녀:
전체
남학교
여학교
남녀공학
설립:
전체
공립
사립
국립
기타
여러 필터를 동시에 적용할 수 있게 한다.
예:
동대문구
+
일반고
+
여학교
+
사립
========================================================
24. 지도 학교 마커
========================================================
학교 위치는
학교알리미 위도/경도를 사용한다.
지도에서 다음 정보를
구분할 수 있어야 한다.
학교 유형
→ 마커 색상
남녀 구분
→ 모양 또는 내부 문자
설립 구분
→ 테두리 또는 작은 배지
예:
남학교 → 남
여학교 → 여
남녀공학 → 공
범례를 지도 한쪽에 표시한다.
========================================================
25. 지도 마커와 학교 목록 동기화
========================================================
왼쪽 학교 카드를 클릭하면
지도 중심이 해당 학교로 이동하고
해당 마커를 강조한다.
지도 마커를 클릭하면
왼쪽 학교 목록에서 해당 학교를 선택하고
학교 상세정보를 연다.
========================================================
26. 학교 목록 카드
========================================================
예:
[일반고] [동대문구] [남학교] [사립]
경희고등학교
총 학생: 710명
학급당: 29.6명
단,
아직 상세 데이터를 불러오지 않았다면
총 학생: -
처럼 고정된 빈값을 계속 보여주지 않는다.
필요하면
"상세정보 확인"
정도로 표시하고
학교 선택 후 상세 데이터를 불러온다.
========================================================
27. 학교 상세정보 조회
========================================================
서울 전체 학교의 모든 상세정보를
앱 시작 시 한꺼번에 호출하지 않는다.
처음에는 학교 기본정보만 불러온다.
사용자가 학교를 클릭했을 때
schoolCode
를 이용해
해당 학교의 상세 공시정보를 조회한다.
lazy loading을 사용한다.
========================================================
28. 학교 상세화면 — 기본정보
========================================================
학교명
학교유형
남녀구분
설립구분
지역
주소
전화번호
홈페이지
관할 교육지원청
학생 수
학급 수
교원 수
등을 보여준다.
========================================================
29. 학생 현황
========================================================
학교알리미의 실제 공시자료가 존재하면
전체 학생 수
남학생 수
여학생 수
학년별 학생 수
전체 학급 수
학년별 학급 수
교원 수
를 보여준다.
학급당 학생 수를 직접 계산한다면
전체 학생 수 ÷ 전체 학급 수
를 사용하고
"공시자료 기준 계산값"
이라고 표시한다.
========================================================
30. 입학 정보
========================================================
진로교사가 중요한 정보를
위쪽에 배치한다.
학교알리미에 존재하면
입학생 현황
입학전형 자료
모집 관련 자료
입학전형 요강
등을 제공한다.
PDF/HWP 등의 첨부자료라면
[입학전형 자료 보기]
버튼을 제공한다.
========================================================
31. 교육과정
========================================================
다음 내용을
학교알리미에서 확인되는 범위 내에서 제공한다.
학교교육과정 편성·운영
개설 교과
개설 과목
선택과목
학년별 교육과정
관련 공시자료
구조화된 데이터면
표 또는 카드로 표시한다.
파일로만 존재하면
[교육과정 원문 보기]
버튼을 제공한다.
========================================================
32. 학교 특색
========================================================
학교알리미에 존재하면
교육운영 특색사업
동아리 활동
방과후학교
도서관
학생교육활동 지원시설
등을 보여준다.
========================================================
33. 졸업 후 진로
========================================================
학교알리미에 존재하면
졸업생 진로 현황
진학
취업
기타
등을 보여준다.
자료의 기준연도를 반드시 표시한다.
예:
2025학년도 졸업생 진로 현황
========================================================
34. 파일 자료
========================================================
학교알리미 자료가
PDF
HWP
XLSX
DOCX
등 파일로 존재하면
내용을 안정적으로 읽을 수 없는 경우
억지로 분석하지 않는다.
대신
[원문 보기]
버튼을 제공한다.
파일 URL을 임의로 만들지 않는다.
실제 API나 학교알리미에서 확인된 링크만 사용한다.
========================================================
35. 데이터 없음과 오류 구분
========================================================
다음 상태는 반드시 구분한다.
실제 공시자료 없음
→ "공시자료 없음"
API 호출 실패
→ "자료를 불러오지 못했습니다"
아직 조회하지 않음
→ "학교를 선택하면 정보를 불러옵니다"
API가 실패했는데
0명
이라고 표시하지 않는다.
========================================================
36. 비교 기능
========================================================
학교 상세 화면에서
[비교함에 추가]
버튼을 제공한다.
최대 4개 학교를 비교할 수 있다.
비교 항목:
학교유형
남녀구분
설립구분
지역
학생 수
학급 수
학급당 학생 수
교원 수
교육과정
선택과목
특색사업
동아리
입학전형
졸업생 진로
========================================================
37. 즐겨찾기
========================================================
별표 버튼으로
관심학교를 저장한다.
localStorage를 사용한다.
Firebase
Supabase
회원가입
등은 사용하지 않는다.
========================================================
38. 앱을 처음 실행했을 때의 순서
========================================================
사용자가
SCHOOLINFO_API_KEY
GOOGLE_MAPS_API_KEY
두 값을 입력하고 Apply 하면
앱이 바로 다음 순서로 동작해야 한다.
1.
서버 시작
2.
GET /api/maps-config 정상 응답
3.
Google Maps 로딩
4.
서울 지도 표시
5.
GET /api/schools 실행
6.
서울 25개 자치구 학교정보 조회
7.
학교 목록 표시
8.
지도 마커 표시
9.
검색/필터 사용 가능
사용자가 키를 입력한 뒤
추가 환경변수를 다시 요구하면 안 된다.
========================================================
39. 초기 화면 완료 조건
========================================================
앱 첫 화면에서 다음이 모두 보여야 한다.
서울 고교 지도
서울 고등학교 XXX개교
지역/유형 등의 필터
왼쪽:
학교 목록
오른쪽:
서울 Google 지도
지도:
학교 마커
동대문구를 선택하면
동대문구 API에서 실제 조회된
고등학교 전체가 학교 목록과 지도에 나타나야 한다.
========================================================
40. 중요한 금지사항
========================================================
절대로 다음 작업을 하지 않는다.
1.
VITE_GOOGLE_MAPS_API_KEY 생성
2.
Google Maps Key 2개 요구
3.
Maps용 Secret 외에 Map ID 요구
4.
Google Maps 외의
API KEY REQUIRED 타일지도 사용
5.
학교알리미 API를 브라우저에서 직접 호출
6.
학교알리미 API Key를 브라우저에 전달
7.
서울 학교 목록 하드코딩
8.
API 실패 시 sample school 사용
9.
학교 수 하드코딩
10.
위치가 없는 학교 삭제
11.
분류가 안 되는 학교 삭제
12.
하나의 구 API 실패 때문에
전체 서울 조회 실패
13.
API 오류 상태에서
무한 "조회 중"
========================================================
41. 구현 우선순위
========================================================
한꺼번에 모든 기능을 만들다가
핵심 기능을 깨뜨리지 않는다.
먼저 아래 기능을 완전히 구현한다.
PHASE 1
두 Secret 읽기
PHASE 2
/api/maps-config
PHASE 3
Google Maps 정상 표시
PHASE 4
/api/schools
PHASE 5
서울 25개 구 학교 조회
PHASE 6
학교 목록
PHASE 7
학교 지도 마커
PHASE 8
검색 및 필터
여기까지 정상 작동한 것을
실제로 preview에서 확인한다.
그 후
PHASE 9
학교 상세정보
PHASE 10
학생현황
PHASE 11
교육과정
PHASE 12
입학정보
PHASE 13
진로현황
PHASE 14
비교 / 즐겨찾기
를 구현한다.
이미 정상 작동하는 기능은
다음 Phase에서 다시 작성하지 않는다.
========================================================
42. 최종 자체 점검
========================================================
작업을 완료하기 전에
반드시 스스로 다음을 확인한다.
환경변수 입력란이 정확히 2개인가?
SCHOOLINFO_API_KEY
GOOGLE_MAPS_API_KEY
VITE_GOOGLE_MAPS_API_KEY가 없는가?
Google Maps가 표시되는가?
API KEY REQUIRED가 없는가?
서울 25개 구 API 요청이 수행되는가?
학교 목록이 실제 schoolinfo list인가?
학교 목록과 지도 마커의 개수가 합리적으로 연결되는가?
동대문구 등 특정 구를 선택했을 때
그 구의 학교가 모두 표시되는가?
학교 마커를 클릭할 수 있는가?
학교 상세정보가 열리는가?
API 오류가 전체 앱을 멈추게 하지 않는가?
이 검증이 완료된 상태에서만
프로젝트 생성을 완료했다고 판단한다.
========================================================
43. 최종 지시
========================================================
위 요구사항에 맞춰
처음부터 프로젝트를 생성해줘.
특히 이전 프로젝트에서 발생했던
Google Maps 환경변수 중복
VITE_GOOGLE_MAPS_API_KEY 문제
지도만 나오고 학교 마커가 안 나오는 문제
학교가 76개만 나오는 문제
학교가 0개가 되는 문제
조회 중 상태에서 멈추는 문제
를 반복하지 마라.
사용자는
SCHOOLINFO_API_KEY
와
GOOGLE_MAPS_API_KEY
두 개만 입력하면 된다.
두 키를 입력하고 Apply를 누른 직후
서울 전체 Google 지도
+
실제 학교알리미 서울 고등학교 목록
+
학교 마커
+
지역 및 학교유형 필터
가 정상적으로 나타나는 상태를
가장 우선적으로 완성해줘.
지도 자리에 "Google Maps API Key가 설정되지 않았습니다"라고 나오는 것은 정상입니다. 반대로 회색 지도 위에 "For development purposes only"가 겹쳐 보이면 키나 결제 설정에 문제가 있다는 뜻이므로 3단계에서 확인합니다.
학교알리미 인증키와 Google 지도 키 발급
두 키는 역할이 다르고 서로 바꿔 쓸 수 없습니다. 학교알리미 키는 학교 공시자료를 불러오는 데, Google 지도 키는 지도를 화면에 띄우고 사용량을 확인하는 데 씁니다.
이 단계를 마치면 — 키 두 개가 AI 스튜디오 Secrets에 정확한 이름으로 저장되고, 미리보기에 서울 지도와 학교 목록이 나타납니다.
| 키 | 발급 위치 | 저장할 이름 | 쓰이는 곳 |
|---|---|---|---|
| 학교알리미 | 학교알리미 > OpenAPI > 나의 정보 조회 | SCHOOLINFO_API_KEY | 서버 |
| Google 지도 | Google Cloud Console > 사용자 인증 정보 | GOOGLE_MAPS_API_KEY | 브라우저 지도 |
가. 학교알리미 인증키 받기
2026년 1월 1일 이후 발급된 인증키는 요청할 때 시·군·구 코드(sggCode)가 반드시 있어야 합니다. 그래서 서울 전체를 한 번에 부르지 않고 25개 자치구를 각각 조회한 뒤 합칩니다. 2단계 프롬프트에 이 방식이 이미 들어 있습니다.
나. Google 지도 키 만들기
| 환경 | 허용 주소 예시 | 설명 |
|---|---|---|
| 실제 배포 | https://example.com/* | 그 도메인의 모든 경로 허용 |
| 하위 도메인 | https://*.example.com/* | 모든 하위 도메인 허용 |
| 내 컴퓨터 | http://localhost:5173/* | 실제로 쓰는 포트만 허용 |
| AI 스튜디오 | 주소창의 실제 주소를 확인해 입력 | 추측하지 말고 주소창이나 오류 메시지로 확인 |
브라우저가 요청을 보낼 때 주소의 뒷부분(경로)을 지우는 경우가 있어, 경로까지 지정하면 예상과 다르게 실패할 수 있습니다. 도메인 단위로 /*까지만 지정하는 방식을 쓰세요.
Maps JavaScript API를 쓰려면 결제가 연결된 프로젝트가 필요합니다. 연결했다고 곧바로 청구되는 것은 아니지만 사용량에 따라 비용이 생길 수 있으니, 연수 전에 예산 알림과 사용량 상한을 함께 설정하세요. 앱마다 별도의 키를 쓰고, 유출이 의심되면 새 키로 바꾼 뒤 기존 키를 폐기합니다.
다. AI 스튜디오 Secrets에 두 키 저장
Secrets는 서버에 값을 보관하는 곳이지만, 지도는 브라우저에서 그려지므로 지도 키는 실행 중 브라우저로 전달될 수밖에 없습니다. 그래서 허용 주소 제한과 API 제한을 반드시 걸어 두어야 합니다. 학교알리미 키는 브라우저로 보내지 않습니다.
잘 안 될 때
| 증상 | 먼저 확인할 것 |
|---|---|
| 회색 지도에 "For development purposes only" | 결제 연결과 결제수단 상태, Maps JavaScript API 사용 설정, 키 입력 여부 |
| RefererNotAllowedMapError | 지금 보고 있는 주소가 허용 주소 목록과 정확히 일치하는지 |
| ApiNotActivatedMapError | 키가 속한 그 프로젝트에서 Maps JavaScript API가 켜져 있는지 |
| 학교알리미 요청 실패 | 키 상태, apiType, 학교급, 시도·시군구 코드. 2026년 신규 키는 sggCode 필수 |
| AI 스튜디오에서 값이 undefined | Secret 이름의 대소문자와 공백, 저장 여부, 서버 재시작 |
| 제한을 걸자마자 실패 | 반영될 때까지 몇 분 기다린 뒤 재시도. 실제로 부르는 API가 허용 목록에 있는지 |
공식 안내 바로가기
- 학교알리미 API 이용안내 — 로그인부터 인증키 발급까지
- 학교알리미 Open API 개발자 활용 가이드(PDF) — 인증키 확인 경로
- 파라미터 운영 기준 변경 안내 — 2026년 신규 키의 시·군·구 코드 필수화
- Maps JavaScript API 설정 — 결제·활성화·키 만들기
- Google Maps Platform 보안 지침 — 웹사이트 및 API 제한
- AI 스튜디오 풀스택 앱과 Secrets — 설정 > Secrets와 서버 환경 변수
코드를 내려받아 Netlify에 배포하기
AI 스튜디오 안에서만 열리는 앱은 다른 선생님이나 학생에게 보여주기 어렵습니다. 코드를 내려받아 Netlify에 올리면 누구나 열 수 있는 주소가 생깁니다.
이 단계를 마치면 — https://○○○.netlify.app 주소에서 지도와 학교 목록이 그대로 동작합니다.
이 앱은 화면과 서버 두 부분으로 되어 있는데, 내려받은 파일을 Netlify에 그냥 올리면 화면만 올라갑니다. 그러면 지도는 떠도 학교 목록이 비어 있습니다. 그래서 올리기 전에 서버 부분을 Netlify가 실행할 수 있는 형태로 바꿔 달라고 AI 스튜디오에 한 번 더 요청합니다. 아래 3번이 그 작업입니다.
따라 하기
3번에서 보낼 요청 문장
이 앱을 Netlify에 배포할 수 있게 바꿔줘. 서버의 GET /api/maps-config 와 GET /api/schools 를 Netlify Functions(netlify/functions 폴더)로 옮기고, netlify.toml 을 추가해줘. 키는 계속 process.env.SCHOOLINFO_API_KEY 와 process.env.GOOGLE_MAPS_API_KEY 로 읽고, SCHOOLINFO_API_KEY 는 절대로 브라우저에 전달하지 마. 이미 정상 작동하는 지도·학교 목록·필터 기능은 다시 작성하지 말고 그대로 두고, 배포에 필요한 부분만 바꿔줘.
복사했습니다배포 후 최종 점검
AI 스튜디오에서 고친 뒤 ZIP을 다시 내려받아, 사이트의 Deploys 화면 아래쪽 드롭 영역에 새 폴더를 끌어다 놓으면 같은 주소가 갱신됩니다. 매번 새 사이트를 만들 필요가 없습니다.
공식 안내 바로가기
- Netlify Drop 빠른 시작 — 끌어다 놓아 배포하기
- Netlify 환경 변수와 서버 함수 — 키를 안전하게 넣는 곳
- AI 스튜디오 Build 모드 안내 — 코드 탭과 ZIP 내보내기