Cheondi
개발 · API

환경별 시간대 파일 주소

시간대 데이터 다운로드 주소가 개발과 배포 환경에서 달라진 문제를 설정과 배포 경계로 정리한 기록입니다.

  • #api
  • #configuration
  • #deployment

시간대 정보를 갱신하는 파일은 개발 환경에서 잘 내려받아졌지만 배포된 WebGL에서는 404가 났다. 파일 이름과 요청 코드는 같았고 브라우저에서 개발 주소를 직접 열면 정상이라 한동안 데이터 문제를 의심했다. 실제 배포에서는 정적 파일의 기준 경로와 CDN prefix가 달랐다.

코드 안의 상대 주소 하나가 실행 위치에 따라 다른 서버를 가리키고 있었다.

기준 주소 기반 URL 생성

window.location에 경로를 붙이는 방식은 하위 경로 배포와 CDN에서 깨졌다. 환경 설정에서 정적 자산 기준 URL을 전달하고 URL API로 결합했다.

const timezoneUrl = new URL(
  'data/timezones.json',
  window.appConfig.assetBaseUrl
).toString();

설정에는 공개 가능한 기준 주소만 넣고 인증 정보는 포함하지 않았다.

파일 존재와 응답 내용의 분리 검증

HTTP 200이어도 오류 페이지 HTML이 반환될 수 있었다. 상태 코드, Content-Type, JSON 버전을 순서대로 검사했다.

if (!response.IsSuccessStatusCode) return DownloadFailed.Http;
if (!IsJson(response.ContentType)) return DownloadFailed.UnexpectedContent;

var data = Parse(await response.ReadText());
if (data.Version < minimumVersion) return DownloadFailed.OldData;

전체 본문을 로그에 남기지 않고 주소의 공개 경로, 상태 코드, 콘텐츠 종류만 기록했다.

다운로드 실패 시 마지막 정상 데이터

시간대 파일을 못 받았다고 로그인과 전체 앱을 막을 필요는 없었다. 앱과 함께 들어 있는 기본 데이터나 마지막으로 검증된 캐시를 사용하고, 갱신 실패를 별도로 표시했다.

잘못 받은 파일로 정상 캐시를 덮지 않도록 다운로드, 검증, 교체 단계를 분리했다. 새 파일은 임시 위치에서 확인한 뒤 원자적으로 교체했다.

배포 산출물로서의 설정

로컬에서 맞는 URL을 하드코딩하면 구현은 끝난 것처럼 보인다. 실제 서비스에서는 개발, 테스트, 운영의 자산 위치와 페이지 기준 경로가 달랐다. 코드 성공과 배포 환경 성공을 구분해야 했다.

이후 외부 파일이나 API 주소를 붙일 때 환경별 기준, 최종 생성 URL, 실패 대체 경로를 함께 확인한다. 주소 한 줄도 실행 환경과 배포 구조를 잇는 계약이었다.

유사 문제 대응 기준

작업 당시에는 눈앞의 오류를 먼저 고쳤지만, 이후 기술 문서와 맞춰 보며 확인 순서를 조금 더 구체화했다.

RFC 3339의 문자열은 시각과 UTC 오프셋을 교환하는 데 유용하지만, 지역의 시간대 규칙 전체를 담는 형식은 아니다. +09:00은 그 순간의 차이를 말할 뿐 이후의 서머타임 규칙이나 지역 이름을 대신하지 않는다.

화면에서 필요한 것은 보통 서버가 기록한 절대 시각, 사용자가 선택한 지역, 표시 형식 세 가지다. 이 값을 하나의 문자열로 뭉치지 않으면 조회 범위와 표시 날짜가 어긋나는 문제를 줄일 수 있다.

다음에 환경별 시간대 파일 주소 같은 문제를 보면 아래 순서부터 확인하려고 한다.

  • 서버 저장 시각과 화면 지역 분리
  • 조회 시작·끝의 포함 여부
  • 날짜 변경선과 DST 경계 예제
  • 다운로드 실패 시 마지막 정상 규칙

날짜만 보내야 할 때와 정확한 순간을 보내야 할 때를 API 계약에서 구분하고, 범위의 시작·끝 포함 여부도 함께 고정해야 한다.

공식 참고 자료