티스토리 뷰

반응형

넥스트(nextjs)로 개발 시 기본적으로 개발 환경과 배포 환경, QA 환경에 대한 설정(next.config.js)을 다르게 해야한다. 특히나 process.env에 포함되는 변수에 대한 설정도 분리해서 저장을 해야한다. 그리고 보통은 개발/배포로 나누지만, 실무에서는 개발, QA, 실서비스에 따른 환경도 각각 다르게 설정을 해야한다. 이러한 환경 변수(environmental variables) 설정하는 방식에 대해 알아보자. 우선은 아래의 글을 참고하여 PHASE_DEVELOPMENT_SERVER에 대한 이해를 하자. 그리고 react 배포 환경에 대한 .env에 대한 지식을 보고 오자.

 

[react] 실무 개발 환경/배포 환경 설정(.env)

[nextjs] next.config.js 기초 정리

 

 

 

우선은 next.config.js에 대한 환경변수 설정법을 먼저 알아본다. 그 후에 위의 react와 같은 방식인 .env를 활용한 방법에 대해 알아본다. 그 후에 2가지 방법을 서로 비교하면서 글을 마쳐보려 한다.

 

1. next.config.js 기초

우선은 package.json 내용은 아래와 같다.

{
  "private": true,
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "latest",
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
  }
}

 

 

환경 변수를 설정하는 방법으로는 .env.dev 나 .env.production 과 같은 방법도 사용을 하긴한다. 하지만, 공식문서에 의거한 next.config.js를 활용한 환경 변수 설정을 진행해 보려한다. 기본적으로 위의 next.config.js를 보고 왔다면, 아래의 코드를 이해하는 것에는 문제가 없을 것이다.

 

const {
  PHASE_DEVELOPMENT_SERVER,
  PHASE_PRODUCTION_BUILD,
} = require('next/constants')

module.exports = (phase) => {
  
  const env = {
    NEXT_PUBLIC_ABC: 'envTest'
  }
  
  return {
    env,
  }
}

 

위의 코드에서 배포/개발 환경에 따른 분기는 하지 않았지만, 기본적으로 nextjs.config.js에서 위와 같이 env 내부에 key/value를 넣어주는 방식으로 환경변수 settings가 가능하다.

 

기본적으로  phase는 빌드를 진행하면서, PHASE_DEVELOPMENT_SERVER나 PHASE_PRODUCTION_BUILD 값을 가질 수 있다. 이러한 phase를 활용하면, react app에서 환경에 따라 다른 변수 설정이 가능하다. 아래의 예제를 보면서 좀 더 자세히 알아보자.

 

2. next.config.js 예제

기본적으로 next.config.js를 활용할 때도 staging은 next에서 제공하는 기본 버전이 아니기 때문에 따로 setting이 필요하다고 할 수 있다. 여기서 staging이란 개발 모드와 배포(실서비스) 모드의 중간으로 QA 단계인 테스트 모드라고 생각하면 좋을 것같다. 개발을 할때 보는 개발 환경, 개발 후 실 서비스 전에 테스트를 하는 staging 모드, 그리고 실제 서비스가 진행되는 production 모드로 이해를 하면 좋을 것 같다. 이러한 분류는 회사나 개발 팀에 따라 다를 수 있음을 인지하자.

const {
  PHASE_DEVELOPMENT_SERVER,
  PHASE_PRODUCTION_BUILD,
} = require('next/constants')

module.exports = (phase) => {
  // when started in development mode `next dev` or `npm run dev` regardless of the value of STAGING environmental variable
  const isDev = phase === PHASE_DEVELOPMENT_SERVER
  // when `next build` or `npm run build` is used
  const isProd = phase === PHASE_PRODUCTION_BUILD && process.env.STAGING !== '1'
  // when `next build` or `npm run build` is used
  const isStaging =
    phase === PHASE_PRODUCTION_BUILD && process.env.STAGING === '1'

  console.log(`isDev:${isDev}  isProd:${isProd}   isStaging:${isStaging}`)

  const env = {
    RESTURL_SPEAKERS: (() => {
      if (isDev) return 'http://localhost:4000/speakers'
      if (isProd) {
        return 'https://www.siliconvalley-codecamp.com/rest/speakers/ps'
      }
      if (isStaging) return 'http://localhost:11639'
      return 'RESTURL_SPEAKERS:not (isDev,isProd && !isStaging,isProd && isStaging)'
    })(),
    RESTURL_SESSIONS: (() => {
      if (isDev) return 'http://localhost:4000/sessions'
      if (isProd) return 'https://www.siliconvalley-codecamp.com/rest/sessions'
      if (isStaging) return 'http://localhost:11639'
      return 'RESTURL_SESSIONS:not (isDev,isProd && !isStaging,isProd && isStaging)'
    })(),
  }

  // next.config.js object
  return {
    env,
  }
}

 

