로컬·운영 구분이 없는 '개발용 Cloudflare URL' 찾기 실패 — 환경 분리의 교훈
운영 워커만 있고 개발용 URL이 따로 없다는 Notion 메모를 바탕으로, 개발·운영 환경을 뒤섞으면 유령 같은 디버깅 문제가 생기는 과정을 공개 가능하게 정리합니다.

“개발용 Cloudflare URL은 어디 있지?“라는 질문으로 시작된 하루였다. Notion에 정리된 운영 구성 설명 메모는 명확하게 답한다. Cloudflare에는 운영만 있고(re-view-all.com 같은 실서비스 + 워커 직접 URL), 개발용 Cloudflare URL은 없다. 개발은 로컬 localhost:3000 / 8787을 쓰면 된다. 그런데 그렇게 단순한 답도, 환경을 구분하는 습관이 없으면 결국 유령 같은 오류를 만든다.
사실: ’운영 배포 URL’과 ’개발 실행 주소’는 서로 다른 세계였다
메모를 풀어 보면 구조가 나온다. 웹 프론트는 Next.js로, API는 Wrangler dev로 따로 띄운다. 프론트가 프로덕션에서 쓰는 API 워커 주소와, 로컬에서 쓰는 localhost:8787은 완전히 다르다. 나는 이 차이를 무시하고, 운영 URL에서 동작하던 엔드포인트를 그대로 로컬로 가져왔다. 그 결과 로그인 콜백·CORS 허용 목록·환경변수 때문에 같은 코드가 다른 곳에서 다르게 행동했다.
더 답답했던 건, 운영에만 있고 개발에는 없는 설정 값이었다. 콜백 URL, 시크릿, CORS 출처가 환경별로 갈라져 있는데, 나는 한 곳의 설정만 바꾸고 두 환경을 “같은 것”처럼 취급했다. 문제가 생겼을 때 확인한 첫번째는 “어느 환경에서 도는 코드인가”가 아니라 배포 기록이어서, 원인 찾기에 담을 짚었다.
이유: 환경 분리는 ’선택’이 아니라 ’디버깅 도구’다
의외로 흔한 실수인데, 코드는 바꿨는데 환경별 설정을 안 바꾸는 경우가 많다. 운영에만 있는 CORS 출처, 개발 전용 로컬 주소, 시크릿 불일치. 이들이 섞이면 “이 코드가 방금 수정했는데 왜 안 되지?“의 원인은 대부분 코드가 아니라 환경 구성이 된다. 로컬과 운영의 URL·시크릿·CORS를 한 번에 목록으로 만들어 두면, 오류가 났을 때 “코드 vs 구성”을 빠르게 분리할 수 있다.
메모의 한 줄 요약(“개발은 localhost, 운영은 Cloudflare”)이 곧 방법론이다. 개발·운영 환경을 명시적으로 갈라 놓고, 어느 쪽을 만지는지 그때그때 확인하는 습관이, 유령 같은 크로스 환경 버그의 대부분을 막는다.
평가: 환경 분리 규칙 세 가지
첫째, URL을 하드코딩하지 말고 환경별로 나눈다. 프론트가 가리키는 API 주소가 환경마다 달라야 한다면, 그 값이 어느 환경인지 소스에서 바로 보이게 한다. 둘째, 시크릿·콜백·CORS 출처는 환경별 목록으로 관리한다. 콜백 URL 하나를 바꾸면 그게 어느 환경에 적용돼야 하는지가 디버깅의 첫 질문이어야 한다. 셋째, 개발·운영을 “같은 서비스”로 보되 “다른 세상”으로 취급한다. 운영 배포 기록으로 로컬 문제를 찾으려는 시도는 원인을 늦춘다.
한계: 이 글은 운영/로컬 두 환경이 나뉜 사례만 다룬다. 스테이징·카나리처럼 환경이 더 많아지면 ‘환경별 구성 저장소’ 관리가 별도 과제가 된다. 또 공개 구성 문서만으로는 특정 버그의 실제 원인을 단정할 수 없으므로, 로그와 실행 주소 확인이 항상 우선이다.
부연: 다음에 손댄다면
개발 서버를 띄울 때 시작 지점에 “지금 어느 환경이며, API는 어디를 바라보는가”를 출력하게 하면 헷갈림이 줄어든다. 그리고 콜백 URL·CORS·시크릿을 바꿀 때마다 해당 환경 목록을 함께 갱신한다. 가장 쉽게 잊는 것이 가장 먼저 터진다. URL 한 줄의 차이가 같은 코드의 결과를 뒤집는다는 걸, 이번 실패는 정확히 보여 줬다.