RLidea
한국어
기술 기록

Astro i18n 루트 리다이렉트가 깜빡이는 이유

루트 / 를 기본 언어로 보내는 정적 리다이렉트는 흰 화면이 한 번 선다. 원인은 Astro 가 아니라 「문서가 리다이렉트를 말해주는」 구조다. nginx 301 로 옮기고 meta refresh 는 폴백으로 남긴 기록.

이 사이트의 주소는 /ko/·/en/ 으로 나뉘고 루트 / 는 기본 언어로 보낸다. 처음엔 이 리다이렉트를 Astro 정적 페이지로 만들었다. 루트에 작은 index.html 을 두고 meta refresh 로 /ko/ 를 가리키는 방식이다.

로컬 preview 로 열어 보니 흰 화면이 한 번 비쳤다가 첫 페이지가 뜬다.

답부터 적는다. 깜빡임은 Astro 의 잘못이 아니라 정적 리다이렉트의 구조다. 브라우저가 HTML 을 받아 파싱해야 리다이렉트인 걸 아는데 그 사이에 빈 문서가 화면에 선다. 하여 오리진을 세울 때 nginx 가 루트에서 301 을 쏘게 했고 깜빡임은 사라졌다.

증상

재 보면 차이가 또렷하다. nginx 없이 로컬 preview 로 루트를 받으면 이렇다.

$ curl -s -o /dev/null -w 'status=%{http_code} size=%{size_download}B\n' http://localhost:4331/
status=200 size=666B

200 응답에 666바이트짜리 문서다. 안에는 이게 들어 있다.

<meta http-equiv="refresh" content="0; url=/ko/" />
<script>location.replace('/ko/');</script>

브라우저는 이 문서를 내려받고 파싱한 다음에야 /ko/ 로 가야 한다는 걸 안다. 그때까지 화면에 서 있는 것은 본문 없는 흰 문서다. 빠른 회선에선 깜빡임 한 번이지만 내려받기가 느릴수록 흰 화면도 길어진다.

Astro 탓은 아니다. 정적 빌드에는 요청을 가로챌 서버 프로세스가 없으니 Astro 의 redirects 설정도 정적 출력에선 같은 meta refresh HTML 을 만들어 두는 것까지만 한다.

원인

깜빡임의 유무는 「리다이렉트를 누가 말해주는가」에서 갈린다.

문서가 말해주면(meta refresh·JS) 브라우저는 문서를 받아 그린 뒤에 안다. 서버가 말해주면(301·302) 헤더만 보고 즉시 다음 주소로 가므로 그릴 틈이 없다.

정적 사이트는 혼자서는 앞쪽을 할 수밖에 없다. 뒤쪽을 하려면 파일을 내보내 주는 계층(nginx 든 호스팅의 리다이렉트 규칙이든)의 손을 빌려야 한다.

해결

  1. 정적 파일을 서빙하는 nginx 서버 블록에서 루트만 301 로 쏜다.

    # 루트 → 기본 언어. 정적 index.html 의 meta refresh 대신 서버가 즉시 301 로 보낸다.
    location = / {
        return 301 /ko/;
    }
  2. 실측. 본문 없이 헤더로 끝나서 흰 화면이 설 자리가 없다.

    $ curl -sI https://rlidea.app/
    HTTP/2 301
    location: https://rlidea.app/ko/
  3. meta refresh 페이지는 지우지 않고 남겼다. nginx 가 먼저 301 을 쏘는 동안은 아무도 못 받는 파일이지만 서버 설정이 사라지는 날 폴백으로 일한다. 파일 안에 「지금 이 쪽은 서빙되지 않는다」는 주석을 달아 두었다 — 다음에 열어 본 사람이 왜 안 쓰이는 파일이 있는지 헤매지 않도록.

덤 — 아무도 안 읽는 _redirects

레포에는 _redirects 파일도 있다. Cloudflare Pages 나 Netlify 가 읽는 리다이렉트 규칙 파일인데 이 사이트는 nginx 가 직접 서빙하므로 해석할 주체가 없다. 실제로 받아 보면 76바이트짜리 텍스트 파일로 그냥 내려온다.

$ curl -s -o /dev/null -w '%{http_code} %{size_download}B\n' https://rlidea.app/_redirects
200 76B

리다이렉트는 읽는 주체가 있는 곳에 적어야 한다. 이 파일이 그걸 매일 보여주고 있다.

참고: