대시보드는 노트북 브라우저에서 잘 열리지만, 같은 스프레드시트 스크립트는 주소를 사용할 수 없다는 오류로 실패합니다. VPN을 켜거나 꺼도 아무것도 바뀌지 않습니다. 요청이 노트북에서 아예 나가지 않기 때문입니다. Apps Script은 Google 인프라에서 실행되고 거기서 자체 연결을 엽니다. 이 한 가지 사실이 설계 전체를 결정합니다.

무엇이든 바꾸기 전에 두 질문을 분리하세요. 어느 머신이 요청을 보내는지, 수신 측이 어떤 자격 증명을 받아들이는지입니다.

요청은 결코 당신의 노트북에서 시작되지 않는다

브라우저 탭은 노트북에서 VPN 어댑터와 내부 DNS 접미사를 거쳐 사설 서브넷으로 보냅니다. UrlFetchApp은 Google이 관리하는 호스트에서 보냅니다. 그래서 Google의 리졸버와 Google의 송신 주소만 보고, 당신의 분할 터널 경로는 하나도 보지 못합니다. 두 경로가 공유하는 것은 스프레드시트 문서이지 네트워크 위치가 아닙니다. 앱의 접속 로그에서 스크립트의 시도는 VPN 풀 주소가 아니라 Google 주소로 나타나며, 이것이 얻을 수 있는 가장 빠른 확인입니다.

그래서 로컬 수정은 아무 효과가 없습니다. 노트북을 다른 리졸버로 돌리거나, VPN 클라이언트를 다시 시작하거나, hosts에 항목을 추가해도 브라우저 경로만 바뀌고 스크립트 경로는 그대로입니다.

그것이 배제하는 것

내부 전용 엔드포인트는 Apps Script에서 도달할 수 없고, IP 허용 목록은 이 위치에서 접근 제어의 약한 대체물입니다. Google의 송신 대역은 넓고 다른 고객과 공유되며 하나의 스크립트에 묶을 수 없습니다. UrlFetchApp 참조 문서 는 요청이 Google의 IP 풀에서 나온다고 밝히며, 이것이 그 주장의 권위 있는 판본입니다. 사내 앱을 그 대역에 열면 귀속할 수 없는 트래픽을 받아들이게 됩니다.

브라우저 세션도 같은 방식입니다. 노트북 브라우저의 쿠키나 SSO 세션은 요청과 함께 이동하지 않습니다. 요청은 세션 상태가 없는 새 HTTPS 클라이언트입니다. 브라우저 SSO 리디렉션에 의존하는 것은 당신의 데이터가 아니라 그 리디렉션에서 끝납니다.

실행 가능한 두 가지 형태

첫 번째 형태는 스크립트에 승인된 API를 줍니다. 내부 서비스를 호출자를 인증하는 게이트웨이 뒤에 게시하고, 스크립트가 게이트웨이가 받아들이는 자격 증명, 예를 들어 서비스 계정 토큰을 제시하게 합니다. Apps Script에서는 OAuth2 라이브러리나 ScriptApp.getOAuthToken()을 쓰고, API 쪽에서는 IP 목록 대신 호출자 ID 허용 목록을 둡니다.

두 번째 형태는 방향을 뒤집습니다. 내부 작업이 사설 시스템을 조회하고 통제된 결과를 스크립트가 읽는 Sheet, Cloud Storage 객체, BigQuery 테이블에 게시합니다. Cloud Run 작업, 온프레미스 스케줄러, 기존 ETL 단계가 모두 그 작업이 될 수 있고, 어느 것도 인바운드 연결을 받을 필요가 없습니다. 그러면 스프레드시트는 인터페이스 대신 데이터셋을 소비합니다.

어느 형태가 이길지는 신선도, 필드 수준 제어, 그리고 누가 읽는 사람을 감사할 수 있어야 하는지에 달려 있습니다.

게시된 결과에 담겨야 하는 것

반대 방향 피드에는 명시적 계약이 필요합니다. 실어 나르는 필드, 갱신 간격, 읽는 사람 그룹, 그리고 내부 작업이 실패할 때 벌어지는 일입니다. 이 네 가지가 없으면 스프레드시트는 조용히 어제 숫자를 보여줍니다. 생성된 타임스탬프 열과 행 수를 추가해 두면 오래되었거나 일부만 게시된 상태가 로그를 열지 않고도 시트 자체에서 보입니다.

API 방향에도 계약이 필요합니다. 게이트웨이가 어떤 자격 증명을 받아들이는지, 토큰이 어떤 스코프를 지니는지, 어떤 호출자 ID가 허용되는지입니다. 로그인 페이지가 담긴 200 응답은 성공한 호출이 아니므로 상태 코드만이 아니라 본문도 확인하세요.

오류는 올바른 쪽에서 읽으세요

Apps Script은 도달할 수 없는 호스트를 주소 사용 불가 예외로 보고하는데, 이는 브라우저의 연결 거부 메시지가 아닙니다. 게이트웨이의 403은 요청이 도착했고 자격 증명이나 정책이 거부되었음을 뜻합니다. HTML 로그인 페이지는 요청이 스크립트가 완료할 수 없는 대화형 계층에 닿았음을 뜻합니다. 세 가지 다른 실패와 세 명의 다른 책임자입니다.

스크립트 로그를 브라우저 결과 옆에 두고, 하나를 다른 것으로 대체하지 마세요. 그러면 남는 질문은 평범한 통합 결정입니다. 그 환경에 필요한 접근을 주거나, 통제된 결과를 전달하는 것입니다.

관련 글