AI용 분할본 · 지도 2단계(서버) · 이 페이지 전에 읽을 페이지: PART 0 사용법·AI 시작 지침, 부록 A 책 코드 받기 · 코드 파일은 여기 없다 — 코드 자리의 줄을 따른다(폴더에 책 파일이 하나도 없는 처음이면 부록 A-2 의 curl 한 줄부터)

핵심 규칙 — AI 는 어느 페이지에서든 이것을 지킨다

  1. 사용자가 결정 질문(PART 0 지침 1)에 답하고 승인하기 전에는 코드를 한 줄도 쓰지 않는다.
  2. HRUM API 키는 서버 환경변수 HRUM_API_KEY 에만 둔다. 미니앱 코드·.env·채팅·커밋·로그에 쓰지 않고, 키 값을 사용자에게 달라고 하지 않는다. 미니앱은 내 서버만 부른다.
  3. 책 코드 파일은 다시 쓰지 않는다 — node scripts/get-book-code.mjs 가 책 그대로 만든다(처음에는 부록 A-2 의 curl 한 줄). 분할본의 코드 자리는 「경로」 한 줄이다 — 받은 파일을 cat 으로 읽는다.
  4. 앱인토스 내용은 각 장 끝 출처의 공식 문서가 우선이다. 다르면 문서를 따르고 사용자에게 알린다.
  5. 확인은 명령 출력으로 증명한다. 콘솔 화면(앱인토스·HRUM)은 사용자가 누르고, AI 는 대신 가입·로그인하지 않는다. 진행은 PROGRESS.md 에 적는다.
  6. AI 는 지도(https://console.hrum.ai/tossEbook/ — 같은 지도가 tossEbook/ai.html 에도 있다)의 단계 순서대로 그 단계의 페이지만 읽는다. 전체본 tossEbook.html 은 사람용이다.

PART 3 — 서버 만들기: HRUM 키를 지키는 곳

3-0. 책 코드 받기

빈 프로젝트 폴더에서 부록 A 의 curl 한 줄을 실행하면 이 책의 [완전 코드] 파일이 전부 만들어집니다(서버 파일은 폴더 맨 위, 미니앱 파일은 miniapp/ 아래). 그다음부터는 node scripts/get-book-code.mjs 가 책과 다른 파일을 알려 줍니다.

3-1. 부를 API — HRUM 오늘의 사주

HRUM 응답뜻이 책의 서버가 미니앱에 주는 것
200 success: true성공화면에 쓸 칸만 골라 200
400잘못된 입력400 invalid_input — 같은 요청을 다시 보내지 않음
401 · 403 · 404키 문제 · 열리지 않은 기능503 temporarily_unavailable(서버 로그에 상태 코드만)
402 INSUFFICIENT_BALANCE크레딧 부족503 temporarily_unavailable — 빌링에서 충전
429요청 한도 초과429 + Retry-After
5xx · 시간 초과일시 오류502 upstream_unavailable

3-2. 서버가 하는 일

Origin 검사는 브라우저가 지키는 규칙입니다. curl 처럼 Origin 을 보내지 않는 도구는 막지 않으므로, 서버 주소가 알려져도 위의 울타리와 HRUM 요청 제한이 크레딧을 지킵니다.

package.json — 서버 — 의존성 없음, Node 22 이상코드 자리: cat package.json · 없거나 get-book-code 가 "다름"이면 node scripts/get-book-code.mjs · 손으로 고치지 않는다 · 원문(사람용 — AI 는 열지 않는다)

server.mjs — 서버 본체 — 키 보관·CORS·검사·캐시·HRUM 호출코드 자리: cat server.mjs · 없거나 get-book-code 가 "다름"이면 node scripts/get-book-code.mjs · 손으로 고치지 않는다 · 원문(사람용 — AI 는 열지 않는다)

mock-hrum.mjs — 키 없이 시험하는 가짜 HRUM(HRUM 문서의 응답 예시를 그대로 돌려줌)코드 자리: cat mock-hrum.mjs · 없거나 get-book-code 가 "다름"이면 node scripts/get-book-code.mjs · 손으로 고치지 않는다 · 원문(사람용 — AI 는 열지 않는다)

test/server.test.mjs — 서버 자동 테스트 — 가짜 HRUM 으로코드 자리: cat test/server.test.mjs · 없거나 get-book-code 가 "다름"이면 node scripts/get-book-code.mjs · 손으로 고치지 않는다 · 원문(사람용 — AI 는 열지 않는다)

3-3. 키 없이 돌려 보기

① 자동 테스트 — 프로젝트 폴더에서:

명령
npm test

끝에 # pass 13 · # fail 0 이 보이면 됩니다. 이 테스트는 실제 서버 코드를 가짜 HRUM 에 붙여 돌립니다 — 미니앱 주소만 허용되는지, 키가 헤더로 가는지, 같은 날 두 번째 요청이 캐시에서 나오는지, 크레딧 부족·잘못된 키가 화면에 어떻게 보이는지, 가짜 X-Real-IP 로 방문자 제한을 피할 수 없는지를 봅니다.

② 손으로 한 번 — 터미널 세 개를 엽니다.

터미널 1 — 가짜 HRUM
npm run mock
터미널 2 — 서버 (appName 자리에 내 값)
HRUM_API_KEY=mock-key-for-local-tests \
HRUM_BASE_URL=http://127.0.0.1:4010/api/v1/partners/v1 \
TOSS_APP_NAME=my-today EXTRA_ORIGINS=http://localhost:5173 \
npm start
터미널 3 — 확인
curl -s -X POST http://localhost:3000/api/today \
  -H "Content-Type: application/json" -H "Origin: http://localhost:5173" \
  -d '{"year":1990,"month":5,"day":15,"hour":12,"minute":0,"gender":"male"}'

"relation":"조율의 날" 이 든 JSON 이 나오면 됩니다. 이 값은 가짜 HRUM 이 돌려주는 고정 예시라 생년월일을 바꿔도 같습니다. mock-key-for-local-tests 는 가짜 HRUM 전용 문자열이고 진짜 키가 아닙니다.

환경변수필수뜻
HRUM_API_KEY예(비밀)HRUM 콘솔에서 발급한 키. 운영에서는 RIDM Apps 환경변수 칸에만
TOSS_APP_NAME예앱인토스 appName — 허용 Origin 두 개를 만든다
EXTRA_ORIGINS아니오쉼표로 더 허용할 주소. 내 컴퓨터 개발 때만 http://localhost:5173, 운영에서는 비운다
HRUM_BASE_URL아니오가짜 HRUM 으로 시험할 때만. 운영에서는 비운다(기본값이 실제 주소)
DAILY_UPSTREAM_CAP아니오서버 하루 HRUM 호출 상한. 비우면 2000
TRUST_PROXYRIDM Apps 에서는 예1 이면 앞단 프록시가 덮어쓴 X-Real-IP 로 방문자를 구분. 내 컴퓨터처럼 프록시 없이 바로 받는 곳에서는 비운다
이 책을 쓸 때 실제로 돌린 것 (2026-10-28, Node 22.22.2): 위 책 코드 그대로 npm test → 13개 통과·0개 실패. 서버와 가짜 HRUM 을 따로 띄워 curl → 200 과 위 JSON. 그다음 HRUM 시험용 계정에서 API 키를 하나 발급해 서버 환경변수에만 넣고, 실제 https://api.hrum.ai 에 붙여 성공 응답을 받았습니다(예시 생년월일, 결과는 PART 5-5). 같은 요청을 한 번 더 보내면 서버 캐시에서 나와 HRUM 을 다시 부르지 않는 것도 확인했고, 끝난 뒤 그 키는 폐기했습니다. 키 없이 보내면 401(success:false·statusCode:401), 틀린 키를 넣은 서버는 미니앱 쪽에 503 을 주는 것도 확인했습니다. 가짜 HRUM 의 값은 HRUM 문서의 응답 예시를 옮긴 것입니다.

출처

앱인토스 내용은 2026-10-28 에 앱인토스 개발자센터 문서를 직접 읽고 요약했고, 2026-10-30 에 문서와 다시 대조했습니다. 정책·화면은 바뀔 수 있으니 시작 전에 원문을 다시 확인하세요.

AI용 분할본 · 지도 2단계(서버) · 이 페이지 전에 읽을 페이지: PART 0 사용법·AI 시작 지침, 부록 A 책 코드 받기 · 코드 파일은 여기 없다 — 코드 자리의 줄을 따른다(폴더에 책 파일이 하나도 없는 처음이면 부록 A-2 의 curl 한 줄부터)