이러한 env 설정은 최종 번들이 되기 전에 변수들이 하드코딩되서 들어간다. 따라서 주의할 점은 실행 중인 application에서 환경변수를 변경하면, 변경되지 않는다. 즉, 다시 build가 되어야한 변경한 환경 변수들이 변경된다.

 

package.json 파일의 script 부분은 보면 아래와 같이 작성이 가능하다..

  "scripts": {
    "dev:local": "next dev -p 3030",
    "dev:build": "next build",
    "dev:start": "next start -p 3030",
    "staging:build": "cross-env STAGING=1 next build",
    "staging:start": "cross-env STAGING=1 next start -p 3030",
    "prod:build": "next build",
    "prod:start": "next start -p 3030",
  },

 

위의 설명은 생략하겠다. 이 글을 전체 다 읽는다면, 전부 이해할 수 있을 것이다. 아래까지 쭉 읽은 후에 자신만의 개발환경을 꼭 만들어보자.

 

3. Default Environment Variables

next.config.js가 아닌 다른 방법으로 환경변수를 설정하는 것도 가능하다. 기본은 .env.local 파일로 환경 변수 셋팅을 한다. 그러나 development 환경이나 production 환경으로 셋팅을 하는 경우도 있다. 위의 react 환경 변수 셋팅 방식을 보고 왔다고 가정을 하고, 바로 환경 변수 조회 순서를 알아보자. 아래의 순서로 nextjs를 환경 변수를 조회하고, 파일을 발견 즉시 조회를 멈춘다.

  1. process.env
  2. .env.$(NODE_ENV).local       ( .local 부분은 .gitignore에 포함 시켜 repository에 올리지 안도록 하자.)
  3. .env.local                                  (Not checked when NODE_ENV is test.)
  4. .env.$(NODE_ENV)
  5. .env

조금 더 설명을 하면, 위의 조건이 적용되기 위해 NODE_ENV에 허용되는 값은 'production'과 'development', 'test'이다. 만약 .env.development.local과 .env 파일이 있다면, .env.development.local 파일이 적용 될 것이다. .env.development.local.env.development 파일이 있다면 .env.development.local이 적용될 것이다.

 

production과 development 환경은 자주 봤을 것이다. 그러나 test 환경은 생소 할 수 있다. test 환경은 보통 jest나 cypress와 같은 도구를 활용하여 test를 할때, 보통 사용한다. 즉, 테스트 목적으로만 환경 변수를 설정해야하는 경우 많이 사용한다고 기억하면 된다. 그리고 NODE_ENV를 test로 설정하는 경우도 있겠지만, 보통은 테스트 tool에서 자동으로 설정을 해주는 경우가 있기 때문에 구현 시 주의를 하자.

 

추가적으로 명령어에 따라 자동으로 nextjs에서 NODE_ENV를 지정한다. 

  • next dev       =>     development
  • next start      =>     production

 

3-1. environment variables test (환경 변수 실습)

기본 package.json 세팅은 아래와 같다. script 부분을 참고하여 명령어에 대한 이해를 하도록 하자.

 

{
  "name": "nextjs-env-test",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
  },
  "dependencies": {
    "next": "12.2.5",
    "react": "17.0.2",
    "react-dom": "17.0.2"
  },
  "devDependencies": {
  }
}

 

 

.env.development

우선은 .env.development 하나만 만들어서 실행해본다.

 

TEST=development test
NEXT_PUBLIC_TEST=development NEXT_PUBLIC test

 

.env.development를 위와 같이 하나 만들었다. 그리고 아래와 같이 테스트를 위해 pages/index.js를 만들었다.

 

// pages/index.js
import styles from "../styles/Home.module.css";

export default function Home() {
  console.log('----------------CLIENT ENVIRONMENT VARIABLES TEST----------------')
  console.log('process.env.NODE_ENV : ', process.env.NODE_ENV)
  console.log('process.env.TEST : ', process.env.TEST)
  console.log('process.env.NEXT_PUBLIC_TEST : ', process.env.NEXT_PUBLIC_TEST)

  return (
    <div className={styles.container}>
      <h1>TEST</h1>
      <p>adf</p>
      <p>adf</p>
    </div>
  );
}

export function getServerSideProps() {
  console.log('----------------SERVER ENVIRONMENT VARIABLES TEST----------------')
  console.log('process.env.NODE_ENV : ', process.env.NODE_ENV)
  console.log('process.env.TEST : ', process.env.TEST)
  console.log('process.env.NEXT_PUBLIC_TEST : ', process.env.NEXT_PUBLIC_TEST)
  return { props: {  } }
}

