본문으로 건너뛰기

remix 브라우저 환경변수 설정

process.env으로 환경변수에 접근하는 방법은 브라우저에서는 불가능하다.

remix docs에서 제시하는 브라우저 환경에서의 접근방법은 아래와 같다.

// root.tsx
export async function loader() {
return json({
ENV: {
STRIPE_PUBLIC_KEY: process.env.STRIPE_PUBLIC_KEY,
FAUNA_DB_URL: process.env.FAUNA_DB_URL,
},
});
}


export function Root() {
const data = useLoaderData<typeof loader>();
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body>
<Outlet />
<script
dangerouslySetInnerHTML={{
__html: `window.ENV = ${JSON.stringify(
data.ENV
)}`,
}}
/>
<Scripts />
</body>
</html>
);
}

// page.tsx
import { loadStripe } from "@stripe/stripe-js";

export async function redirectToStripeCheckout(
sessionId
) {
const stripe = await loadStripe(
window.ENV.STRIPE_PUBLIC_KEY
);
return stripe.redirectToCheckout({ sessionId });
}

root.tsx에서 window.ENV에 환경변수를 할당하는 방법이다.

하지만 위 방식은 클라이언트에서만 유효하다. 서버측에서만 접근 가능한 process.env와 동일하게 window는 클라이언트에서만 접근 가능하며 서버에서는 접근 불가능하다. 리믹스의 컴포넌트는 서버와 클라이언트 모두 실행되는데, 위의 문제로 인해 컴포넌트에서 환경변수를 사용할 수 없다.

간단한 해결책은 리액트의 전역 context를 생성하는 것이다.

// root.tsx
export async function loader({ context }: LoaderFunctionArgs) {
return json({
ENV: {
SERVER_URL: context.env.SERVER_URL as string,
},
});
}

export default function App() {
const { ENV } = useLoaderData<typeof loader>();

return (
<html lang="en" className="dark">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
<EnvContext.Provider value={ENV}>
<Outlet />
</EnvContext.Provider>
<ScrollRestoration />
<Scripts />
<LiveReload />
</body>
</html>
);
}

// routes/login.tsx
export default function LoginPage() {
const env = useEnv();

return (
<div>
<Link to={`${env.SERVER_URL}/auth/google`}>
<Button>구글 로그인</Button>
</Link>
<Link to={`${env.SERVER_URL}/auth/github`}>
<Button>깃 허브 로그인</Button>
</Link>
</div>
);
}

서버와 클라이언트 모두 잘 동작한다.