Skip to content

1. 목적·범위

  • 목적: www /trial 이메일 필터(회사 이메일 분류·검증) 흐름에서 HTTP 404·405 및 Zuplo unmatched-path 로그가 날 때, 원인을 체계적으로 구분하고 우선순위대로 조치할 수 있게 한다.
  • 범위: 기존 아키텍처(www /trial — Zuplo·Cloudflare 통합 기획)를 전제로, 증상 → 구간 → 원인 → 조치(배포·설정) 까지. 이 문서만으로 새 코드를 작성하지 않는다.

2026-04 (OAS fragments): 게이트웨이 OpenAPI는 config/oas-manifest.json 순서의 다수 조각이다. 아래 로그·본문에 나오는 05-auth.oas.json당시 관측 예시이며, 동일 유형의 $ref / components 누락 오류는 어느 Auth·trial 조각에서도 발생할 수 있다. 현재 레이아웃: OAS layout history.


2. 정상 호출 경로 (재확인)

프로덕션에서 브라우저가 호출하는 것은 동일 출처 POST https://www.pregoi.com/api/trial/email/check 이다. 이후 Cloudflare Pages FunctionsZUPLO_API_URL 기준으로 Zuplo에 같은 경로를 서버에서 프록시하고, Zuplo가 Control Planev1/trial/... 로 이어진다.

이메일 필터 “기능 오류”를 말할 때는 반드시 POST + 경로 /api/trial/email/check(또는 동계열 manual-approval) 의 응답·로그를 기준으로 한다.


3. 증상·원인 매핑 (의사결정 트리)

3.1 POST https://www.pregoi.com/api/trial/...405 Method Not Allowed

가설의미
Pages Functions가 배포에 포함되지 않음해당 경로에 onRequestPost 핸들러가 없고, 정적/폴백만 있음 → POST 거부.

조치 방향: Cloudflare Pages 빌드 산출물 옆에 functions/가 생성·업로드되는지(빌드 명령, Root directory), 배포 로그에 Functions 스킵 메시지가 없는지 확인한다.


3.2 POST .../api/trial/email/check404 (본문에 Zuplo problem JSON인 경우)

구간 A — Cloudflare Pages Functions → Zuplo

가설의미
ZUPLO_API_URL 누락·오타프록시가 업스트림을 호출하지 못하거나 잘못된 호스트로 호출. (환경에 따라 500에 가깝게 나오기도 함.)
잘못된 Zuplo 베이스 URL다른 프로젝트/환경의 호스트를 가리킴.

구간 B — Zuplo

가설의미
배포된 Zuplo API 스펙에 /api/trial/email/check 라우트가 없음OpenAPI에 정의된 trial 라우트(prego-zuplo15-trial-access-*19-trial-access-* 등, oas-manifest.json)가 해당 인스턴스 빌드에 포함되지 않음. 요청은 Zuplo까지 가지만 어떤 operation에도 매칭되지 않음.

Zuplo 관측 로그에서 Route Name: unmatched-path, route: "/(.*)" 이고, method·URL이 POST /api/trial/email/check 이면, 위 구간 B(라우트 미포함) 를 강하게 의심한다.

조치 방향: prego-zuplo에서 OAS 동기화·검증 후 해당 Zuplo 프로젝트에 재배포; Zuplo 대시보드에서 실제로 POST /api/trial/email/check operation이 보이는지 확인한다.


3.3 Zuplo 로그: GET + /favicon.ico + unmatched-path + 호스트 *.zuplo.app

이 패턴은 이메일 필터 API 오류의 원인으로 쓰이면 안 된다.

사실설명
브라우저(또는 일부 클라이언트)는 문서를 열면 자동으로 GET /favicon.ico 를 요청한다.
Zuplo는 정적 사이트가 아니므로 일반적으로 favicon.ico 를 제공하지 않는다.
결과적으로 catch-all /(.*)unmatched-path404정상적으로 발생할 수 있다.

결론: prego-main-….zuplo.app 에 대해 GET /favicon.ico 보고 “아직도 404”라고 하면, 이메일 필터 실패와 혼동된다. 반드시 같은 시간대의 POST /api/trial/email/check (또는 Pages 동일 출처 해당 POST) 로그를 대조한다.


3.4 POST Zuplo 직접 URL → 404 + unmatched-path

Control Plane이 아닌 Zuplo 게이트웨이에 trial 라우트가 올라와 있지 않으면 동일하게 발생한다. www·Pages 쪽을 고쳐도 해결되지 않으며, prego-zuplo 배포·환경이 맞는지 봐야 한다.


3.5 Zuplo Gateway Build 실패 — API 게이트가 통째로 갱신되지 않음 (선행 차단)

배포 로그에 아래와 같이 Gateway 빌드만 실패하고, Developer Portal(Zudoku) 빌드는 성공하는 패턴이 있다.

구분로그에서의 의미
Gateway BuildBuilding Zuplo API... 이후 실패 → 런타임에 올라가는 API 라우트 스펙이 새 커밋으로 갱신되지 않음
Dev Portalzudoku build, Deploying developer portal..., Dev Portal deployed successfully문서 사이트만 정상 배포될 수 있음

관측된 오류 (예시)

ERROR: Failed to resolve reference: /config/05-auth.oas.json#/components/parameters/PregoGatewayXTraceId
| Token "components" does not exist.
| File: /config/05-auth.oas.json:0:0
Build failed.
Failed to build API Gateway