우선 npm run dev 명령어를 실행하고 console.log를 확인해 보면 아래와 같다.

 

----------------SERVER ENVIRONMENT VARIABLES TEST----------------
process.env.NODE_ENV :  development
process.env.TEST :  development test
process.env.NEXT_PUBLIC_TEST :  development NEXT_PUBLIC test
----------------CLIENT ENVIRONMENT VARIABLES TEST----------------
process.env.NODE_ENV :  development
process.env.TEST :  undefined
process.env.NEXT_PUBLIC_TEST :  development NEXT_PUBLIC test

 

기본적으로 env setting 시  client에서 process.env를 사용하려면, NEXT_PUBLIC_ 접두사를 변수 앞에 붙여주어야 한다.여기서 만약 console이 두 번찍히는 이유가 알고 싶다면 아래를 참고하자.

 

[nextjs] console.log가 두 번 찍히는 이유

 

 

.env.development.local

여기서 우리는 env.development.local을 아래와 같이 추가하자.

 

TEST=development test
NEXT_PUBLIC_TEST=development NEXT_PUBLIC test

 

그리고 서버를 실행하고 결과를 보면 아래와 같다.

 

----------------CLIENT ENVIRONMENT VARIABLES TEST----------------
process.env.NODE_ENV :  development
process.env.TEST :  development local test
process.env.NEXT_PUBLIC_TEST :  development NEXT_PUBLIC local test
----------------CLIENT ENVIRONMENT VARIABLES TEST----------------
process.env.NODE_ENV :  development
process.env.TEST :  undefined
process.env.NEXT_PUBLIC_TEST :  development NEXT_PUBLIC local test

 

.env.development.local.env.development를 보다 우선시 되 settings되는 것을 알 수 있다.

 

위의 상태에서 배포를 해보자. npm run build npm run start 시 consle.log 결과는 아래와 같다. 

----------------SERVER ENVIRONMENT VARIABLES TEST----------------
process.env.NODE_ENV :  production
process.env.TEST :  undefined
process.env.NEXT_PUBLIC_TEST :  undefined
----------------CLIENT ENVIRONMENT VARIABLES TEST----------------
process.env.NODE_ENV :  production
process.env.TEST :  undefined
process.env.NEXT_PUBLIC_TEST :  undefined

이는 당연하다. 왜냐하면, env.production을 만들지 않았기 때문이다. 추가적으로 NODE_ENV는 명령어에 따라 nextjs가 알아서 지정해 주는 것을 알 수 있다.

 

 

.env.production

.env.production을 아래와 같이 만들어보자

TEST=production test
NEXT_PUBLIC_TEST=production NEXT_PUBLIC test

 

npm run build  npm run start 시 consle.log는 아래와 같다.  

 

----------------SERVER ENVIRONMENT VARIABLES TEST----------------
process.env.NODE_ENV :  production
process.env.TEST :  production test
process.env.NEXT_PUBLIC_TEST :  production NEXT_PUBLIC test
----------------CLIENT ENVIRONMENT VARIABLES TEST----------------
process.env.NODE_ENV :  production
process.env.TEST :  undefined
process.env.NEXT_PUBLIC_TEST :  production NEXT_PUBLIC test

 

npm run start를 하면 위와 같이 .env.production 버전으로 셋팅되는 것을 알 수 있다.

 

.env.production.local

이제 .env.production.local을 아래와 같이 만들어 보자.

 

TEST=production local test
NEXT_PUBLIC_TEST=production NEXT_PUBLIC local test

 

다시 npm run build  npm run start 시 consle.log는 아래와 같다.  

 

----------------SERVER ENVIRONMENT VARIABLES TEST----------------
process.env.NODE_ENV :  production
process.env.TEST :  production local test
process.env.NEXT_PUBLIC_TEST :  production NEXT_PUBLIC local test
----------------CLIENT ENVIRONMENT VARIABLES TEST----------------
process.env.NODE_ENV :  production
process.env.TEST :  undefined
process.env.NEXT_PUBLIC_TEST :  production NEXT_PUBLIC local test

 

.env.production.local .env.production를 보다 우선시 되 settings되는 것을 알 수 있다.

 

 

추가 실무 custom 셋팅

