AI용 분할본 · 지도 2단계(서버) · 이 페이지 전에 읽을 페이지: PART 0 사용법·AI 시작 지침, 부록 A 책 코드 받기 · 코드 파일은 여기 없다 — 코드 자리의 줄을 따른다(폴더에 책 파일이 하나도 없는 처음이면 부록 A-2 의 curl 한 줄부터)
핵심 규칙 — AI 는 어느 페이지에서든 이것을 지킨다
HRUM_API_KEY 에만 둔다. 미니앱 코드·.env·채팅·커밋·로그에 쓰지 않고, 키 값을 사용자에게 달라고 하지 않는다. 미니앱은 내 서버만 부른다.node scripts/get-book-code.mjs 가 책 그대로 만든다(처음에는 부록 A-2 의 curl 한 줄). 분할본의 코드 자리는 「경로」 한 줄이다 — 받은 파일을 cat 으로 읽는다.빈 프로젝트 폴더에서 부록 A 의 curl 한 줄을 실행하면 이 책의 [완전 코드] 파일이 전부 만들어집니다(서버 파일은 폴더 맨 위, 미니앱 파일은 miniapp/ 아래). 그다음부터는 node scripts/get-book-code.mjs 가 책과 다른 파일을 알려 줍니다.
POST https://api.hrum.ai/api/v1/partners/v1/todayX-Partner-Api-Key 헤더에 API 키year·month·day·hour·minute·timezone·gender, 음력이면 calendar: "lunar") + date(볼 날짜, 생략하면 한국 시간 오늘). 출생 시각을 모르면 시각을 빼고 보내고, HRUM 이 정오로 계산해 birthHour 를 붙입니다summary(일진·오늘의 십성·흐름 등)와 omen(관계·행운 색·음식·키워드·좋은 시간·피할 시간·추천 활동·한 줄 메시지)| 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 |
HRUM_API_KEY 환경변수에서만 읽고, 어떤 응답·로그에도 쓰지 않습니다. /health 는 「키가 있는지(true/false)」만 알려 줍니다https://<appName>.apps.tossmini.com, 콘솔 QR 테스트 https://<appName>.private-apps.tossmini.com 입니다. 서버는 TOSS_APP_NAME 으로 이 두 주소를 만들고, 다른 Origin 에서 온 브라우저 요청은 403 으로 막습니다. 이 책의 미니앱은 SDK 3.8.0 을 쓰므로 3.0.x 용 주소(.web.tossmini.com)는 넣지 않습니다DAILY_UPSTREAM_CAP). 방문자 수를 세는 표는 1분마다 비우고, 한 분에 셀 수 있는 방문자 수에도 상한이 있어 메모리가 계속 늘지 않습니다. 진짜 마지막 울타리는 HRUM 콘솔의 요청 제한입니다(2-2)X-Real-IP 같은 헤더는 누구나 요청에 적어 보낼 수 있습니다. 서버가 이 헤더를 그냥 믿으면 요청마다 다른 값을 적어 방문자별 제한을 피할 수 있습니다. 그래서 서버는 기본으로 연결한 상대의 주소(req.socket.remoteAddress)를 쓰고, 앞단 프록시가 이 헤더를 항상 자기가 본 주소로 덮어쓰는 곳에서만 TRUST_PROXY=1 로 헤더를 씁니다. RIDM Apps 게이트웨이는 이 헤더를 덮어써서 넘기므로 PART 5 에서 켭니다(끄면 모든 방문자가 게이트웨이 주소 하나로 묶여 한 사람처럼 세집니다). 앞단 사정으로 주소가 정확하지 않을 수 있어 방문자 구분은 대략적입니다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 는 열지 않는다)
① 자동 테스트 — 프로젝트 폴더에서:
npm test
끝에 # pass 13 · # fail 0 이 보이면 됩니다. 이 테스트는 실제 서버 코드를 가짜 HRUM 에 붙여 돌립니다 — 미니앱 주소만 허용되는지, 키가 헤더로 가는지, 같은 날 두 번째 요청이 캐시에서 나오는지, 크레딧 부족·잘못된 키가 화면에 어떻게 보이는지, 가짜 X-Real-IP 로 방문자 제한을 피할 수 없는지를 봅니다.
② 손으로 한 번 — 터미널 세 개를 엽니다.
npm run mock
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
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_PROXY | RIDM 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 한 줄부터)