원인 분석 (기획 관점)

  • (당시 예: 05-auth.oas.json; 현재는 Auth 관련 조각) paths 안 여러 operation이 $ref: "#/components/parameters/PregoGatewayXTraceId" 를 사용한다.
  • 동일 파일에 components 객체가 없거나, components.parameters.PregoGatewayXTraceId 정의가 없으면 OpenAPI 파일 단위로 볼 때 내부 참조가 깨진다.
  • Zuplo Gateway 빌드는 이런 미해결 $ref 에서 중단되므로, trial-access 조각 포함 전체 게이트웨이 스펙이 배포되지 않는다.
  • 결과적으로 런타임은 이전에 성공했던 빌드를 쓰거나, 라우트가 비어 unmatched-path 로 떨어지는 현상과 연결될 수 있다 (환경·이전 배포 상태에 따라 다름).

Zuplo 포털 UI와의 대응

  • Environments → Production (main) 에서 아이콘이 부분 성공(녹/적) 으로 보이는 경우, Gateway와 Dev Portal이 서로 다른 결과일 수 있다.
  • GitHub 연동 배포가 “성공”처럼 보여도 Gateway 서브작업만 실패하면, 이메일 필터용 API는 갱신되지 않는다.

조치 방향 (코드 변경은 본 문서 범위 밖)

  • prego-zuplo 저장소에서 해당 Auth(또는 공통 헤더 $ref를 쓰는) OAS 조각OpenAPI 참조 무결성을 복구한 뒤(예: components.parameters.PregoGatewayXTraceId 정의 추가, 또는 프로젝트에서 허용하는 방식으로 $ref 정리), 저장소 관례에 따라 sync-oasverify → Zuplo 재배포.
  • Gateway 빌드가 성공한 뒤에만, 3.2·3.4 절의 “trial 라우트 미배포” 가설을 런타임에서 다시 검증하는 것이 타당하다.

참고: Dev Portal 로그에 Wrote ... merged.oas.json | paths: 93 등이 찍히는 것은 문서용 병합이며, Gateway 빌드 실패를 보상하지 않는다. 두 파이프라인을 혼동하지 말 것.


4. 원인 요약 표 (이메일 필터 관점)

관측1차 원인 후보주 레포/설정
www에서 POST 405Pages Functions 미포함Prego Pages 빌드·functions/
www에서 POST 404 (Zuplo body)Zuplo에 trial 라우트 없음 또는 잘못된 ZUPLO_API_URLprego-zuplo 배포, Pages ZUPLO_API_URL
Zuplo 로그 GET /favicon.ico 404API 버그 아님 (브라우저 기본 요청)무시하거나 Zuplo/별도 호스팅에서 파비콘은 별도 논의
Zuplo 로그 POST /api/trial/... unmatched-pathTrial OAS 미배포·다른 프로젝트 URLprego-zuplo trial-access 조각(15-trial-access-* …), 배포 타깃 인스턴스
Zuplo Gateway Build 로그: 05-auth.oas.json(또는 유사) + PregoGatewayXTraceId + Token "components" does not existOAS 내부 $ref 깨짐 → Gateway 전체 배포 실패prego-zuplo 해당 Auth 조각·01-prego-gateway-parameters 공통 헤더 패턴
Dev Portal만 성공 / Gateway 실패문서 사이트는 최신, API 라우트는 구버전 또는 미갱신Zuplo 빌드 로그에서 두 단계를 분리해 확인

5. 대응 절차 (기획 단계 체크리스트)

순서를 지키면 원인 추적 비용이 줄어든다.

  1. 증상 고정: 실패한 요청이 POST 인지, 경로가 /api/trial/email/check 인지, 응답 본문이 Zuplo problem 인지 Pages HTML 인지 기록한다.
  2. 노이즈 제거: Zuplo 로그에서 GET /favicon.ico, GET /, 정적 리소스만 있는 항목은 이메일 필터 실패 증거에서 제외한다.
  3. Zuplo 배포 파이프라인: 동일 배포에서 Gateway Build성공했는지 먼저 확인한다. Failed to build API Gateway 가 있으면 3.5 를 처리하기 전에는 런타임 trial 동작을 신뢰할 수 없다. Dev Portal만 성공한 것으로 착각하지 않는다.
  4. www 구간: POST /api/trial/...405면 Pages Functions·빌드 설정을 본다.
  5. Zuplo 구간: Gateway 빌드가 성공한 전제에서, 동일 POST가 404이고 Zuplo가 unmatched-path 이면 trial 라우트가 그 인스턴스에 포함됐는지를 본다 (prego-zuplo → 해당 Zuplo 프로젝트).
  6. 환경 일치: ZUPLO_API_URL / 대시보드에 등록한 호스트가 로그를 보고 있는 Zuplo 인스턴스와 동일한지 확인한다 (호스트명이 a8d4dfe.zuplo.appbb45748.d2.zuplo.dev 등으로 바뀌면 혼선이 크다).

6. 관련 문서


7. 이 문서의 한계

  • 코드 수정·PR은 포함하지 않는다. 조치가 “배포·환경·라우트 포함 여부·OAS 참조 복구”에 집중된다.
  • 파비콘 404를 없애려면 www 정적 자산이나 Zuplo 외부 CDN별도 UX/브랜딩 결정이 필요하며, 이메일 필터 신뢰성과는 분리해 논의하는 것이 좋다.
  • Auth 관련 OAS 조각(구 단일 05-auth 병기)의 components 누락구체적인 수정 패치prego-zuplo 쪽에서 이루어져야 하며, 본 기획서는 증상·원인·우선순위만 정리한다.
Help