추가적으로 nodejs 실행단계에서 port 변경 setting과 development와 production 외의 QA 환경 setting에 대한 설명도 추가해 보겠다. package.json의 스크립트부터 보면서 설명해보겠다.

  "scripts": {
    "qa:local": "env-cmd -f .env.qa.local next dev -p 3030",
    "qa:build": "env-cmd -f .env.qa next build",
    "qa:start": "env-cmd -f .env.qa next start -p 3030",
    "live:local": "env-cmd -f .env.live.local next -p 3030",
    "live:build": "env-cmd -f .env.live next build",
    "live:start": "env-cmd -f .env.live next start -p 3030",
  },

 

qa 부분을 설명하면서 진행해 보겠다.

"qa:local": "env-cmd -f .env.qa.local next dev -p 3030"
  • npm run qa:local 이라고 명령어를 치면, 실행된다.
  • env-cmd를 사용하기 위해 npm install env-cmd 설치가 필요하다.
  • -f .env.qa.local은 .env.qa.local 파일을 사용하겠다는 명령어이다.
  •  next dev는 NODE_ENV를 development 환경으로 실행하겠다는 뜻이다.
  • -p 3030은 3030 port로 접속이 가능하게 만든다는 말이다.

 

"qa:build": "env-cmd -f .env.qa next build",
"qa:start": "env-cmd -f .env.qa next start -p 3030",
  • npm run qa:build는 빌드 명령어이다.
  • npm run qa:start는 빌드된 파일을 실행하는 명령어이다.
  • NONE_ENV는 deployment 환경으로 실행된다.
  • 배포시 .env.qa파일을 사용하는 명령어이다.
  • 접속은 3030포트로 접속이 된다.

 

 

 

 

4. script에서 환경 변수 추가하기

staging은 기본적으로 nextjs에서 자동 제공을 하지 않는다. 따라서 관련 추가 setting이 필요하다. 아래와 같은 방식을 통해 개발/배포 환경을 제외한 다른 방법에 대한 환경변수 setting이 가능하다.

 

아래의 명령어를 실행하여 cross-env 모듈을 사용하여 환경변수를 설정하는 것이 좋다.

$ npm i cross-env

 

설치 후에 아래와 같이 pakage.json에서 사용가능하다.

  ```
  @사용법
  cross-env 환경변수1=값 환경변수2=값 실행명령어
  ```
"scripts": {
  "local": "cross-env NEXT_PUBLIC_API_URL=localhost next dev",
  "build": "cross-env NEXT_PUBLIC_API_URL=999.99.99.99 next build"
},

 

리액트에서 .env 환경 설정 시 변수명에 NEXT_PUBLIC_이라고 앞에 붙여줘야 인식을 한다. 붙이지 않으면 무시한다. 위의 방식으로 하면 단점은 환경변수가 노출된다는 치명적인 단점이 있다.

 

 

강제로 .env파일을 지정하는 방법도 있다. 기본적으로  $ npm i env-cmd 를 설치해야한다.

"scripts": {
    "start": "next start",
    "build": "env-cmd -f .env next build",
  },
  • env-cmd -f .env는 우선순위가 높은 .env.production가 아닌 .env 를 실행하도록 지정한 것이다.
  • -f를 안적으면 .env 파일을 찾을 수 없다고 나오니 조심하자.

 

"scripts": {
    "start": "next start",
    "build": "env-cmd -f .env.production next build",
  },
  • $ npm run build 실행 시 .env.production이 적용된다.

 

staging 세팅과 yarn을 활용한 세팅은 아래와 같다고 할 수 있다.

"build:staging": "env-cmd -f .env.staging yarn build && yarn start"

 

 

 

5. nextjs env 변수 설정

초창기 nextjs(매우 옛날..)에서는 환경 변수를 브라우저에서 조회하는 것이 불가능했다. 최근에는 가능하다! 브라우저에서 환경변수를 사용하기 위해서는 NEXT_PUBLIC_를 접두사로 넣어주어야 한다. 조금 더 쉽게 말하면, SSR이 진행되는 부분(getStaticProps, getserversideprops, api 폴더 내부)에서는 상관이 없지만, react 내부 브라우저에서는 접두사를 넣어주지 않으면, 환경 변수가 undefined로 불러올 수 없으니 주의해야한다.

 

변수설정 가능

# .env
HOSTNAME=localhost
PORT=8080
HOST=http://$HOSTNAME:$PORT

위와 같이 $을 사용해서 변수 설정과 변수 사용이 가능하다.

 

 

정리하면, next.config.js 환경과 .env를 활용한 변수 settings을 배웠다. 우리는 현업에서는 환경분리가 필요하기 때문에 .env를 많이 활용한다. 하지만, next.config.js로 핸들링이 필요한 부분도 있기 때문에 두 가지 방법으로 각각 토이프로젝트를 만들고 보고, 장단점을 익혀보는 것도 좋은 방법이라 생각이 든다.

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함