Safari에서만 나는 초기화 오류, top-level await 버그일까?
같은 모듈을 한 번 불러오면 멀쩡한데, 두 곳에서 동시에 불러오면 Safari에서만 초기화 오류가 난다. 내 코드 문제일까, Safari 27에서 고친 top-level await 버그일까?

- Safari 27은 top-level await를 쓰는 모듈의 실행 순서와 초기화 문제를 수정했다.
- 같은 비동기 모듈을 동시에 import할 때 실패하는 현상은 구형 모듈 로더 버그의 단서다.
- 변수 초기화 전 접근과 순환 참조는 별도 원인이므로, 오류 문구만으로 브라우저 탓을 할 수 없다.
같은 모듈의 두 번째 import가 너무 일찍 끝났다면
Safari에서만 Cannot access uninitialized variable 같은 오류가 난다면, 비동기 모듈을 동시에 불러오는 경로가 있는지부터 볼 만하다. Safari 27.0은 모듈 로더를 다시 구현하면서 export 초기화가 끝나기 전에 import가 진행되던 문제를 고쳤다.
WebKit이 공개한 사례에서는 하나의 모듈을 세 번 동적으로 불러온다. 그 모듈이 최상위 await에서 잠시 기다리는 동안, 구형 로더는 두 번째와 세 번째 import를 먼저 완료해 버렸다. 이어서 아직 준비되지 않은 export를 읽으면서 오류가 났다.
이 현상은 개발자들이 오래전부터 보고했다. WebKit 버그 242740에는 동시 호출과 순차 호출의 결과가 다르다는 최초 제보, Astro에서 초기화 오류를 만났다는 댓글, 두 번째 import만 즉시 끝난다는 재현이 남아 있다. 27의 수정은 이런 모듈 평가 순서 문제에 해당한다.
파일을 받았다는 것과 모듈이 준비됐다는 것은 다르다
await import(...)가 돌려주는 값은 단순히 내려받은 파일이 아니다. MDN의 반환값 설명에 따르면 모듈을 성공적으로 로드하고 평가한 뒤, 내보낸 값들이 담긴 모듈 네임스페이스 객체로 Promise가 이행된다.
최상위 await는 이 평가 과정에 비동기 대기를 넣는다. 예를 들어 설정 데이터를 받아 export하는 모듈이라면, 그 설정을 필요로 하는 모듈도 준비가 끝날 때까지 기다려야 한다. 이 대기는 의존 관계를 따른다. 의존 관계가 없는 모듈까지 모두 순서대로 실행해야 한다는 뜻은 아니다.
따라서 네트워크 탭에 JavaScript 파일이 200으로 표시돼도 초기화가 끝났다고 판단할 수 없다. 파일 수신 성공 뒤에 모듈 평가가 남아 있기 때문이다. 오류를 좁힐 때는 응답 상태와 함께 import Promise가 끝나는 시점, export를 처음 읽는 위치를 봐야 한다.
같은 오류 문구라도 순환 참조는 업데이트로 고쳐지지 않는다
초기화 전 접근 오류는 정상적인 JavaScript 규칙으로도 발생한다. let·const를 초기화 전에 읽거나, 서로 의존하는 모듈이 상대의 준비되지 않은 값을 읽는 경우다. 코드에 선언이 적힌 위치보다 실제 실행 순서가 중요하다.
| 관찰한 상황 | 다음 확인 |
|---|---|
| 구버전 Safari에서 같은 모듈의 동시 import만 실패한다. | Safari 27 이상과 다른 엔진에서 같은 입력·번들을 대조한다. |
| 여러 브라우저에서 같은 변수를 읽다가 실패한다. | 변수 초기화 순서와 모듈의 순환 의존성을 확인한다. |
| 모듈 요청 자체가 404·CORS 오류로 실패한다. | 모듈 URL·응답·접근 정책을 먼저 확인한다. |
순환 import가 있다고 무조건 실패하는 것도 아니다. MDN 모듈 가이드는 실제로 값을 읽는 순간 아직 초기화되지 않았을 때 오류가 난다고 설명한다. 순환이 원인이라면 공유 코드를 제3의 모듈로 옮기거나 모듈 경계를 조정하는 방법을 검토할 수 있다.
우회 코드를 없애기 전에는 실제 배포 번들을 대조한다
실무 점검은 문제가 난 브라우저 버전과 import 경로를 기록하는 데서 시작한다. 같은 모듈을 한 번만 불러올 때와 동시에 불러올 때를 나누고, Safari 27 이상에서도 동일한 실패가 남는지 확인한다. 이 구분은 구형 로더의 재현 조건을 찾는 데 도움이 된다.
개발 서버에서 성공해도 검증은 끝나지 않는다. WebKit 버그 보고에는 번들러 설정에 따라 결과가 달랐다는 사례도 있으므로, 사용자가 받는 빌드 결과를 기준으로 비교해야 한다. 구버전 지원이 필요한 서비스라면 최신 Safari에서의 성공만으로 기존 대응 코드를 제거할 수 없다.
Safari 27은 비동기 모듈을 다시 검토할 이유를 제공한다. 우회 코드 제거 여부는 버전 숫자 하나보다 구체적인 실패 조건으로 결정해야 한다. 동시 import 문제는 수정된 로더에서 대조하고, 초기화 순서와 순환 참조 문제는 코드에서 해결하는 것이 출발점이다.