Nextjs RunTime 변수 at k8s

IT공부중·2024년 12월 5일
0

Next

목록 보기
12/12

NextJS 에서는 보통 .env 파일을 활용하여 환경변수를 작성하게 되는데,
이 때는 build time에 반영되어 literal 로 변경되어 들어가게 된다.

NEXT_PUBLIC_URL='http://naver.com'
// build 후에는 'http://naver.com' 값으로 들어감.
const HOST_URL = process.env.NEXT_PUBLIC_URL;

그렇게 되면 docker image로 만들 때 빌드 타임에 이미 환경변수가 literal로 들어간 상태가 된다.
dev용, real 용 image를 각각 만들어야하는 것이다.

사내 플랫폼에서는 하나의 image로 dev랑 real을 다 사용하기를 권장하고 있었다. 이렇게 하면 image를 하나로만 할 수 있으니 빌드를 한번만 하면 됐고, 그래서 더 빠르게, 같은 결과물이니 신뢰성 있게 사용할 수 있다는 장점이 있었다. 하지만 그렇게 하기 위해서는 runtime에 환경 변수를 수정할 수 있어야했다.

찾아보니 다른 회사 분들이 쓴 글들이 있었는데 client 단에서는 window 객체에 넣어서 사용하고, server 단에서는 .env 파일을 사용하여 할 수 있도록 하는 방식이었다. 그것이 가능하도록 꽤나 긴 코드들이 필요했는데 이것을 쉽게 할 수 있도록 제공하는 라이브러리가 있어서 사용했다.

next-runtime-env

next-runtime-env 라이브러리도 위 설명과 같은 방식으로 동작하는 걸로 보였다.
next 13, 14 버전을 지원하고, .env 친화적이라 사용하기도 편했다.

사용하는 방식은

app/layout.tsx 에 아래와 같이 head에 PublicEnvScript 를 넣어주면 된다.

// app/layout.tsx
import { PublicEnvScript } from 'next-runtime-env';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head>
        <PublicEnvScript />
      </head>
      <body>
        {children}
      </body>
    </html>
  );
}

그리고 사용하는 곳에서는 client 단이라면 아래와 같이 NEXT_PUBLIC 이 붙은 환경변수로 사용하면된다.

// app/client-page.tsx
'use client';
import { env } from 'next-runtime-env';

export default function SomePage() {
  const NEXT_PUBLIC_FOO = env('NEXT_PUBLIC_FOO');
  return <main>NEXT_PUBLIC_FOO: {NEXT_PUBLIC_FOO}</main>;
}

server 단이라면 NEXT_PUBLIC 없는걸로 사용하면 된다. (있는 것도 사용 가능)

import { env } from 'next-runtime-env';

import styles from './page.module.css';

export default function ServerSide() {
  return (
    <main className={styles.main}>
      <div className={styles.description}>
        <p>
          BAR: {env('BAR') /* This is the same as process.env.BAR */}
          <br />
          BAZ: {process.env.BAZ}
        </p>
      </div>
    </main>
  );
}

Dockerfile 예시

실행할 땐 NEXT_PUBLIC_FOO=foo-value BAR=bar-value BAZ=baz-value npm run start 이렇게 실행해주면 된다고 하는데, 저렇게 일일이 적어줄 수는 없으니 .env.dev .env.prod 를 만들어서 사용하고, docker 에서 실행시킬 때 환경변수로 expose 하게 작성하였다.

아래는 dockerfile의 마지막 일부분이다.

CMD bash -c '\
  if [ "$PHASE" = "production" ]; then \
    echo "Loading production environment"; \
    export $(cat .env.prod | xargs); \
  elif [ "$PHASE" = "develop" ]; then \
    echo "Loading development environment"; \
    export $(cat .env.dev | xargs); \
  else \
    echo "No PHASE set or invalid phase, loading default .env"; \
    export $(cat .env | xargs); \
  fi; \
  exec node server.js'

처음에는 저 부분을 sh 파일로 만들어서 ENTRYPOINT로 실행하도록 하려고 했으나 계속 deployment 실패가 나서, 기존처럼 CMD 형식으로 고쳐서 사용하였다.

이렇게 사내에서 권장하는 방법으로 배포할 수 있게 되었고, image를 한번만 빌드하여 더 빠르게 배포할 수 있게 되었다.


참고 글

카카오엔터 기술블로그
U+ 기술 블로그

profile
4년차 프론트엔드 개발자 문건우입니다.

0개의 댓글